~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/dndGuest/rpcV3Util.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @rpcV3Util.cpp --
 
21
 *
 
22
 * Implementation of common utility object for DnD/CP version 3 rpc object.
 
23
 * It is shared by vmx and guest implementation. Some common utilities
 
24
 * including
 
25
 * *packet marshalling/un-marshalling
 
26
 * *big buffer support
 
27
 * are implemented here.
 
28
 */
 
29
 
 
30
 
 
31
#include "rpcV3Util.hpp"
 
32
 
 
33
extern "C" {
 
34
#ifdef VMX86_TOOLS
 
35
   #include "debug.h"
 
36
   #define LOG(level, msg) (Debug msg)
 
37
#else
 
38
   #define LOGLEVEL_MODULE dnd
 
39
   #include "loglevel_user.h"
 
40
#endif
 
41
 
 
42
   #include "dndClipboard.h"
 
43
   #include "util.h"
 
44
   #include "dndMsg.h"
 
45
   #include "hostinfo.h"
 
46
}
 
47
 
 
48
 
 
49
 
 
50
/**
 
51
 * Constructor.
 
52
 */
 
53
 
 
54
RpcV3Util::RpcV3Util(void)
 
55
   : mVersionMajor(3),
 
56
     mVersionMinor(0),
 
57
     mSeqNum(1)
 
58
{
 
59
   mSendBuf.buffer = NULL;
 
60
   mRecvBuf.buffer = NULL;
 
61
   DnD_TransportBufReset(&mSendBuf);
 
62
   DnD_TransportBufReset(&mRecvBuf);
 
63
}
 
64
 
 
65
 
 
66
/**
 
67
 * Destructor.
 
68
 */
 
69
 
 
70
RpcV3Util::~RpcV3Util(void)
 
71
{
 
72
   free(mSendBuf.buffer);
 
73
   free(mRecvBuf.buffer);
 
74
}
 
75
 
 
76
 
 
77
/**
 
78
 * Initialize the RpcV3Util object. All owner should call this first before
 
79
 * calling any other utility function.
 
80
 *
 
81
 * @param[in] rpc the owner of this utility object
 
82
 * @param[in] msgType the type of message (DnD/CP/FT)
 
83
 * @param[in] msgSrc source of the message (host/guest/controller)
 
84
 */
 
85
 
 
86
void
 
87
RpcV3Util::Init(RpcBase *rpc)
 
88
{
 
89
   ASSERT(rpc);
 
90
   mRpc = rpc;
 
91
}
 
92
 
 
93
 
 
94
/**
 
95
 * Serialize command, then send the message.
 
96
 *
 
97
 * @param[in] cmd version 3 command
 
98
 *
 
99
 * @return true on success, false otherwise.
 
100
 */
 
101
 
 
102
bool
 
103
RpcV3Util::SendMsg(uint32 cmd)
 
104
{
 
105
   DnDMsg msg;
 
106
   bool ret = false;
 
107
 
 
108
   DnDMsg_Init(&msg);
 
109
   DnDMsg_SetCmd(&msg, cmd);
 
110
   ret = SendMsg(&msg);
 
111
   DnDMsg_Destroy(&msg);
 
112
 
 
113
   return ret;
 
114
}
 
115
 
 
116
 
 
117
/**
 
118
 * Serialize the clipboard item if there is one, then send the message to
 
119
 * destId.
 
120
 *
 
121
 * @param[in] cmd version 3 command
 
122
 * @param[in] clip the clipboard item.
 
123
 *
 
124
 * @return true on success, false otherwise.
 
125
 */
 
126
 
 
127
bool
 
128
RpcV3Util::SendMsg(uint32 cmd,
 
129
                   const CPClipboard *clip)
 
130
{
 
131
   DnDMsg msg;
 
132
   DynBuf buf;
 
133
   bool ret = false;
 
134
 
 
135
   DnDMsg_Init(&msg);
 
136
   DynBuf_Init(&buf);
 
137
 
 
138
   /* Serialize clip and output into buf. */
 
139
   if (!CPClipboard_Serialize(clip, &buf)) {
 
140
      LOG(0, ("%s: CPClipboard_Serialize failed.\n", __FUNCTION__));
 
141
      goto exit;
 
142
   }
 
143
 
 
144
   /* Construct msg with both cmd CP_HG_SET_CLIPBOARD and buf. */
 
145
   DnDMsg_SetCmd(&msg, cmd);
 
146
   if (!DnDMsg_AppendArg(&msg, DynBuf_Get(&buf), DynBuf_GetSize(&buf))) {
 
147
      LOG(0, ("%s: DnDMsg_AppendData failed.\n", __FUNCTION__));
 
148
      goto exit;
 
149
   }
 
150
 
 
151
   ret = SendMsg(&msg);
 
152
 
 
153
exit:
 
154
   DynBuf_Destroy(&buf);
 
155
   DnDMsg_Destroy(&msg);
 
156
   return ret;
 
157
}
 
