Bool markedForDeletion;
} HgfsSharedFolderProperties;
+static void HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSession,
+ HgfsSessionInfo *sessionInfo);
+
+static void HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession,
+ HgfsSessionInfo *sessionInfo);
/*
* Limit payload to 16M + header.
* This limit ensures that list of shared pages fits into VMCI datagram.
/* Local functions. */
+static Bool HgfsServerAllocateSession(HgfsTransportSessionInfo *transportSession,
+ uint32 channelCapabilities,
+ HgfsSessionInfo **sessionData);
static void HgfsInvalidateSessionObjects(DblLnkLst_Links *shares,
HgfsSessionInfo *session);
static Bool HgfsAddToCacheInternal(HgfsHandle handle,
HgfsServerSessionPut(HgfsSessionInfo *session) // IN: session context
{
ASSERT(session);
+
if (Atomic_FetchAndDec(&session->refCount) == 1) {
HgfsServerExitSessionInternal(session);
}
}
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsServerTransportSessionGet --
+ *
+ * Increment transport session reference count.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+HgfsServerTransportSessionGet(HgfsTransportSessionInfo *transportSession) // IN: session context
+{
+ ASSERT(transportSession);
+ Atomic_Inc(&transportSession->refCount);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsServerTransportSessionPut --
+ *
+ * Decrement transport session reference count.
+ *
+ * Free session info data if no reference.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerTransportSessionPut(HgfsTransportSessionInfo *transportSession) // IN: transport session context
+{
+ ASSERT(transportSession);
+ if (Atomic_FetchAndDec(&transportSession->refCount) == 1) {
+ DblLnkLst_Links *curr, *next;
+
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+
+ DblLnkLst_ForEachSafe(curr, next, &transportSession->sessionArray) {
+ HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
+ HgfsServerTransportRemoveSessionFromList(transportSession, session);
+ HgfsServerSessionPut(session);
+ }
+
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+ }
+}
+
+
/*
*-----------------------------------------------------------------------------
*
replySize = sizeof *header + replyPayloadSize;
replyPacketSize = replySize;
header = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
- input->session);
+ input->transportSession);
packetOut = (char *)header;
ASSERT_DEVEL(header && (replySize <= replyPacketSize));
}
replyPacketSize = replySize;
reply = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
- input->session);
+ input->transportSession);
packetOut = (char *)reply;
ASSERT_DEVEL(reply && (replySize <= replyPacketSize));
}
}
if (!HgfsPacketSend(input->packet, packetOut, replySize,
- input->session, 0)) {
+ input->transportSession, 0)) {
/* Send failed. Drop the reply. */
LOG(4, ("Error sending reply\n"));
}
HgfsServerSessionPut(input->session);
+ HgfsServerTransportSessionPut(input->transportSession);
free(input);
}
if (!input->metaPacket) {
input->metaPacket = HSPU_GetMetaPacket(input->packet,
&input->metaPacketSize,
- input->session);
+ input->transportSession);
}
input->payload = (char *)input->metaPacket + input->payloadOffset;
HgfsServerSessionReceive(HgfsPacket *packet, // IN: Hgfs Packet
void *clientData) // IN: session info
{
- HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
+ HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
HgfsInternalStatus status;
HgfsInputParam *input = NULL;
- ASSERT(session);
+ ASSERT(transportSession);
- if (session->state == HGFS_SESSION_STATE_CLOSED) {
+ if (transportSession->state == HGFS_SESSION_STATE_CLOSED) {
LOG(4, ("%s: %d: Received packet after disconnected.\n", __FUNCTION__,
__LINE__));
return;
}
- HgfsServerSessionGet(session);
+ HgfsServerTransportSessionGet(transportSession);
- if (!HgfsParseRequest(packet, session, &input, &status)) {
+ if (!HgfsParseRequest(packet, transportSession, &input, &status)) {
LOG(4, ("%s: %d: Can't generate any response for the guest, just exit.\n ",
__FUNCTION__, __LINE__));
- HgfsServerSessionPut(session);
+ HgfsServerTransportSessionPut(transportSession);
return;
}
* Asynchronous processing is supported by the transport.
* We can release mappings here and reacquire when needed.
*/
- HSPU_PutMetaPacket(packet, session);
+ HSPU_PutMetaPacket(packet, transportSession);
input->metaPacket = NULL;
Atomic_Inc(&gHgfsAsyncCounter);
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerTransportGetSessionInfo --
+ *
+ * Scans the list of sessions and return the session with the specified
+ * session id.
+ *
+ * Results:
+ * A valid pointer to HgfsSessionInfo if there is a session with the
+ * specified session id. NULL, otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+HgfsSessionInfo *
+HgfsServerTransportGetSessionInfo(HgfsTransportSessionInfo *transportSession, // IN: transport session info
+ uint64 sessionId) // IN: session id
+{
+ DblLnkLst_Links *curr;
+ HgfsSessionInfo *session = NULL;
+
+ ASSERT(transportSession);
+
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+
+ DblLnkLst_ForEach(curr, &transportSession->sessionArray) {
+ session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
+ if (session->sessionId == sessionId) {
+ HgfsServerSessionGet(session);
+ break;
+ }
+ session = NULL;
+ }
+
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+
+ return session;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerTransportRemoveSessionFromList --
+ *
+ * Unlinks the specified session info from the list.
+ *
+ * Note: The caller must acquire the sessionArrayLock in transportSession
+ * before calling this function.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSession, // IN: transport session info
+ HgfsSessionInfo *session) // IN: session info
+{
+ ASSERT(transportSession);
+ ASSERT(session);
+
+ DblLnkLst_Unlink1(&session->links);
+ HgfsServerSessionPut(session);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerTransportAddSessionToList --
+ *
+ * Links the specified session info to the list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession, // IN: transport session info
+ HgfsSessionInfo *session) // IN: session info
+{
+ ASSERT(transportSession);
+ ASSERT(session);
+
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+ DblLnkLst_LinkLast(&transportSession->sessionArray, &session->links);
+ HgfsServerSessionGet(session);
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+}
+
+
/*
*-----------------------------------------------------------------------------
*
*
* Initialize a new client session.
*
+ * Allocate HgfsTransportSessionInfo and initialize it.
+ *
+ * Results:
+ * TRUE on success, FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsServerSessionConnect(void *transportData, // IN: transport session context
+ HgfsServerChannelCallbacks *channelCbTable, // IN: Channel callbacks
+ uint32 channelCapabilities, // IN: channel capabilities
+ void **transportSessionData) // OUT: server session context
+{
+ HgfsTransportSessionInfo *transportSession;
+ HgfsSessionInfo *defaultSession;
+
+ ASSERT(transportSessionData);
+
+ LOG(4, ("%s: initting.\n", __FUNCTION__));
+
+ transportSession = Util_SafeCalloc(1, sizeof *transportSession);
+ transportSession->transportData = transportData;
+ transportSession->channelCbTable = channelCbTable;
+ transportSession->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
+ transportSession->type = HGFS_SESSION_TYPE_REGULAR;
+ transportSession->state = HGFS_SESSION_STATE_OPEN;
+ transportSession->channelCapabilities = channelCapabilities;
+
+ transportSession->sessionArrayLock =
+ MXUser_CreateExclLock("HgfsSessionArrayLock",
+ RANK_hgfsSessionArrayLock);
+ if (transportSession->sessionArrayLock == NULL) {
+ LOG(4, ("%s: Could not create session sync mutex.\n", __FUNCTION__));
+ free(transportSession);
+ return FALSE;
+ }
+
+ DblLnkLst_Init(&transportSession->sessionArray);
+
+ if (!HgfsServerAllocateSession(transportSession,
+ channelCapabilities,
+ &defaultSession)) {
+ MXUser_DestroyExclLock(transportSession->sessionArrayLock);
+ free(transportSession);
+ return FALSE;
+ }
+
+ defaultSession->type = HGFS_SESSION_TYPE_INTERNAL;
+ HgfsServerTransportAddSessionToList(transportSession, defaultSession);
+
+ transportSession->defaultSessionId = defaultSession->sessionId;
+
+ Atomic_Write(&transportSession->refCount, 0);
+
+ /* Give our session a reference to hold while we are open. */
+ HgfsServerTransportSessionGet(transportSession);
+
+ *transportSessionData = transportSession;
+ return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerAllocateSession --
+ *
+ * Initialize a new Hgfs session.
+ *
* Allocate HgfsSessionInfo and initialize it. Create the nodeArray and
* searchArray for the session.
*
*/
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
+HgfsServerAllocateSession(HgfsTransportSessionInfo *transportSession, // IN:
+ uint32 channelCapabilities, // IN:
+ HgfsSessionInfo **sessionData) // OUT:
{
int i;
- HgfsSessionInfo *session = Util_SafeMalloc(sizeof *session);
+ HgfsSessionInfo *session;
- ASSERT(sessionData);
+ ASSERT(transportSession);
- LOG(4, ("%s: initting.\n", __FUNCTION__));
+ session = Util_SafeCalloc(1, sizeof *session);
/*
* Initialize all our locks first as these can fail.
session->fileIOLock = MXUser_CreateExclLock("HgfsFileIOLock",
RANK_hgfsFileIOLock);
if (session->fileIOLock == NULL) {
- free(session);
LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
-
+ free(session);
return FALSE;
}
RANK_hgfsNodeArrayLock);
if (session->nodeArrayLock == NULL) {
MXUser_DestroyExclLock(session->fileIOLock);
- free(session);
LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
-
+ free(session);
return FALSE;
}
if (session->searchArrayLock == NULL) {
MXUser_DestroyExclLock(session->fileIOLock);
MXUser_DestroyExclLock(session->nodeArrayLock);
- free(session);
LOG(4, ("%s: Could not create search array sync mutex.\n",
__FUNCTION__));
-
+ free(session);
return FALSE;
}
session->sessionId = HgfsGenerateSessionId();
+ session->type = HGFS_SESSION_TYPE_REGULAR;
+ session->state = HGFS_SESSION_STATE_OPEN;
+ DblLnkLst_Init(&session->links);
session->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
session->activeNotification = FALSE;
+ session->transportSession = transportSession;
+
/*
* Initialize the node handling components.
*/
/* Initialize search freelist. */
DblLnkLst_Init(&session->searchFreeList);
+ Atomic_Write(&session->refCount, 0);
+
+ /* Give our session a reference to hold while we are open. */
+ HgfsServerSessionGet(session);
+
/* Allocate array of searches and add them to free list. */
session->numSearches = NUM_SEARCHES;
session->searchArray = Util_SafeCalloc(session->numSearches,
&session->searchArray[i].links);
}
- /*
- * Initialize the general session stuff.
- */
-
- session->type = HGFS_SESSION_TYPE_REGULAR;
- session->state = HGFS_SESSION_STATE_OPEN;
- session->transportData = transportData;
- 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) {
+ if (channelCapabilities & HGFS_CHANNEL_SHARED_MEM) {
HgfsServerSetSessionCapability(HGFS_OP_READ_FAST_V4,
HGFS_REQUEST_SUPPORTED, session);
HgfsServerSetSessionCapability(HGFS_OP_WRITE_FAST_V4,
HGFS_REQUEST_SUPPORTED, session);
}
+ *sessionData = session;
+
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
- * HgfsServerSessionDisconnect --
+ * HgfsDisconnectSessionInt --
*
* Disconnect a client session.
*
*/
static void
-HgfsServerSessionDisconnect(void *clientData) // IN: session context
+HgfsDisconnectSessionInt(HgfsSessionInfo *session) // IN: session context
{
- HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
ASSERT(session);
ASSERT(session->nodeArray);
if (session->activeNotification) {
HgfsNotify_CleanupSession(session);
}
+}
- session->state = HGFS_SESSION_STATE_CLOSED;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsServerSessionDisconnect --
+ *
+ * Disconnect a client session.
+ *
+ * Mark the session as closed as we are in the process of teardown
+ * of the session. No more new requests should be processed. We would
+ * start draining any outstanding pending operations at this point.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsServerSessionDisconnect(void *clientData) // IN: session context
+{
+ HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
+ DblLnkLst_Links *curr, *next;
+
+ ASSERT(transportSession);
+
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+
+ DblLnkLst_ForEachSafe(curr, next, &transportSession->sessionArray) {
+ HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
+
+ HgfsDisconnectSessionInt(session);
+ }
+
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+
+ transportSession->state = HGFS_SESSION_STATE_CLOSED;
}
static void
HgfsServerSessionClose(void *clientData) // IN: session context
{
- HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
-
- ASSERT(session);
- ASSERT(session->nodeArray);
- ASSERT(session->searchArray);
+ HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
- ASSERT(session->state == HGFS_SESSION_STATE_CLOSED);
+ ASSERT(transportSession);
+ ASSERT(transportSession->state == HGFS_SESSION_STATE_CLOSED);
/* Remove, typically, the last reference, will teardown everything. */
- HgfsServerSessionPut(session);
+ HgfsServerTransportSessionPut(transportSession);
}
MXUser_DestroyExclLock(session->nodeArrayLock);
MXUser_DestroyExclLock(session->searchArrayLock);
MXUser_DestroyExclLock(session->fileIOLock);
+
free(session);
}
* Side effects:
* Frees the packet buffer.
*
- *----------------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
void
HgfsServerSessionSendComplete(HgfsPacket *packet, // IN/OUT: Hgfs packet
void *clientData) // IN: session info
{
- HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
+ HgfsTransportSessionInfo *transportSession =
+ (HgfsTransportSessionInfo *)clientData;
if (packet->guestInitiated) {
- HSPU_PutMetaPacket(packet, session);
- HSPU_PutReplyPacket(packet, session);
- HSPU_PutDataPacketBuf(packet, session);
+ HSPU_PutMetaPacket(packet, transportSession);
+ HSPU_PutReplyPacket(packet, transportSession);
+ HSPU_PutDataPacketBuf(packet, transportSession);
} else {
free(packet->metaPacket);
free(packet);
HgfsPacketSend(HgfsPacket *packet, // IN/OUT: Hgfs Packet
char *packetOut, // IN: output buffer
size_t packetOutLen, // IN: packet size
- HgfsSessionInfo *session, // IN: session info
+ HgfsTransportSessionInfo *transportSession, // IN: session info
HgfsSendFlags flags) // IN: flags for how to process
{
Bool result = FALSE;
Bool notificationNeeded = packet->guestInitiated && packet->processedAsync;
ASSERT(packet);
- ASSERT(session);
+ ASSERT(transportSession);
- if (session->state == HGFS_SESSION_STATE_OPEN) {
+ if (transportSession->state == HGFS_SESSION_STATE_OPEN) {
packet->replyPacketSize = packetOutLen;
- ASSERT(session->type == HGFS_SESSION_TYPE_REGULAR);
- result = session->channelCbTable->send(session->transportData,
+ ASSERT(transportSession->type == HGFS_SESSION_TYPE_REGULAR);
+ result = transportSession->channelCbTable->send(transportSession->transportData,
packet, packetOut,
packetOutLen, flags);
}
void
HgfsServerSessionInvalidateObjects(void *clientData, // IN:
- DblLnkLst_Links *shares) // IN: List of new shares
+ DblLnkLst_Links *shares) // IN: List of new shares
{
- HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
+ HgfsTransportSessionInfo *transportSession =
+ (HgfsTransportSessionInfo *)clientData;
+ DblLnkLst_Links *curr;
+
+ ASSERT(transportSession);
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
- HgfsInvalidateSessionObjects(shares, session);
+ DblLnkLst_ForEach(curr, &transportSession->sessionArray) {
+ HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
+ HgfsServerSessionGet(session);
+ HgfsInvalidateSessionObjects(shares, session);
+ HgfsServerSessionPut(session);
+ }
+
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
}
headerSize = sizeof(HgfsReply);
}
replyPacketSize = headerSize + payloadSize;
- reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
+ reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session->transportSession);
if (reply && (replyPacketSize >= headerSize + payloadSize)) {
memset(reply, 0, headerSize + payloadSize);
payload = &reply->payload[0];
} else {
payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
- input->session);
+ input->transportSession);
}
if (payload) {
status = HgfsPlatformReadFile(file, input->session, offset,
if (inlineDataSize == 0) {
info.replyPayload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
- input->session);
+ input->transportSession);
} else {
info.replyPayload = (char *)info.reply + baseReplySize;
}
if (HgfsUnpackCreateSessionRequest(input->payload, input->payloadSize,
input->op, &info)) {
+ HgfsSessionInfo *session;
LOG(4, ("%s: create session\n", __FUNCTION__));
+
+ if (!HgfsServerAllocateSession(input->transportSession,
+ input->transportSession->channelCapabilities,
+ &session)) {
+ status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
+ goto abort;
+ } else {
+ HgfsServerTransportAddSessionToList(input->transportSession, session);
+ }
+
if (info.maxPacketSize < input->session->maxPacketSize) {
input->session->maxPacketSize = info.maxPacketSize;
}
if (HgfsPackCreateSessionReply(input->packet, input->metaPacket,
- &replyPayloadSize, input->session)) {
-
- /*
- * XXX - TO BE RESTORED on session support implementation
- * completion.
- */
-#if defined HGFS_SESSION_SUPPORT
- HgfsServerSessionGet(input->session);
-#endif
+ &replyPayloadSize, session)) {
status = HGFS_ERROR_SUCCESS;
} else {
status = HGFS_ERROR_INTERNAL;
status = HGFS_ERROR_PROTOCOL;
}
+abort:
HgfsServerCompleteRequest(status, replyPayloadSize, input);
}
static void
HgfsServerDestroySession(HgfsInputParam *input) // IN: Input params
{
+ HgfsTransportSessionInfo *transportSession;
+ HgfsSessionInfo *session;
+
HGFS_ASSERT_INPUT(input);
- HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
+ transportSession = input->transportSession;
+ session = input->session;
+
+ if ((session->sessionId == transportSession->defaultSessionId) ||
+ (session->type != HGFS_SESSION_TYPE_REGULAR)) {
+
+ /*
+ * In each transport session, there will be a default session. This
+ * default session should be in opened state till the end of the
+ * transport session. If we receive a destroy session request for
+ * default session, then we are receiving the requests for a malformed
+ * client. Return an error.
+ */
+ HgfsServerCompleteRequest(HGFS_STATUS_PROTOCOL_ERROR, 0, input);
+ return;
+ }
+
+ session->state = HGFS_SESSION_STATE_CLOSED;
+
/*
- * XXX - TO BE RESTORED on session support implementation
- * completion.
- */
-#if defined HGFS_SESSION_SUPPORT
- HgfsServerSessionPut(input->session);
-#endif
+ * Remove the session from the list. By doing that, the refcount of
+ * the session will be decremented. Later, we will be invoking
+ * HgfsServerCompleteRequest which will decrement the session's
+ * refcount and cleanup the session
+ */
+ MXUser_AcquireExclLock(transportSession->sessionArrayLock);
+ HgfsServerTransportRemoveSessionFromList(transportSession, session);
+ MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
+ HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
+ HgfsServerSessionPut(session);
}
HgfsPackChangeNotificationRequest(packetHeader, subscriber, shareName, fileName, mask,
flags, session, &sizeNeeded);
- if (!HgfsPacketSend(packet, (char *)packetHeader, sizeNeeded, session, 0)) {
+ if (!HgfsPacketSend(packet, (char *)packetHeader, sizeNeeded, session->transportSession, 0)) {
LOG(4, ("%s: failed to send notification to the host\n", __FUNCTION__));
}
HGFS_SESSION_TYPE_INTERNAL, /* This is a static session. */
} HgfsSessionInfoType;
-/* HgfsTransportSessionState, used for session status. */
+/* HgfsSessionState, used for session status. */
typedef enum {
HGFS_SESSION_STATE_OPEN,
HGFS_SESSION_STATE_CLOSED,
} HgfsSessionInfoState;
-typedef struct HgfsSessionInfo {
- /* Unique session id. */
- uint64 sessionId;
+typedef struct HgfsTransportSessionInfo {
+ /* Default session id. */
+ uint64 defaultSessionId;
+
+ /* Lock to manipulate the list of sessions */
+ MXUserExclLock *sessionArrayLock;
+
+ /* List of sessions */
+ DblLnkLst_Links sessionArray;
/* Max packet size that is supported by both client and server. */
uint32 maxPacketSize;
/* Function callbacks into Hgfs Channels. */
HgfsServerChannelCallbacks *channelCbTable;
+ Atomic_uint32 refCount; /* Reference count for session. */
+
+ uint32 channelCapabilities;
+} HgfsTransportSessionInfo;
+
+typedef struct HgfsSessionInfo {
+
+ DblLnkLst_Links links;
+
+ /* Unique session id. */
+ uint64 sessionId;
+
+ /* Max packet size that is supported by both client and server. */
+ uint32 maxPacketSize;
+
+ /* Transport session context. */
+ HgfsTransportSessionInfo *transportSession;
+
+ /* Current state of the session. */
+ HgfsSessionInfoState state;
+
+ /* Session is dynamic or internal. */
+ HgfsSessionInfoType type;
+
/* Lock to ensure some fileIO requests are atomic for a handle. */
MXUserExclLock *fileIOLock;
uint32 numberOfCapabilities;
Bool activeNotification;
-
} HgfsSessionInfo;
-
/*
* These structs represent information about file open requests, file
* attributes, and directory creation requests.
const char *metaPacket;
size_t metaPacketSize;
HgfsSessionInfo *session;
+ HgfsTransportSessionInfo *transportSession;
HgfsPacket *packet;
void const *payload;
uint32 payloadOffset;
Bool
HgfsParseRequest(HgfsPacket *packet, // IN: request packet
- HgfsSessionInfo *session, // IN: current session
+ HgfsTransportSessionInfo *transportSession, // IN: current session
HgfsInputParam **input, // OUT: request parameters
HgfsInternalStatus *status); // OUT: error code
size_t packetOutLen, // IN: Output packet size
HgfsInternalStatus status, // IN: status
HgfsHandle id, // IN: id of the request packet
- HgfsSessionInfo *session, // IN: session info
+ HgfsTransportSessionInfo *transportSession, // IN: session info
HgfsSendFlags flags); // IN: flags how to send
+/* Get the session with a specific session id */
+HgfsSessionInfo *
+HgfsServerTransportGetSessionInfo(HgfsTransportSessionInfo *transportSession, // IN: transport session info
+ uint64 sessionId); // IN: session id
+
Bool
HgfsPacketSend(HgfsPacket *packet, // IN/OUT: Hgfs Packet
char *packetOut, // IN: Output packet buffer
size_t packetOutLen, // IN: Output packet size
- HgfsSessionInfo *session, // IN: session info
+ HgfsTransportSessionInfo *transportSession, // IN: session info
HgfsSendFlags flags); // IN: flags how to send
Bool
HgfsSessionInfo *session, // IN: Session info
HgfsLocalId *localId, // OUT: Local unique file ID
fileDesc *newHandle); // OUT: Handle to the file
-void HgfsServerSessionGet(HgfsSessionInfo *session); // IN: session context
-
void *
HSPU_GetBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
uint32 startIndex, // IN: start index of iov
size_t bufSize, // IN: Size of buffer
Bool *isAllocated, // OUT: Was buffer allocated ?
MappingType mappingType, // IN: Readable/ Writeable ?
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void *
HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *metaPacketSize, // OUT: Size of metaPacket
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void *
HSPU_GetDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
MappingType mappingType, // IN: Readable/ Writeable ?
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void
HSPU_PutPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void
HSPU_PutBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *bufSize, // IN: Size of the buffer
Bool *isAllocated, // IN: Was buffer allocated ?
MappingType mappingType, // IN: Readable/ Writeable ?
- HgfsSessionInfo *session); // IN: Session info
+ HgfsTransportSessionInfo *transportSession); // IN: Session info
void
HSPU_PutDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void
HSPU_PutMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void
HSPU_CopyBufToDataIovec(HgfsPacket *packet, // IN/OUT: Hgfs packet
void *buf, // IN: Buffer to copy from
uint32 bufSize, // IN: Size of buffer
- HgfsSessionInfo *session);// IN: Session Info
+ HgfsTransportSessionInfo *transportSession);// IN: Session Info
void
HSPU_CopyBufToIovec(HgfsPacket *packet, // IN/OUT: Hgfs Packet
uint32 startIndex, // IN: start index into iov
void *buf, // IN: Buffer
size_t bufSize, // IN: Size of buffer
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void *
HSPU_GetReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *replyPacketSize, //IN/OUT: Size of reply Packet
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
void
HSPU_PutReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session); // IN: Session Info
+ HgfsTransportSessionInfo *transportSession); // IN: Session Info
#endif /* __HGFS_SERVER_INT_H__ */
void *
HSPU_GetReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *replyPacketSize, // IN/OUT: Size of reply Packet
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
- ASSERT(session);
+ ASSERT(transportSession);
if (packet->replyPacket) {
/*
* When we are transferring packets over backdoor, reply packet
LOG(4, ("Exising reply packet %s %Zu %Zu\n", __FUNCTION__,
*replyPacketSize, packet->replyPacketSize));
ASSERT_DEVEL(*replyPacketSize <= packet->replyPacketSize);
- } else if (session->channelCbTable && session->channelCbTable->getWriteVa) {
+ } else if (transportSession->channelCbTable && transportSession->channelCbTable->getWriteVa) {
/* Can we write directly into guest memory ? */
ASSERT_DEVEL(packet->metaPacket);
if (packet->metaPacket) {
packet->metaPacketSize,
&packet->metaPacketIsAllocated,
BUF_WRITEABLE,
- session);
+ transportSession);
/*
* Really this can never happen, we would have caught bad physical address
* during getMetaPacket.
void
HSPU_PutReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
if (packet->replyPacketIsAllocated) {
LOG(10, ("%s Freeing reply packet", __FUNCTION__));
void *
HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
size_t *metaPacketSize, // OUT: Size of metaPacket
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
*metaPacketSize = packet->metaPacketSize;
return HSPU_GetBuf(packet, 0, &packet->metaPacket,
packet->metaPacketSize,
&packet->metaPacketIsAllocated,
- BUF_READWRITEABLE, session);
+ BUF_READWRITEABLE, transportSession);
}
void *
HSPU_GetDataPacketIov(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session, // IN: Session Info
+ HgfsTransportSessionInfo *transportSession, // IN: Session Info
HgfsVaIov iov) // OUT: I/O vector
{
NOT_IMPLEMENTED();
void *
HSPU_GetDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
MappingType mappingType, // IN: Writeable/Readable
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
packet->dataMappingType = mappingType;
return HSPU_GetBuf(packet, packet->dataPacketIovIndex,
&packet->dataPacket, packet->dataPacketSize,
- &packet->dataPacketIsAllocated, mappingType, session);
+ &packet->dataPacketIsAllocated, mappingType, transportSession);
}
size_t bufSize, // IN: Size of buffer
Bool *isAllocated, // OUT: Was buffer allocated ?
MappingType mappingType, // IN: Readable/Writeable ?
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
uint32 iovCount;
uint32 iovMapped = 0;
return NULL;
}
- if (!session->channelCbTable) {
+ if (!transportSession->channelCbTable) {
return NULL;
}
if (mappingType == BUF_WRITEABLE ||
mappingType == BUF_READWRITEABLE) {
- func = session->channelCbTable->getWriteVa;
+ func = transportSession->channelCbTable->getWriteVa;
} else {
ASSERT(mappingType == BUF_READABLE);
- func = session->channelCbTable->getReadVa;
+ func = transportSession->channelCbTable->getReadVa;
}
/* Looks like we are in the middle of poweroff. */
freeMem:
for (i = startIndex; i < iovCount; i++) {
- session->channelCbTable->putVa(&packet->iov[i].token);
+ transportSession->channelCbTable->putVa(&packet->iov[i].token);
packet->iov[i].va = NULL;
}
void
HSPU_PutMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
LOG(4, ("%s Hgfs Putting Meta packet\n", __FUNCTION__));
HSPU_PutBuf(packet, 0, &packet->metaPacket,
&packet->metaPacketSize,
&packet->metaPacketIsAllocated,
- BUF_WRITEABLE, session);
+ BUF_WRITEABLE, transportSession);
}
void
HSPU_PutDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
LOG(4, ("%s Hgfs Putting Data packet\n", __FUNCTION__));
HSPU_PutBuf(packet, packet->dataPacketIovIndex,
&packet->dataPacket, &packet->dataPacketSize,
&packet->dataPacketIsAllocated,
- packet->dataMappingType, session);
+ packet->dataMappingType, transportSession);
}
size_t *bufSize, // IN: Size of the buffer
Bool *isAllocated, // IN: Was buffer allocated ?
MappingType mappingType, // IN: Readable / Writeable ?
- HgfsSessionInfo *session) // IN: Session info
+ HgfsTransportSessionInfo *transportSession) // IN: Session info
{
uint32 iovCount = 0;
int size = *bufSize;
ASSERT(buf);
- if (!session->channelCbTable) {
+ if (!transportSession->channelCbTable) {
return;
}
- if (!session->channelCbTable->putVa || *buf == NULL) {
+ if (!transportSession->channelCbTable->putVa || *buf == NULL) {
return;
}
if (*isAllocated) {
if (mappingType == BUF_WRITEABLE) {
- HSPU_CopyBufToIovec(packet, startIndex, *buf, *bufSize, session);
+ HSPU_CopyBufToIovec(packet, startIndex, *buf, *bufSize, transportSession);
}
LOG(10, ("%s: Hgfs Freeing buffer \n", __FUNCTION__));
free(*buf);
iovCount < packet->iovCount && size > 0;
iovCount++) {
ASSERT_DEVEL(packet->iov[iovCount].token);
- session->channelCbTable->putVa(&packet->iov[iovCount].token);
+ transportSession->channelCbTable->putVa(&packet->iov[iovCount].token);
size -= packet->iov[iovCount].len;
}
LOG(10, ("%s: Hgfs bufSize = %d \n", __FUNCTION__, size));
HSPU_CopyBufToMetaIovec(HgfsPacket *packet, // IN/OUT: Hgfs packet
void *buf, // IN: Buffer to copy from
size_t bufSize, // IN: Size of buffer
- HgfsSessionInfo *session)// IN: Session Info
+ HgfsTransportSessionInfo *transportSession)// IN: Session Info
{
- HSPU_CopyBufToIovec(packet, 0, buf, bufSize, session);
+ HSPU_CopyBufToIovec(packet, 0, buf, bufSize, transportSession);
}
HSPU_CopyBufToDataIovec(HgfsPacket *packet, // IN: Hgfs packet
void *buf, // IN: Buffer to copy from
uint32 bufSize, // IN: Size of buffer
- HgfsSessionInfo *session)
+ HgfsTransportSessionInfo *transportSession)
{
HSPU_CopyBufToIovec(packet, packet->dataPacketIovIndex, buf, bufSize,
- session);
+ transportSession);
}
uint32 startIndex, // IN: start index into iov
void *buf, // IN: Contigous Buffer
size_t bufSize, // IN: Size of buffer
- HgfsSessionInfo *session) // IN: Session Info
+ HgfsTransportSessionInfo *transportSession) // IN: Session Info
{
uint32 iovCount;
size_t remainingSize = bufSize;
ASSERT(packet);
ASSERT(buf);
- if (!session->channelCbTable) {
+ if (!transportSession->channelCbTable) {
return;
}
- ASSERT_DEVEL(session->channelCbTable->getWriteVa);
- if (!session->channelCbTable->getWriteVa) {
+ ASSERT_DEVEL(transportSession->channelCbTable->getWriteVa);
+ if (!transportSession->channelCbTable->getWriteVa) {
return;
}
ASSERT_DEVEL(packet->iov[iovCount].len <=
(PAGE_SIZE - PAGE_OFFSET(packet->iov[iovCount].pa)));
- packet->iov[iovCount].va = session->channelCbTable->getWriteVa(packet->iov[iovCount].pa,
+ packet->iov[iovCount].va = transportSession->channelCbTable->getWriteVa(packet->iov[iovCount].pa,
packet->iov[iovCount].len,
&packet->iov[iovCount].token);
ASSERT_DEVEL(packet->iov[iovCount].va);
if (packet->iov[iovCount].va != NULL) {
memcpy(packet->iov[iovCount].va, (char *)buf + copiedAmount, copyAmount);
- session->channelCbTable->putVa(&packet->iov[iovCount].token);
+ transportSession->channelCbTable->putVa(&packet->iov[iovCount].token);
remainingSize -= copyAmount;
copiedAmount += copyAmount;
} else {