* Open the backdoor in an idempotent way.
*
* Results:
- * TRUE on success, FALSE on failure.
+ * Existing or updated channel status, HGFS_CHANNEL_CONNECTED on success.
*
* Side effects:
* None
*-----------------------------------------------------------------------------
*/
-static Bool
+static HgfsChannelStatus
HgfsBdChannelOpen(HgfsTransportChannel *channel) // IN: Channel
{
- Bool ret;
-
pthread_mutex_lock(&channel->connLock);
switch (channel->status) {
case HGFS_CHANNEL_UNINITIALIZED:
- ret = FALSE;
+ LOG(8, ("Backdoor uninitialized.\n"));
break;
case HGFS_CHANNEL_CONNECTED:
- ret = TRUE;
+ LOG(8, ("Backdoor already connected.\n"));
break;
case HGFS_CHANNEL_NOTCONNECTED:
if (HgfsBd_OpenBackdoor((RpcOut **)&channel->priv)) {
- LOG(8, ("Backdoor opened.\n"));
- bdChannel.status = HGFS_CHANNEL_CONNECTED;
- ret = TRUE;
+ LOG(8, ("Backdoor opened and connected.\n"));
+ channel->status = HGFS_CHANNEL_CONNECTED;
ASSERT(channel->priv != NULL);
} else {
- ret = FALSE;
+ LOG(8, ("ERROR: Backdoor cannot connect.\n"));
}
break;
default:
ASSERT(0); /* Not reached. */
- ret = FALSE;
+ LOG(2, ("ERROR: Backdoor status %d is unknown resetting.\n",
+ channel->status));
+ channel->status = HGFS_CHANNEL_UNINITIALIZED;
}
pthread_mutex_unlock(&channel->connLock);
- return ret;
+ return channel->status;
}
static HgfsTransportChannel *gHgfsActiveChannel; /* Current active channel. */
static pthread_mutex_t gHgfsActiveChannelLock; /* Current active channel lock. */
+static Bool gHgfsActiveChannelLockInited;
static struct list_head gHgfsPendingRequests; /* Pending requests queue. */
static pthread_mutex_t gHgfsPendingRequestsLock; /* Pending requests queue lock. */
+static Bool gHgfsPendingRequestsLockInited;
#define HgfsRequestId(req) ((HgfsRequest *)req)->id
* Open a new workable channel.
*
* Results:
- * TRUE on success and the new channel, otherwise FALSE and NULL.
+ * 0 on success and the new channel, otherwise -ENOTCONN and NULL.
*
* Side effects:
* None
*----------------------------------------------------------------------
*/
-static Bool
+static int
HgfsTransportChannelOpen(HgfsTransportChannel **channel) // IN: active channel
{
- Bool result = FALSE;
+ int result = 0;
*channel = HgfsBdChannelInit();
if (NULL != *channel) {
- if ((*channel)->ops.open(*channel)) {
- result = TRUE;
- } else {
+ HgfsChannelStatus status = (*channel)->ops.open(*channel);
+ if (status != HGFS_CHANNEL_CONNECTED) {
HgfsTransportChannelClose(channel);
+ result = -ENOTCONN;
+ *channel = NULL;
}
}
HgfsTransportChannelReset(HgfsTransportChannel **channel) // IN: active channel
{
Bool ret = FALSE;
+ int openResult;
+
HgfsTransportChannelClose(channel);
- ret = HgfsTransportChannelOpen(channel);
- LOG(8, ("Result: %s.\n", ret ? "TRUE" : "FALSE"));
+ openResult = HgfsTransportChannelOpen(channel);
+ if (openResult == 0) {
+ ret = TRUE;
+ }
+ LOG(8, ("Result: %d: %s.\n",openResult, ret ? "TRUE" : "FALSE"));
return ret;
}
pthread_mutex_lock(&gHgfsActiveChannelLock);
/* Try opening the channel. */
- if (NULL == gHgfsActiveChannel &&
- !HgfsTransportChannelOpen(&gHgfsActiveChannel)) {
- pthread_mutex_unlock(&gHgfsActiveChannelLock);
- return -EPROTO;
+ if (NULL == gHgfsActiveChannel) {
+ ret = HgfsTransportChannelOpen(&gHgfsActiveChannel);
+ if (ret != 0) {
+ goto exit;
+ }
}
ASSERT(gHgfsActiveChannel->ops.send);
if (ret < 0) {
LOG(4, ("Send failed, status = %d. Try reopening the channel ...\n",
ret));
- if (gHgfsActiveChannel->ops.open(gHgfsActiveChannel) &&
- HgfsTransportChannelReset(&gHgfsActiveChannel)) {
+ if (HgfsTransportChannelReset(&gHgfsActiveChannel)) {
ret = gHgfsActiveChannel->ops.send(gHgfsActiveChannel, req);
}
}
+exit:
ASSERT(req->state == HGFS_REQ_STATE_COMPLETED ||
req->state == HGFS_REQ_STATE_SUBMITTED ||
req->state == HGFS_REQ_STATE_UNSENT);
* connected socket.
*
* Results:
- * Zero on success and negative one on failure.
+ * Zero on success and negative error on failure.
*
* Side effects:
* None
HgfsTransportInit(void)
{
int res;
+
+ gHgfsActiveChannel = NULL;
+ gHgfsPendingRequestsLockInited = FALSE;
+ gHgfsActiveChannelLockInited = FALSE;
INIT_LIST_HEAD(&gHgfsPendingRequests);
+
res = pthread_mutex_init(&gHgfsPendingRequestsLock, NULL);
- if( res != 0) {
- return -1;
+ if (res != 0) {
+ res = -res;
+ goto exit;
}
+ gHgfsPendingRequestsLockInited = TRUE;
+
res = pthread_mutex_init(&gHgfsActiveChannelLock, NULL);
- if( res != 0) {
- return -1;
+ if (res != 0) {
+ res = -res;
+ goto exit;
}
- gHgfsActiveChannel = NULL;
- return 0;
+ gHgfsActiveChannelLockInited = TRUE;
+
+ res = HgfsTransportChannelOpen(&gHgfsActiveChannel);
+
+exit:
+ if (res != 0) {
+ HgfsTransportExit();
+ }
+ return res;
}
HgfsTransportExit(void)
{
LOG(8, ("Entered.\n"));
- pthread_mutex_lock(&gHgfsActiveChannelLock);
- HgfsTransportChannelClose(&gHgfsActiveChannel);
- pthread_mutex_unlock(&gHgfsActiveChannelLock);
+
+ if (gHgfsActiveChannelLockInited) {
+ pthread_mutex_lock(&gHgfsActiveChannelLock);
+ HgfsTransportChannelClose(&gHgfsActiveChannel);
+ pthread_mutex_unlock(&gHgfsActiveChannelLock);
+
+ pthread_mutex_destroy(&gHgfsActiveChannelLock);
+ gHgfsActiveChannelLockInited = FALSE;
+ }
ASSERT(list_empty(&gHgfsPendingRequests));
+
+ if (gHgfsPendingRequestsLockInited) {
+ pthread_mutex_destroy(&gHgfsPendingRequestsLock);
+ gHgfsPendingRequestsLockInited = FALSE;
+ }
LOG(8, ("Exited.\n"));
}
#include "request.h"
#include <pthread.h>
+typedef enum {
+ HGFS_CHANNEL_UNINITIALIZED,
+ HGFS_CHANNEL_NOTCONNECTED,
+ HGFS_CHANNEL_CONNECTED,
+} HgfsChannelStatus;
+
/*
* There are the operations a channel should implement.
*/
struct HgfsTransportChannel;
typedef struct HgfsTransportChannelOps {
- Bool (*open)(struct HgfsTransportChannel *);
+ HgfsChannelStatus (*open)(struct HgfsTransportChannel *);
void (*close)(struct HgfsTransportChannel *);
int (*send)(struct HgfsTransportChannel *, HgfsReq *);
int (*recv)(struct HgfsTransportChannel *, char **, size_t *);
void (*exit)(struct HgfsTransportChannel *);
} HgfsTransportChannelOps;
-typedef enum {
- HGFS_CHANNEL_UNINITIALIZED,
- HGFS_CHANNEL_NOTCONNECTED,
- HGFS_CHANNEL_CONNECTED,
-} HgfsChannelStatus;
-
typedef struct HgfsTransportChannel {
const char *name; /* Channel name. */
HgfsTransportChannelOps ops; /* Channel ops. */