158
 
 
159
 
 
160
/**
 
161
 * Serialize command with mouse position, and send the message.
 
162
 *
 
163
 * @param[in] cmd version 3 command
 
164
 * @param[in] x mouse position x.
 
165
 * @param[in] y mouse position y.
 
166
 *
 
167
 * @return true on success, false otherwise.
 
168
 */
 
169
 
 
170
bool
 
171
RpcV3Util::SendMsg(uint32 cmd,
 
172
                   int32 x,
 
173
                   int32 y)
 
174
{
 
175
   bool ret = false;
 
176
 
 
177
   DnDMsg msg;
 
178
 
 
179
   DnDMsg_Init(&msg);
 
180
 
 
181
   DnDMsg_SetCmd(&msg, cmd);
 
182
 
 
183
   if (!DnDMsg_AppendArg(&msg, &x, sizeof x) ||
 
184
       !DnDMsg_AppendArg(&msg, &y, sizeof y)) {
 
185
      LOG(0, ("%s: DnDMsg_AppendData failed.\n", __FUNCTION__));
 
186
      goto exit;
 
187
   }
 
188
 
 
189
   ret = SendMsg(&msg);
 
190
 
 
191
exit:
 
192
   DnDMsg_Destroy(&msg);
 
193
   return ret;
 
194
}
 
195
 
 
196
 
 
197
/**
 
198
 * Serialize and send the message.
 
199
 *
 
200
 * @param[in] msg the message to be serialized and sent.
 
201
 *
 
202
 * @return true on success, false otherwise.
 
203
 */
 
204
 
 
205
bool
 
206
RpcV3Util::SendMsg(const DnDMsg *msg)
 
207
{
 
208
   DynBuf buf;
 
209
   bool ret = false;
 
210
 
 
211
   DynBuf_Init(&buf);
 
212
 
 
213
   /* Serialize msg and output to buf. */
 
214
   if (!DnDMsg_Serialize((DnDMsg *)msg, &buf)) {
 
215
      LOG(0, ("%s: DnDMsg_Serialize failed.\n", __FUNCTION__));
 
216
      goto exit;
 
217
   }
 
218
 
 
219
   ret = SendMsg((uint8 *)DynBuf_Get(&buf), DynBuf_GetSize(&buf));
 
220
 
 
221
exit:
 
222
   DynBuf_Destroy(&buf);
 
223
   return ret;
 
224
}
 
225
 
 
226
 
 
227
/**
 
228
 * Serialize the message and send it to destId.
 
229
 *
 
230
 * @param[in] binary
 
231
 * @param[in] binarySize
 
232
 *
 
233
 * @return true on success, false otherwise.
 
234
 */
 
235
 
 
236
bool
 
237
RpcV3Util::SendMsg(const uint8 *binary,
 
238
                   uint32 binarySize)
 
239
{
 
240
   DnDTransportPacketHeader *packet = NULL;
 
241
   size_t packetSize;
 
242
   bool ret = FALSE;
 
243
 
 
244
   if (binarySize > DNDMSG_MAX_ARGSZ) {
 
245
      LOG(1, ("%s: message is too big, quit.\n", __FUNCTION__));
 
246
      return false;
 
247
   }
 
248
 
 
249
   LOG(4, ("%s: got message, size %d.\n", __FUNCTION__, binarySize));
 
250
 
 
251
   if (binarySize <= DND_MAX_TRANSPORT_PACKET_PAYLOAD_SIZE) {
 
252
      /*
 
253
       * It is a small size message, so it is not needed to buffer it. Just
 
254
       * put message into a packet and send it.
 
255
       */
 
256
      packetSize = DnD_TransportMsgToPacket((uint8 *)binary, binarySize,
 
257
                                            mSeqNum, &packet);
 
258
   } else {
 
259
      /*
 
260
       * It is a big size message. First buffer it and send it with multiple
 
261
       * packets.
 
262
       */
 
263
      if (mSendBuf.buffer) {
 
264
         /*
 
265
          * There is a pending big size message. If there is no update time more than
 
266
          * DND_MAX_TRANSPORT_LATENCY_TIME, remove old message and send new message.
 
267
          * Otherwise ignore this message.
 
268
          */
 
269
         VmTimeType curTime;
 
270
 
 
271
         Hostinfo_GetTimeOfDay(&curTime);
 
272
 
 
273
         if ((curTime - mSendBuf.lastUpdateTime) < DND_MAX_TRANSPORT_LATENCY_TIME) {
 
274
            LOG(1, ("%s: got a big buffer, but there is another pending one, drop it\n",
 
275
                    __FUNCTION__));
 
276
            return false;
 
277
         }
 
278
      }
 
279
      DnD_TransportBufInit(&mSendBuf, (uint8 *)binary, binarySize, mSeqNum);
 
280
      packetSize = DnD_TransportBufGetPacket(&mSendBuf, &packet);
 
281
   }
 
282
 
 
283
   /* Increase sequence number for next message. */
 
284
   mSeqNum++;
 
285
   if (packetSize) {
 
286
      ret = mRpc->SendPacket(0, (const uint8 *)packet, packetSize);
 
287
   }
 
288
   free(packet);
 
289
   return ret;
 
290
}
 
