1
/*********************************************************
2
* Copyright (C) 2010 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Helper functions for DnDCPMsgV4.
25
#include "vm_assert.h"
27
#include "dndClipboard.h"
28
#include "dndCPMsgV4.h"
33
* Check if received packet is valid or not.
36
* @param[in] packetSize
38
* @return TRUE if the packet is valid, FALSE otherwise.
42
DnDCPMsgV4IsPacketValid(const uint8 *packet,
45
DnDCPMsgHdrV4 *msgHdr = NULL;
48
if (packetSize < DND_CP_MSG_HEADERSIZE_V4) {
52
msgHdr = (DnDCPMsgHdrV4 *)packet;
54
/* Payload size is not valid. */
55
if (msgHdr->payloadSize > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
59
/* Binary size is not valid. */
60
if (msgHdr->binarySize > DND_CP_MSG_MAX_BINARY_SIZE_V4) {
64
/* Payload size is more than binary size. */
65
if (msgHdr->payloadOffset + msgHdr->payloadSize > msgHdr->binarySize) {
74
* Initialize the DnDCPMsgV4.
76
* @param[in/out] msg DnDCPMsgV4 to be initialized.
80
DnDCPMsgV4_Init(DnDCPMsgV4 *msg)
83
memset(msg, 0, sizeof(DnDCPMsgV4));
87
* Destroy the DnDCPMsgV4.
89
* @param[in/out] msg DnDCPMsgV4 to be destroyed.
93
DnDCPMsgV4_Destroy(DnDCPMsgV4 *msg)
103
* Check the packet type.
106
* @param[in] packetSize
108
* @return DnDCPMsgPacketType
111
DnDCPMsgPacketType DnDCPMsgV4_GetPacketType(const uint8 *packet,
114
DnDCPMsgHdrV4 *msgHdr = NULL;
117
if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
118
return DND_CP_MSG_PACKET_TYPE_INVALID;
121
msgHdr = (DnDCPMsgHdrV4 *)packet;
122
if (msgHdr->binarySize <= DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
123
return DND_CP_MSG_PACKET_TYPE_SINGLE;
126
if (0 == msgHdr->payloadOffset) {
127
return DND_CP_MSG_PACKET_TYPE_MULTIPLE_NEW;
130
if (msgHdr->payloadOffset + msgHdr->payloadSize == msgHdr->binarySize) {
131
return DND_CP_MSG_PACKET_TYPE_MULTIPLE_END;
134
return DND_CP_MSG_PACKET_TYPE_MULTIPLE_CONTINUE;
139
* Serialize the msg to packet.
141
* @param[in/out] msg DnDCPMsgV4 to be serialized from.
142
* @param[out] packet DnDCPMsgV4 to be serialized to.
143
* @param[out] packetSize serialized packet size.
145
* @return TRUE if succeed, FALSE otherwise.
149
DnDCPMsgV4_Serialize(DnDCPMsgV4 *msg,
153
size_t payloadSize = 0;
158
ASSERT(msg->hdr.binarySize >= msg->hdr.payloadOffset);
160
if (msg->hdr.binarySize <= DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
162
* One single packet is enough for the message. For short message, the
163
* payloadOffset should always be 0.
165
ASSERT(msg->hdr.payloadOffset == 0);
166
payloadSize = msg->hdr.binarySize;
168
/* For big message, payloadOffset means binary size we already sent out. */
169
if (msg->hdr.binarySize - msg->hdr.payloadOffset > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
170
payloadSize = DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4;
172
payloadSize = msg->hdr.binarySize - msg->hdr.payloadOffset;
176
*packetSize = DND_CP_MSG_HEADERSIZE_V4 + payloadSize;
177
*packet = Util_SafeMalloc(*packetSize);
178
memcpy(*packet, msg, DND_CP_MSG_HEADERSIZE_V4);
179
if (payloadSize > 0) {
180
memcpy(*packet + DND_CP_MSG_HEADERSIZE_V4,
181
msg->binary + msg->hdr.payloadOffset,
184
((DnDCPMsgHdrV4 *)(*packet))->payloadSize = payloadSize;
185
/* Next DnDCPMsgV4_Serialize will use this payloadOffset to get unsent binary. */
186
msg->hdr.payloadOffset += payloadSize;
192
* Unserialize the packet to DnDCPMsgV4 for short messsage.
194
* @param[in/out] msg DnDCPMsgV4 to be unserialized to.
195
* @param[in] packet DnDCPMsgV4 to be unserialized from.
196
* @param[in] packetSize
198
* @return TRUE if succeed, FALSE otherwise.
202
DnDCPMsgV4_UnserializeSingle(DnDCPMsgV4 *msg,
206
DnDCPMsgHdrV4 *msgHdr = NULL;
210
if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
214
msgHdr = (DnDCPMsgHdrV4 *)packet;
216
/* Offset should be 0 for short message. */
217
if (msgHdr->payloadOffset != 0) {
221
memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4);
223
if (msg->hdr.binarySize != 0) {
224
msg->binary = Util_SafeMalloc(msg->hdr.binarySize);
227
packet + DND_CP_MSG_HEADERSIZE_V4,
228
msg->hdr.payloadSize);
229
msg->hdr.payloadOffset = msg->hdr.payloadSize;
236
* Unserialize the packet to DnDCPMsgV4 for big messsage.
238
* @param[in/out] msg DnDCPMsgV4 to be unserialized to.
239
* @param[in] packet DnDCPMsgV4 to be unserialized from.
240
* @param[in] packetSize
242
* @return TRUE if succeed, FALSE otherwise.
246
DnDCPMsgV4_UnserializeMultiple(DnDCPMsgV4 *msg,
250
DnDCPMsgHdrV4 *msgHdr = NULL;
254
if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
258
msgHdr = (DnDCPMsgHdrV4 *)packet;
261
* For each session, there is at most 1 big message. If the received
262
* sessionId is different with buffered one, the received packet is for
263
* another another new message. Destroy old buffered message.
266
msg->hdr.sessionId != msgHdr->sessionId) {
267
DnDCPMsgV4_Destroy(msg);
270
/* Offset should be 0 for new message. */
271
if (NULL == msg->binary && msgHdr->payloadOffset != 0) {
275
/* For existing buffered message, the payload offset should match. */
277
msg->hdr.sessionId == msgHdr->sessionId &&
278
msg->hdr.payloadOffset != msgHdr->payloadOffset) {
282
if (NULL == msg->binary) {
283
memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4);
284
msg->binary = Util_SafeMalloc(msg->hdr.binarySize);
287
/* msg->hdr.payloadOffset is used as received binary size. */
288
memcpy(msg->binary + msg->hdr.payloadOffset,
289
packet + DND_CP_MSG_HEADERSIZE_V4,
290
msgHdr->payloadSize);
291
msg->hdr.payloadOffset += msgHdr->payloadSize;
297
* Map a command to a string.
299
* @param[in] cmd the DnD V4 command
301
* @return a valid command string if the command is valid, "invalid command"
306
DnDCPMsgV4_LookupCmd(uint32 cmd)
308
static const struct {
311
} cmdStringTable[] = {
312
{ DNDCP_CMD_PING, "DNDCP_CMD_PING" },
313
{ DNDCP_CMD_PING_REPLY, "DNDCP_CMD_PING_REPLY" },
314
{ DNDCP_CMD_REQUEST_NEXT, "DNDCP_CMD_REQUEST_NEXT" },
315
{ DNDCP_CMP_REPLY, "DNDCP_CMP_REPLY" },
316
{ DNDCP_CMD_TEST_BIG_BINARY, "DNDCP_CMD_TEST_BIG_BINARY" },
317
{ DNDCP_CMD_TEST_BIG_BINARY_REPLY, "DNDCP_CMD_TEST_BIG_BINARY_REPLY" },
319
{ DND_CMD_DEST_DRAG_ENTER, "DND_CMD_DEST_DRAG_ENTER" },
320
{ DND_CMD_DEST_DRAG_ENTER_REPLY, "DND_CMD_DEST_DRAG_ENTER_REPLY" },
321
{ DND_CMD_DEST_SEND_CLIPBOARD, "DND_CMD_DEST_SEND_CLIPBOARD" },
322
{ DND_CMD_DEST_DRAG_LEAVE, "DND_CMD_DEST_DRAG_LEAVE" },
323
{ DND_CMD_DEST_DROP, "DND_CMD_DEST_DROP" },
324
{ DND_CMD_SRC_DRAG_BEGIN, "DND_CMD_SRC_DRAG_BEGIN" },
325
{ DND_CMD_SRC_DRAG_BEGIN_DONE, "DND_CMD_SRC_DRAG_BEGIN_DONE" },
326
{ DND_CMD_SRC_DROP, "DND_CMD_SRC_DROP" },
327
{ DND_CMD_SRC_DROP_DONE, "DND_CMD_SRC_DROP_DONE" },
328
{ DND_CMD_SRC_CANCEL, "DND_CMD_SRC_CANCEL" },
329
{ DND_CMD_PRIV_DRAG_ENTER, "DND_CMD_PRIV_DRAG_ENTER" },
330
{ DND_CMD_PRIV_DRAG_LEAVE, "DND_CMD_PRIV_DRAG_LEAVE" },
331
{ DND_CMD_PRIV_DROP, "DND_CMD_PRIV_DROP" },
332
{ DND_CMD_MOVE_MOUSE, "DND_CMD_MOVE_MOUSE" },
333
{ DND_CMD_UPDATE_FEEDBACK, "DND_CMD_UPDATE_FEEDBACK" },
334
{ DND_CMD_REQUEST_FILES, "DND_CMD_REQUEST_FILES" },
335
{ DND_CMD_GET_FILES_DONE, "DND_CMD_GET_FILES_DONE" },
336
{ DND_CMD_SEND_FILES_DONE, "DND_CMD_SEND_FILES_DONE" },
337
{ DND_CMD_QUERY_EXITING, "DND_CMD_QUERY_EXITING" },
338
{ DND_CMD_DRAG_NOT_PENDING, "DND_CMD_DRAG_NOT_PENDING" },
339
{ DND_CMD_UPDATE_UNITY_DET_WND, "DND_CMD_UPDATE_UNITY_DET_WND" },
341
{ CP_CMD_REQUEST_CLIPBOARD, "CP_CMD_REQUEST_CLIPBOARD" },
342
{ CP_CMD_REQUEST_FILES, "CP_CMD_REQUEST_FILES" },
343
{ CP_CMD_RECV_CLIPBOARD, "CP_CMD_RECV_CLIPBOARD" },
344
{ CP_CMD_SEND_CLIPBOARD, "CP_CMD_SEND_CLIPBOARD" },
345
{ CP_CMD_GET_FILES_DONE, "CP_CMD_GET_FILES_DONE" },
346
{ CP_CMD_SEND_FILES_DONE, "CP_CMD_SEND_FILES_DONE" },
348
{ FT_CMD_HGFS_REQUEST, "FT_CMD_HGFS_REQUEST" },
349
{ FT_CMD_HGFS_REPLY, "FT_CMD_HGFS_REPLY" },
350
{ FT_CMD_UPDATE_PROGRESS, "FT_CMD_UPDATE_PROGRESS" },
351
{ FT_CMD_PROGRESS_REPLY, "FT_CMD_PROGRESS_REPLY" },
355
for (i = 0; i < ARRAYSIZE(cmdStringTable); i++) {
356
if (cmdStringTable[i].cmd == cmd) {
357
return cmdStringTable[i].cmdStr;
360
return "invalid command";