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
*********************************************************/
20
* @dndCPTransportGuestRpc.cpp --
22
* GuestRpc implementation of the dndCPTransport interface.
24
* XXX Move this to a common lib or source location.
27
#include "dndCPTransportGuestRpc.hpp"
39
#define LOG(level, msg) (Debug msg)
42
#include "guest_rpc.h"
44
#define LOGLEVEL_MODULE dnd
45
#include "loglevel_user.h"
51
* Received a message from guestRpc. Forward the message to transport class.
53
* @param[out] result reply string.
54
* @param[out] resultLen reply string length in byte.
55
* @param[in] name guestRpc cmd name.
56
* @param[in] args argument list.
57
* @param[in] argsSize argument list size in byte.
58
* @param[in] clientData callback client data.
60
* @return TRUE if success, FALSE otherwise.
64
RecvMsgCB(RpcInData *data) // IN/OUT
66
LOG(4, ("%s: receiving\n", __FUNCTION__));
68
const uint8 *packet = (const uint8 *)(data->args + 1);
69
size_t packetSize = data->argsSize - 1;
71
/* '- 1' is to ignore empty space between command and args. */
72
if ((data->argsSize - 1) <= 0) {
73
Debug("%s: invalid argsSize\n", __FUNCTION__);
74
return RPCIN_SETRETVALS(data, "invalid arg size", FALSE);
76
GuestRpcCBCtx *ctx = (GuestRpcCBCtx *)data->clientData;
79
* Received a message from guestRpc. Forward the message to transport class.
81
* @param[in] clientData callback client data.
82
* @param[ignored] channelId
83
* @param[in] args argument list.
84
* @param[in] argsSize argument list size in byte.
85
* @param[out] result reply string.
86
* @param[out] resultSize reply string length in byte.
88
* @return TRUE if success, FALSE otherwise.
92
RecvMsgCB(void *clientData,
94
const unsigned char *args,
96
unsigned char **result,
99
const uint8 *packet = args;
100
size_t packetSize = argsSize;
101
GuestRpcCBCtx *ctx = (GuestRpcCBCtx *)clientData;
105
ASSERT(ctx->transport);
106
ctx->transport->OnRecvPacket(ctx->type, packet, packetSize);
109
return RPCIN_SETRETVALS(data, "", TRUE);
111
return GuestRpc_SetRetVals(result, resultSize, (char *)"", TRUE);
120
TransportGuestRpcTables::TransportGuestRpcTables(void)
122
for (int i = 0; i < TRANSPORT_INTERFACE_MAX; i++) {
124
mCmdStrTable[i] = NULL;
125
mDisableStrTable[i] = NULL;
129
mCmdTable[i] = GUESTRPC_CMD_MAX;
131
mCmdTable[TRANSPORT_GUEST_CONTROLLER_DND] = GUESTRPC_CMD_DND_TRANSPORT;
132
mCmdTable[TRANSPORT_GUEST_CONTROLLER_CP] = GUESTRPC_CMD_COPYPASTE_TRANSPORT;
135
mCmdStrTable[TRANSPORT_GUEST_CONTROLLER_DND] = (char *)GUEST_RPC_CMD_STR_DND;
136
mCmdStrTable[TRANSPORT_GUEST_CONTROLLER_CP] = (char *)GUEST_RPC_CMD_STR_CP;
138
mDisableStrTable[TRANSPORT_GUEST_CONTROLLER_DND] = (char *)GUEST_RPC_DND_DISABLE;
139
mDisableStrTable[TRANSPORT_GUEST_CONTROLLER_CP] = (char *)GUEST_RPC_CP_DISABLE;
147
TransportGuestRpcTables::~TransportGuestRpcTables(void)
153
* Get an rpc object by interface type.
155
* @param[in] type transport interface type
157
* @return a registered rpc, or NULL if the rpc for the type is not registered.
161
TransportGuestRpcTables::GetRpc(TransportInterfaceType type)
163
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
164
type == TRANSPORT_GUEST_CONTROLLER_CP ||
165
type == TRANSPORT_GUEST_CONTROLLER_FT);
166
return mRpcList[type];
171
* Add a rpc into rpc table.
173
* @param[in] type transport interface type
174
* @param[in] rpc rpc which is added into the table.
178
TransportGuestRpcTables::SetRpc(TransportInterfaceType type,
181
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
182
type == TRANSPORT_GUEST_CONTROLLER_CP ||
183
type == TRANSPORT_GUEST_CONTROLLER_FT);
184
mRpcList[type] = rpc;
190
* Get a guestRpc cmd by interface type.
192
* @param[in] type transport interface type
194
* @return a guestRpc cmd.
198
TransportGuestRpcTables::GetCmd(TransportInterfaceType type)
200
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
201
type == TRANSPORT_GUEST_CONTROLLER_CP ||
202
type == TRANSPORT_GUEST_CONTROLLER_FT);
204
return mCmdTable[type];
210
* Get a guestRpc cmd string by interface type.
212
* @param[in] type transport interface type
214
* @return a guestRpc cmd string.
218
TransportGuestRpcTables::GetCmdStr(TransportInterfaceType type)
220
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
221
type == TRANSPORT_GUEST_CONTROLLER_CP ||
222
type == TRANSPORT_GUEST_CONTROLLER_FT);
224
return mCmdStrTable[type];
229
* Get a guestRpc cmd disable string by interface type.
231
* @param[in] type transport interface type
233
* @return a guestRpc cmd disable string.
237
TransportGuestRpcTables::GetDisableStr(TransportInterfaceType type)
239
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
240
type == TRANSPORT_GUEST_CONTROLLER_CP ||
241
type == TRANSPORT_GUEST_CONTROLLER_FT);
243
return mDisableStrTable[type];
254
DnDCPTransportGuestRpc::DnDCPTransportGuestRpc(RpcChannel *chan)
257
DnDCPTransportGuestRpc::DnDCPTransportGuestRpc(void)
260
for (int i = 0; i < TRANSPORT_INTERFACE_MAX; i++) {
261
mCBCtx[i].transport = this;
262
mCBCtx[i].type = (TransportInterfaceType)i;
268
* Register a rpc callback to an interface.
270
* @param[in] rpc rpc which is listening to the message.
271
* @param[in] type the interface type rpc is listening to.
273
* @return true on success, false otherwise.
277
DnDCPTransportGuestRpc::RegisterRpc(RpcBase *rpc,
278
TransportInterfaceType type)
280
if (mTables.GetRpc(type)) {
281
LOG(0, ("%s: the type %d is already registered\n", __FUNCTION__, type));
284
const char *cmdStr = (const char *)mTables.GetCmdStr(type);
285
const char *disableStr = mTables.GetDisableStr(type);
287
if (!cmdStr || !disableStr) {
288
LOG(0, ("%s: can not find valid cmd for %d, cmdStr %s disableStr %s\n", __FUNCTION__, type, (cmdStr ? cmdStr : "NULL"), (disableStr ? disableStr : "NULL")));
293
ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
294
type == TRANSPORT_GUEST_CONTROLLER_CP ||
295
type == TRANSPORT_GUEST_CONTROLLER_FT);
296
LOG(4, ("%s: for %s\n", __FUNCTION__, cmdStr));
300
mRpcChanCBList[type].name = cmdStr;
301
mRpcChanCBList[type].callback = RecvMsgCB;
302
mRpcChanCBList[type].clientData = &mCBCtx[type];
303
mRpcChanCBList[type].xdrIn = NULL;
304
mRpcChanCBList[type].xdrOut = NULL;
305
mRpcChanCBList[type].xdrInSize = 0;
306
RpcChannel_RegisterCallback(mRpcChannel, &mRpcChanCBList[type]);
308
GuestRpc_RegisterCommand(mTables.GetCmd(type), disableStr,
309
(const unsigned char *)cmdStr, RecvMsgCB, &mCBCtx[type]);
311
mTables.SetRpc(type, rpc);
317
* Unregister a rpc callback.
319
* @param[in] type the interface type rpc is listening to.
321
* @return true on success, false otherwise.
325
DnDCPTransportGuestRpc::UnregisterRpc(TransportInterfaceType type)
327
if (!mTables.GetRpc(type)) {
328
LOG(0, ("%s: the type %d is not registered\n", __FUNCTION__, type));
333
RpcChannel_UnregisterCallback(mRpcChannel, &mRpcChanCBList[type]);
335
GuestRpc_UnregisterCommand(mTables.GetCmd(type));
337
mTables.SetRpc(type, NULL);
343
* Wrap the buffer into an rpc and send it to the peer.
345
* @param[ignored] destId destination address id
346
* @param[in] type transport interface type
347
* @param[in] data Payload buffer
348
* @param[in] dataSize Payload buffer size
350
* @return true on success, false otherwise.
354
DnDCPTransportGuestRpc::SendPacket(uint32 destId,
355
TransportInterfaceType type,
361
size_t nrWritten = 0;
362
const char *cmd = mTables.GetCmdStr(type);
366
LOG(0, ("%s: can not find valid cmd for %d\n", __FUNCTION__, type));
369
rpcSize = strlen(cmd) + 1 + length;
370
rpc = (char *)Util_SafeMalloc(rpcSize);
371
nrWritten = Str_Sprintf(rpc, rpcSize, "%s ", cmd);
374
ASSERT(nrWritten + length <= rpcSize);
375
memcpy(rpc + nrWritten, msg, length);
379
ret = (TRUE == RpcChannel_Send(mRpcChannel, rpc, rpcSize, NULL, NULL));
382
LOG(0, ("%s: failed to send msg to host\n", __FUNCTION__));
385
LOG(4, ("%s: sending [%s]\n", __FUNCTION__, rpc));
388
LOG(4, ("%s: sending\n", __FUNCTION__));
390
GuestRpc_SendWithTimeOut((const unsigned char *)TOOLS_DND_NAME,
391
(const unsigned char *)rpc, rpcSize,
392
GuestRpc_GenericCompletionRoutine, rpc,
394
LOG(4, ("%s: sending [%s]\n", __FUNCTION__, rpc));
402
* Callback after receiving a guestRpc message.
404
* @param[in] type transport interface type
405
* @param[in] packet Payload buffer
406
* @param[in] packetSize Payload buffer size
410
DnDCPTransportGuestRpc::OnRecvPacket(TransportInterfaceType type,
414
RpcBase *rpc = mTables.GetRpc(type);
416
LOG(0, ("%s: can not find valid rpc for %d\n", __FUNCTION__, type));
419
rpc->OnRecvPacket(DEFAULT_CONNECTION_ID, packet, packetSize);