291
 
 
292
 
 
293
 
 
294
/**
 
295
 * Callback from transport layer after received a packet from srcId.
 
296
 *
 
297
 * @param[in] srcId addressId where the packet is from
 
298
 * @param[in] packet
 
299
 * @param[in] packetSize
 
300
 */
 
301
 
 
302
void
 
303
RpcV3Util::OnRecvPacket(uint32 srcId,
 
304
                        const uint8 *packet,
 
305
                        size_t packetSize)
 
306
{
 
307
   DnDTransportPacketHeader *packetV3 = (DnDTransportPacketHeader *)packet;
 
308
   ASSERT(packetV3);
 
309
   if (packetSize <= 0 ||
 
310
       packetSize != (packetV3->payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE) ||
 
311
       packetSize > DND_MAX_TRANSPORT_PACKET_SIZE) {
 
312
      LOG(0, ("%s: Received invalid data.\n", __FUNCTION__));
 
313
      return;
 
314
   }
 
315
 
 
316
   switch (packetV3->type) {
 
317
   case DND_TRANSPORT_PACKET_TYPE_SINGLE:
 
318
      if (packetV3->payloadSize != packetV3->totalSize) {
 
319
         LOG(0, ("%s: received invalid packet.\n", __FUNCTION__));
 
320
         return;
 
321
      }
 
322
      /* This is a single packet. Forward to rpc layer for further processing. */
 
323
      mRpc->HandleMsg(NULL, packetV3->payload, packetV3->payloadSize);
 
324
      break;
 
325
   case DND_TRANSPORT_PACKET_TYPE_REQUEST:
 
326
      {
 
327
         /* Peer is asking for next packet. */
 
328
         DnDTransportPacketHeader *replyPacket = NULL;
 
329
         size_t replyPacketSize;
 
330
 
 
331
         if (packetV3->payloadSize ||
 
332
             packetV3->seqNum != mSendBuf.seqNum ||
 
333
             packetV3->offset != mSendBuf.offset) {
 
334
            LOG(0, ("%s: received packet does not match local buffer.\n", __FUNCTION__));
 
335
            return;
 
336
         }
 
337
 
 
338
         replyPacketSize = DnD_TransportBufGetPacket(&mSendBuf, &replyPacket);
 
339
 
 
340
         if (!replyPacketSize) {
 
341
            /*
 
342
             * Not needed to reset mSendBuf because DnD_TransportBufGetPacket already
 
343
             * did that.
 
344
             */
 
345
            LOG(0, ("%s: DnD_TransportBufGetPacket failed.\n", __FUNCTION__));
 
346
            return;
 
347
         }
 
348
 
 
349
         if (!mRpc->SendPacket(0, (const uint8 *)replyPacket, replyPacketSize) ||
 
350
             mSendBuf.offset == mSendBuf.totalSize) {
 
351
            /* Reset mSendBuf if whole buffer is sent or there is any error. */
 
352
            DnD_TransportBufReset(&mSendBuf);
 
353
         }
 
354
 
 
355
         free(replyPacket);
 
356
 
 
357
         break;
 
358
      }
 
359
   case DND_TRANSPORT_PACKET_TYPE_PAYLOAD:
 
360
      /* Received next packet for big binary buffer. */
 
361
      if (!DnD_TransportBufAppendPacket(&mRecvBuf, packetV3, packetSize)) {
 
362
         LOG(0, ("%s: DnD_TransportBufAppendPacket failed.\n", __FUNCTION__));
 
363
         return;
 
364
      }
 
365
 
 
366
      if (mRecvBuf.offset == mRecvBuf.totalSize) {
 
367
         /*
 
368
          * Received all packets for the messge, forward it to rpc layer for
 
369
          * further processing.
 
370
          */
 
371
         mRpc->HandleMsg(NULL, mRecvBuf.buffer, mRecvBuf.totalSize);
 
372
         DnD_TransportBufReset(&mRecvBuf);
 
373
      } else {
 
374
         /* Send request for next packet. */
 
375
         DnDTransportPacketHeader *replyPacket = NULL;
 
376
         size_t replyPacketSize;
 
377
 
 
378
         replyPacketSize = DnD_TransportReqPacket(&mRecvBuf, &replyPacket);
 
379
 
 
380
         if (!replyPacketSize) {
 
381
            LOG(0, ("%s: DnD_TransportReqPacket failed.\n", __FUNCTION__));
 
382
            return;
 
383
         }
 
384
 
 
385
         if (!mRpc->SendPacket(0, (const uint8 *)replyPacket, replyPacketSize)) {
 
386
            DnD_TransportBufReset(&mRecvBuf);
 
387
         }
 
388
         free(replyPacket);
 
389
      }
 
390
      break;
 
391
   default:
 
392
      LOG(0, ("%s: unknown packet.\n", __FUNCTION__));
 
393
      break;
 
394
   }
 
395
}
 
396
 
 
397