/* Default maximun number of open nodes that have server locks. */
#define MAX_LOCKED_FILENODES 10
-
/* Maximum number of cached open nodes. */
static unsigned int maxCachedOpenNodes;
void *clientData);
static Bool HgfsServerSessionConnect(void *transportData,
HgfsServerChannelCallbacks *channelCbTable,
+ uint32 channelCapabililies,
void **clientData);
static void HgfsServerSessionDisconnect(void *clientData);
static void HgfsServerSessionClose(void *clientData);
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerSetSessionCapability --
+ *
+ * Sets session capability for a specific operation code.
+ *
+ * Results:
+ * TRUE is the capability for the operation has been changed.
+ * FALSE if the operation is not represented in the capabilities array.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsServerSetSessionCapability(HgfsOp op, // IN: operation code
+ uint32 flags, // IN: flags that describe level of support
+ HgfsSessionInfo *session) // INOUT: session to update
+{
+ int i;
+ Bool result = FALSE;
+
+ for ( i = 0; i < ARRAYSIZE(session->hgfsSessionCapabilities); i++) {
+ if (session->hgfsSessionCapabilities[i].op == op) {
+ session->hgfsSessionCapabilities[i].flags = flags;
+ result = TRUE;
+ }
+ }
+ LOG(4, ("%s: Setting capabilitiy flags %x for op code %d %s\n", __FUNCTION__, flags,
+ op, result ? "succeeded" : "failed"));
+ return result;
+}
+
+
/*
*-----------------------------------------------------------------------------
*
static Bool
HgfsServerSessionConnect(void *transportData, // IN: transport session context
HgfsServerChannelCallbacks *channelCbTable, // IN: Channel callbacks
+ uint32 channelCapabililies, // IN: channel capabilities
void **sessionData) // OUT: server session context
{
int i;
session->channelCbTable = channelCbTable;
Atomic_Write(&session->refCount, 0);
+ /* Get common to all sessions capabiities. */
+ HgfsServerGetDefaultCapabilities(session->hgfsSessionCapabilities,
+ &session->numberOfCapabilities);
+
/* Give our session a reference to hold while we are open. */
HgfsServerSessionGet(session);
*sessionData = session;
+ if (channelCapabililies & HGFS_CHANNEL_SHARED_MEM) {
+ HgfsServerSetSessionCapability(HGFS_OP_READ_FAST_V4, HGFS_REQUEST_SUPPORTED, session);
+ HgfsServerSetSessionCapability(HGFS_OP_WRITE_FAST_V4, HGFS_REQUEST_SUPPORTED, session);
+ }
+
return TRUE;
}
DblLnkLst_Links searchFreeList;
/** END SEARCH ARRAY ****************************************************/
+ /* Array of session specific capabiities. */
+ HgfsCapability hgfsSessionCapabilities[HGFS_OP_MAX];
+
+ uint32 numberOfCapabilities;
+
} HgfsSessionInfo;
char const *packetHeader, // IN: packet header
size_t *payloadSize, // OUT: size of packet
HgfsSessionInfo *session); // IN: Session Info
+void
+HgfsServerGetDefaultCapabilities(HgfsCapability *capabilities, // OUT:
+ uint32 *numberOfCapabilities); // OUT:
/* Node cache functions. */
Bool
ASSERT(payloadSize); \
} while(0)
-/* Capabilities of the HGFS server. */
-static HgfsCapability hgfsServerCapabilities[] =
+/*
+ * This is the default/minimal set of capabilities which is supported by every transport.
+ * Every transport and session may have additional capabilities in addition to these.
+ */
+static HgfsCapability hgfsDefaultCapabilityTable[] =
{
{HGFS_OP_OPEN, HGFS_REQUEST_SUPPORTED},
{HGFS_OP_READ, HGFS_REQUEST_SUPPORTED},
{HGFS_OP_WRITE_WIN32_STREAM_V3, HGFS_REQUEST_WIN32_SUPPORTED},
{HGFS_OP_CREATE_SESSION_V4, HGFS_REQUEST_SUPPORTED},
{HGFS_OP_DESTROY_SESSION_V4, HGFS_REQUEST_SUPPORTED},
- {HGFS_OP_READ_FAST_V4, HGFS_REQUEST_SUPPORTED},
- {HGFS_OP_WRITE_FAST_V4, HGFS_REQUEST_SUPPORTED},
+ {HGFS_OP_READ_FAST_V4, HGFS_REQUEST_NOT_SUPPORTED},
+ {HGFS_OP_WRITE_FAST_V4, HGFS_REQUEST_NOT_SUPPORTED},
{HGFS_OP_OPEN_V4, HGFS_REQUEST_NOT_SUPPORTED},
{HGFS_OP_DIRECTORY_READ_V4, HGFS_REQUEST_NOT_SUPPORTED},
{HGFS_OP_ENUMERATE_STREAMS_V4, HGFS_REQUEST_NOT_SUPPORTED},
{
Bool result;
HgfsReplyCreateSessionV4 *reply;
- uint32 numCapabilities = ARRAYSIZE(hgfsServerCapabilities);
+ uint32 numCapabilities = session->numberOfCapabilities;
+ uint32 capabilitiesLen = numCapabilities * sizeof *session->hgfsSessionCapabilities;
HGFS_ASSERT_PACK_PARAMS;
- *payloadSize = offsetof(HgfsReplyCreateSessionV4, capabilities) +
- sizeof hgfsServerCapabilities;
+ *payloadSize = offsetof(HgfsReplyCreateSessionV4, capabilities) + capabilitiesLen;
- result = HgfsAllocInitReply(packet, packetHeader, *payloadSize,
- (void **)&reply, session);
+ result = HgfsAllocInitReply(packet, packetHeader, *payloadSize, (void **)&reply,
+ session);
if (result) {
reply->sessionId = session->sessionId;
reply->numCapabilities = numCapabilities;
reply->maxPacketSize = session->maxPacketSize;
reply->identityOffset = 0;
reply->reserved = 0;
- memcpy(reply->capabilities, hgfsServerCapabilities,
- sizeof hgfsServerCapabilities);
+ memcpy(reply->capabilities, session->hgfsSessionCapabilities, capabilitiesLen);
}
return result;
return result;
}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerGetDefaultCapabilities --
+ *
+ * Returns list capabilities that are supported by all sessions.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsServerGetDefaultCapabilities(HgfsCapability *capabilities, // OUT: capabilities
+ uint32 *numberOfCapabilities) // OUT: number of items
+{
+ *numberOfCapabilities = ARRAYSIZE(hgfsDefaultCapabilityTable);
+ ASSERT(*numberOfCapabilities <= HGFS_OP_MAX);
+ memcpy(capabilities, hgfsDefaultCapabilityTable, sizeof hgfsDefaultCapabilityTable);
+}
connData->channelCbTable.send = HgfsChannelGuestBdSend;
result = connData->serverCbTable->connect(connData,
&connData->channelCbTable,
+ 0,
&connData->serverSession);
if (result) {
HgfsChannelGuestConnGet(connData);
#define HGFS_SEND_CAN_DELAY (1 << 0)
#define HGFS_SEND_NO_COMPLETE (1 << 1)
+// Channel capability flags
+#define HGFS_CHANNEL_SHARED_MEM (1 << 0)
+#define HGFS_CHANNEL_ASYNC (1 << 1)
typedef Bool
HgfsSessionSendFunc(void *opaqueSession, // IN
}HgfsServerChannelCallbacks;
typedef struct HgfsServerSessionCallbacks {
- Bool (*connect)(void *, HgfsServerChannelCallbacks *, void **);
+ Bool (*connect)(void *, HgfsServerChannelCallbacks *, uint32 ,void **);
void (*disconnect)(void *);
void (*close)(void *);
void (*receive)(HgfsPacket *packet, void *);