[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r28480 - msh/src
From: |
gnunet |
Subject: |
[GNUnet-SVN] r28480 - msh/src |
Date: |
Thu, 8 Aug 2013 23:00:16 +0200 |
Author: harsha
Date: 2013-08-08 23:00:16 +0200 (Thu, 08 Aug 2013)
New Revision: 28480
Modified:
msh/src/msh.c
msh/src/mshd-server.c
msh/src/mshd.c
msh/src/mtypes.h
Log:
- better structure
Modified: msh/src/msh.c
===================================================================
--- msh/src/msh.c 2013-08-08 17:30:02 UTC (rev 28479)
+++ msh/src/msh.c 2013-08-08 21:00:16 UTC (rev 28480)
@@ -48,31 +48,53 @@
struct GNUNET_MessageHeader *msg;
};
-/**
- * DLL head for the message queue
- */
-static struct MessageQueue *mq_head;
/**
- * DLL tail for the message queue
+ * Context information for a connection
*/
-static struct MessageQueue *mq_tail;
+struct ConnCtx
+{
+ /**
+ * The transmit handle
+ */
+ struct GNUNET_CLIENT_TransmitHandle *tx;
-/**
- * Our connection to the parent MSHD
- */
-static struct GNUNET_CLIENT_Connection *client;
+ /**
+ * The client connection handle
+ */
+ struct GNUNET_CLIENT_Connection *conn;
+ /**
+ * configuration used to obtain this connection
+ */
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+ /**
+ * DLL head for the message queue
+ */
+ struct MessageQueue *mq_head;
+
+ /**
+ * DLL tail for the message queue
+ */
+ struct MessageQueue *mq_tail;
+
+ /**
+ * retry backoff time for this connection
+ */
+ struct GNUNET_TIME_Relative backoff;
+};
+
+
/**
- * Our connection to the parent MSHD
+ * context for the connection to parent MSHD
*/
-static struct GNUNET_CLIENT_Connection *client_remote;
+static struct ConnCtx ctx_local;
/**
- * Handle for transmissions on conn
+ * context for the connection to remote MSHD
*/
-static struct GNUNET_CLIENT_TransmitHandle *th;
+static struct ConnCtx ctx_remote;
/**
* file handle for the stdin
@@ -107,16 +129,6 @@
struct GNUNET_CLIENT_TestHandle *test;
/**
- * configuration for connecting to local MSHD through client API
- */
-struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * configuration for connecting to remote MSHD through client API
- */
-struct GNUNET_CONFIGURATION_Handle *remote_cfg;
-
-/**
* length of the cmdstr
*/
static size_t cmdstr_len;
@@ -132,11 +144,6 @@
static GNUNET_SCHEDULER_TaskIdentifier task_fwd_stdout;
/**
- * retry backoff time
- */
-static struct GNUNET_TIME_Relative retry_backoff;
-
-/**
* flag to indicate successful completion by setting it to GNUNET_OK
*/
static int result;
@@ -152,14 +159,25 @@
enum State
{
/**
- * Initial state where the remote command is delivered to the MSHD
+ * Address lookup of the remote instance
*/
+ STATE_LOOKUP,
+
+ /**
+ * Remote command is delivered to remote MSHD
+ */
STATE_DELIVER_CMD,
/**
- * State where the stdin and stdout streams are forwarded to and from the
MSHD
+ * Get authorization credential from parent MSHD
*/
- STATE_FORWARD_STREAMS
+ STATE_GET_CRED,
+
+ /**
+ * stdin and stdout streams are forwarded to and from the MSHD
+ */
+ STATE_FORWARD_STREAMS,
+
} state;
/**
@@ -194,22 +212,27 @@
/**
- * Function to cleanup the message queue
+ * Destroys a connection context
*
- * @param
- * @return
+ * @param ctx connection context
*/
static void
-cleanup_mq ()
+destroy_conn_ctx (struct ConnCtx *ctx)
{
struct MessageQueue *mq;
- while (NULL != (mq = mq_head))
+ if (NULL != ctx->tx)
+ GNUNET_CLIENT_notify_transmit_ready_cancel (ctx->tx);
+ if (NULL != ctx->conn)
+ GNUNET_CLIENT_disconnect (ctx->conn);
+ if (NULL != ctx->cfg)
+ GNUNET_CONFIGURATION_destroy (ctx->cfg);
+ while (NULL != (mq = ctx->mq_head))
{
- GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq);
+ GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq);
GNUNET_free (mq->msg);
GNUNET_free (mq);
- }
+ }
}
@@ -227,48 +250,50 @@
static size_t
conn_transmit_ready (void *cls, size_t size, void *buf)
{
+ struct ConnCtx *ctx = cls;
struct MessageQueue *mq;
uint16_t msg_size;
size_t wrote;
wrote = 0;
- th = NULL;
+ GNUNET_assert (NULL != ctx->tx);
+ ctx->tx = NULL;
if ((0 == size) && (NULL == buf))
{
LOG_ERROR ("Connection to MSHD broken\n");
- cleanup_mq ();
+ destroy_conn_ctx (ctx);
return 0;
}
- mq = mq_head;
+ mq = ctx->mq_head;
GNUNET_assert (NULL != mq);
if ((0 == size) || (NULL == buf))
{
LOG_DEBUG ("Message sending timed out -- retrying\n");
- retry_backoff = GNUNET_TIME_STD_BACKOFF (retry_backoff);
- th =
- GNUNET_CLIENT_notify_transmit_ready (client, ntohs (mq->msg->size),
- retry_backoff, GNUNET_NO,
+ ctx->backoff = GNUNET_TIME_STD_BACKOFF (ctx->backoff);
+ ctx->tx =
+ GNUNET_CLIENT_notify_transmit_ready (ctx->conn, ntohs (mq->msg->size),
+ ctx->backoff, GNUNET_NO,
&conn_transmit_ready,
- NULL);
+ ctx);
return 0;
}
- retry_backoff = GNUNET_TIME_UNIT_ZERO;
+ ctx->backoff = GNUNET_TIME_UNIT_ZERO;
msg_size = ntohs (mq->msg->size);
GNUNET_assert ( msg_size <= size);
(void) memcpy (buf, mq->msg, msg_size);
wrote = msg_size;
GNUNET_free (mq->msg);
- GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq);
- GNUNET_free (mq);
- if (NULL != (mq = mq_head))
+ GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq);
+ GNUNET_free (mq);
+ if (NULL != (mq = ctx->mq_head))
{
- retry_backoff = GNUNET_TIME_STD_BACKOFF (retry_backoff);
- th =
- GNUNET_CLIENT_notify_transmit_ready (client, ntohs (mq->msg->size),
- retry_backoff, GNUNET_NO,
+ ctx->backoff = GNUNET_TIME_STD_BACKOFF (ctx->backoff);
+ ctx->tx =
+ GNUNET_CLIENT_notify_transmit_ready (ctx->conn, ntohs (mq->msg->size),
+ ctx->backoff, GNUNET_NO,
&conn_transmit_ready,
- NULL);
+ ctx);
}
return wrote;
}
@@ -280,7 +305,7 @@
* @param msg the message to queue
*/
static void
-queue_message (struct GNUNET_MessageHeader *msg)
+queue_message (struct ConnCtx *ctx, struct GNUNET_MessageHeader *msg)
{
struct MessageQueue *mq;
uint16_t type;
@@ -293,20 +318,30 @@
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Queueing message of type %u, size %u for sending\n", type,
ntohs (msg->size));
- GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq);
- if (NULL == th)
+ GNUNET_CONTAINER_DLL_insert_tail (ctx->mq_head, ctx->mq_tail, mq);
+ if (NULL == ctx->tx)
{
- retry_backoff = GNUNET_TIME_STD_BACKOFF (retry_backoff);
- th =
- GNUNET_CLIENT_notify_transmit_ready (client, size,
- retry_backoff, GNUNET_NO,
+ ctx->backoff = GNUNET_TIME_STD_BACKOFF (ctx->backoff);
+ ctx->tx =
+ GNUNET_CLIENT_notify_transmit_ready (ctx->conn, size,
+ ctx->backoff, GNUNET_NO,
&conn_transmit_ready,
- NULL);
+ ctx);
}
}
/**
+ * Dispatcher for received messages
+ *
+ * @param cls connection context
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void
+dispatch (void *cls, const struct GNUNET_MessageHeader *msg);
+
+
+/**
* forward stdin data to MSHD
*
* @param cls NULL
@@ -314,7 +349,7 @@
*/
static void
fwd_stdin (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
+{
struct MSH_MSG_CmdIO *msg;
ssize_t size;
uint16_t msg_size;
@@ -344,7 +379,7 @@
msg->header.size = htons (msg_size);
msg->header.type = htons (MSH_MTYPE_CMD_STREAM_STDIN);
(void) memcpy (msg->data, recv_buf, size);
- queue_message (&msg->header);
+ queue_message (&ctx_remote, &msg->header);
reschedule:
task_fwd_stdin =
@@ -358,11 +393,13 @@
* Type of a function to call when we receive a message
* from the service.
*
- * @param cls closure
+ * @param ctx the connection context
* @param msg message received, NULL on timeout or fatal error
+ * @return GNUNET_OK to keep the connection open; any other value to close it
*/
-static void
-forward_output (void *cls, const struct GNUNET_MessageHeader *msg_)
+static int
+handle_cmd_output (struct ConnCtx *ctx,
+ const struct GNUNET_MessageHeader *msg_)
{
const struct MSH_MSG_CmdIO *msg;
uint16_t size;
@@ -372,14 +409,13 @@
{
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
- return;
+ return GNUNET_SYSERR;;
}
size = ntohs (msg->header.size);
GNUNET_break (size ==
GNUNET_DISK_file_write (fh_stdout, msg->data,
size - sizeof (struct MSH_MSG_CmdIO)));
- GNUNET_CLIENT_receive (client_remote, &forward_output, NULL,
- GNUNET_TIME_UNIT_FOREVER_REL);
+ return GNUNET_OK;
}
@@ -387,11 +423,13 @@
* Type of a function to call when we receive a message
* from the service.
*
- * @param cls closure
+ * @param ctx the connection context
* @param msg message received, NULL on timeout or fatal error
+ * @return GNUNET_OK to keep the connection open; any other value to close it
*/
-static void
-challenge_status (void *cls, const struct GNUNET_MessageHeader *msg_)
+static int
+handle_exec_begin (struct ConnCtx *ctx,
+ const struct GNUNET_MessageHeader *msg_)
{
LOG (GNUNET_ERROR_TYPE_INFO, "Executing remote command\n");
fh_stdin = GNUNET_DISK_get_handle_from_native (stdin);
@@ -399,11 +437,9 @@
GNUNET_assert (NULL != fh_stdin);
GNUNET_assert (NULL != fh_stdout);
state = STATE_FORWARD_STREAMS;
- GNUNET_CLIENT_receive (client_remote, &forward_output, NULL,
- GNUNET_TIME_UNIT_FOREVER_REL);
- task_fwd_stdin =
GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- fh_stdin, &fwd_stdin, NULL);
+ fh_stdin, &fwd_stdin, NULL);
+ return GNUNET_OK;
}
@@ -411,21 +447,20 @@
* Type of a function to call when we receive a message
* from the service.
*
- * @param cls closure
+ * @param ctx the connection context
* @param msg message received, NULL on timeout or fatal error
+ * @return GNUNET_OK to keep the connection open; any other value to close it
*/
-static void
-auth_challenge_response (void *cls, const struct GNUNET_MessageHeader *msg_)
+static int
+handle_challenge_response (struct ConnCtx *ctx,
+ const struct GNUNET_MessageHeader *msg_)
{
- const struct MSH_MSG_ChallengeResponse *msg;
+ struct GNUNET_MessageHeader *msg;
- //msg = (const struct MSH_MSG_ChallengeResponse *) msg_;
- GNUNET_CLIENT_transmit_and_get_response (client_remote,
- msg_,
- GNUNET_TIME_UNIT_MINUTES,
- GNUNET_NO,
- &challenge_status,
- NULL);
+ msg = GNUNET_copy_message (msg_);
+ queue_message (&ctx_remote, msg);
+ destroy_conn_ctx (&ctx_local);
+ return GNUNET_OK;
}
@@ -433,82 +468,70 @@
* Type of a function to call when we receive a message
* from the service.
*
- * @param cls closure
+ * @param ctx the connection context
* @param msg message received, NULL on timeout or fatal error
+ * @return GNUNET_OK to keep the connection open; any other value to close it
*/
-static void
-auth_challenge (void *cls, const struct GNUNET_MessageHeader *msg_)
+static int
+handle_challenge (struct ConnCtx *ctx,
+ const struct GNUNET_MessageHeader *msg_)
{
- if (MSH_MTYPE_CHALLENGE != ntohs (msg_->type))
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
+ struct GNUNET_MessageHeader *msg;
if (sizeof (struct MSH_MSG_Challenge) >= ntohs (msg_->size))
{
GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
+ return GNUNET_SYSERR;
}
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CLIENT_transmit_and_get_response (client,
- msg_,
-
GNUNET_TIME_UNIT_SECONDS,
- GNUNET_NO,
-
&auth_challenge_response,
- NULL));
+ msg = GNUNET_copy_message (msg_);
+ queue_message (&ctx_local, msg);
+ return GNUNET_OK;
}
+/**
+ * Tries to establish a connection to the target remote MSHD
+ */
static void
target_connect ()
{
struct MSH_MSG_RunCmd *msg;
+ struct GNUNET_CONFIGURATION_Handle *cfg;
uint16_t size;
- remote_cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_CONFIGURATION_set_value_string (remote_cfg, MSHD_REMOTE, "LISTEN",
+ cfg = GNUNET_CONFIGURATION_create ();
+ GNUNET_CONFIGURATION_set_value_string (cfg, MSHD_REMOTE, "LISTEN",
ip2str (target));
- GNUNET_CONFIGURATION_set_value_number (remote_cfg, MSHD_REMOTE, "PORT",
+ GNUNET_CONFIGURATION_set_value_number (cfg, MSHD_REMOTE, "PORT",
target_port);
- client_remote = GNUNET_CLIENT_connect (MSHD_REMOTE, remote_cfg);
- if (NULL == client_remote)
- return;
+ ctx_remote.cfg = cfg;
+ ctx_remote.conn = GNUNET_CLIENT_connect (MSHD_REMOTE, ctx_remote.cfg);
+ GNUNET_assert (NULL != ctx_remote.conn);
size = sizeof (struct MSH_MSG_RunCmd) + cmdstr_len;
msg = GNUNET_malloc (size);
msg->header.size = htons (size);
msg->header.type = htons (MSH_MTYPE_RUNCMD);
(void) memcpy (msg->cmd, cmdstr, cmdstr_len);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CLIENT_transmit_and_get_response (client_remote,
- &msg->header,
-
GNUNET_TIME_UNIT_SECONDS,
- GNUNET_NO,
- &auth_challenge,
- NULL));
- GNUNET_free (msg);
-}
+ queue_message (&ctx_remote, &msg->header);
+ GNUNET_CLIENT_receive (ctx_remote.conn, &dispatch, &ctx_remote,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ }
/**
* Type of a function to call when we receive a message
* from the service.
*
- * @param cls closure
+ * @param ctx the connection context
* @param msg message received, NULL on timeout or fatal error
+ * @return GNUNET_OK to keep the connection open; any other value to close it
*/
-static void
-lookup_status (void *cls, const struct GNUNET_MessageHeader *msg_)
+static int
+handle_lookup_reply (struct ConnCtx *ctx,
+ const struct GNUNET_MessageHeader *msg_)
{
const struct MSH_MSG_AddressLookupReply *msg;
uint16_t size;
- if (MSH_MTYPE_ADDRESS_LOOKUP_REPLY != ntohs (msg_->type))
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
+
size = ntohs (msg_->size);
msg = (const struct MSH_MSG_AddressLookupReply *) msg_;
if (0 == (target_port = ntohs (msg->port)))
@@ -516,22 +539,65 @@
if ('\0' != msg->emsg[(size - sizeof (struct MSH_MSG_AddressLookup)) - 1])
{
GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
+ return GNUNET_SYSERR;
}
LOG_ERROR ("Address lookup for IP:%s failed with error: %s\n",
ip2str (target), msg->emsg);
- GNUNET_SCHEDULER_shutdown ();
- return;
+ return GNUNET_SYSERR;
}
target_connect ();
+ return GNUNET_OK;
}
/**
+ * Dispatcher for received messages
+ *
+ * @param cls connection context
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void
+dispatch (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+ struct ConnCtx *ctx = cls;
+ int ret;
+
+ if (NULL == msg)
+ goto err_ret;
+ switch (ntohs (msg->type))
+ {
+ case MSH_MTYPE_ADDRESS_LOOKUP_REPLY:
+ ret = handle_lookup_reply (ctx, msg);
+ break;
+ case MSH_MTYPE_CHALLENGE:
+ ret = handle_challenge (ctx, msg);
+ break;
+ case MSH_MTYPE_CHALLENGE_RESPONSE:
+ ret = handle_challenge_response (ctx, msg);
+ break;
+ case MSH_MTYPE_EXEC_BEGIN:
+ ret = handle_exec_begin (ctx, msg);
+ break;
+ case MSH_MTYPE_CMD_STREAM_STDOUT:
+ ret = handle_cmd_output (ctx, msg);
+ break;
+ default:
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Unrecognised message of type %u
received\n",
+ ntohs (msg->type));
+ goto err_ret;
+ }
+ GNUNET_CLIENT_receive (ctx->conn, &dispatch, ctx,
GNUNET_TIME_UNIT_FOREVER_REL);
+ return;
+
+ err_ret:
+ destroy_conn_ctx (ctx);
+}
+
+
+/**
* Function called with the result on the service test.
*
- * @param cls closure
+ * @param cls NULL
* @param result GNUNET_YES if the service is running,
* GNUNET_NO if the service is not running
* GNUNET_SYSERR if the configuration is invalid
@@ -548,21 +614,17 @@
LOG_ERROR ("Service not running\n");
return;
}
- client = GNUNET_CLIENT_connect (MSHD_LOCAL, cfg);
- GNUNET_assert (NULL != client);
+ ctx_local.conn = GNUNET_CLIENT_connect (MSHD_LOCAL, ctx_local.cfg);
+ GNUNET_assert (NULL != ctx_local.conn);
GNUNET_assert (0 != cmdstr_len);
size = sizeof (struct MSH_MSG_AddressLookup);
msg = GNUNET_malloc (size);
msg->header.size = htons (size);
msg->header.type = htons (MSH_MTYPE_ADDRESS_LOOKUP);
msg->ip = htonl ((uint32_t) target);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CLIENT_transmit_and_get_response (client, &msg->header,
-
GNUNET_TIME_UNIT_SECONDS,
- GNUNET_NO,
- &lookup_status,
- NULL));
- GNUNET_free (msg);
+ queue_message (&ctx_local, &msg->header);
+ GNUNET_CLIENT_receive (ctx_local.conn, &dispatch, &ctx_local,
+ GNUNET_TIME_UNIT_FOREVER_REL);
}
@@ -614,14 +676,11 @@
LOG_ERROR ("Could not find socket for local MSHD. Are we running under
MSHD?\n");
return;
}
- cfg = GNUNET_CONFIGURATION_dup (cfg_);
- GNUNET_CONFIGURATION_set_value_string (cfg, MSHD_LOCAL, "UNIXPATH",
psock_path);
- if (NULL == client)
- {
- LOG_ERROR ("Cannot open connection to MSHD\n");
- return;
- }
- test = GNUNET_CLIENT_service_test (MSHD_LOCAL, cfg, GNUNET_TIME_UNIT_SECONDS,
+ ctx_local.cfg = GNUNET_CONFIGURATION_dup (cfg_);
+ GNUNET_CONFIGURATION_set_value_string (ctx_local.cfg, MSHD_LOCAL,
+ "UNIXPATH", psock_path);
+ test = GNUNET_CLIENT_service_test (MSHD_LOCAL, ctx_local.cfg,
+ GNUNET_TIME_UNIT_SECONDS,
&result_cb, NULL);
}
Modified: msh/src/mshd-server.c
===================================================================
--- msh/src/mshd-server.c 2013-08-08 17:30:02 UTC (rev 28479)
+++ msh/src/mshd-server.c 2013-08-08 21:00:16 UTC (rev 28480)
@@ -14,6 +14,16 @@
#define MESSAGE_SEND_TIMEOUT(s) \
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s)
+#define LOG(kind,...) \
+ GNUNET_log_from (kind, "mshd-server", __VA_ARGS__)
+
+#define LOG_DEBUG(...) LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+#define LOG_ERROR(...) LOG(GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__)
+
+#define LOG_STRERROR(kind,cmd) \
+ GNUNET_log_from_strerror (kind, "mshd-error", cmd)
+
/**
* server handle for accepting requests from local MSH instances
*/
@@ -36,32 +46,74 @@
/**
- * Tranmission context
+ * Message queue for transmitting messages
*/
-struct TransmitCtx
+struct MessageQueue
{
- struct GNUNET_SERVER_Client *client;
-
+ /**
+ * next pointer for DLL
+ */
+ struct MessageQueue *next;
+
+ /**
+ * prev pointer for DLL
+ */
+ struct MessageQueue *prev;
+
+ /**
+ * The message to be sent
+ */
struct GNUNET_MessageHeader *msg;
-
};
+
/**
+ * Context associated with each client instance
+ */
+struct ClientCtx;
+
+
+/**
* Context for connections requiring to execute commands
*/
-struct ExecConnCtx
+struct ExecCtx
{
/**
- * the client handle
+ * associated client context
*/
- struct GNUNET_SERVER_Client *client;
-
+ struct ClientCtx *client_ctx;
+
/**
* The command strings to execute
*/
char **args;
/**
+ * the process handle to the command to execute
+ */
+ struct GNUNET_OS_Process *proc;
+
+ /**
+ * Input pipe handle for the process
+ */
+ struct GNUNET_DISK_PipeHandle *pin;
+
+ /**
+ * Input pipe handle for the process
+ */
+ struct GNUNET_DISK_PipeHandle *pout;
+
+ /**
+ * file handle for processes input
+ */
+ struct GNUNET_DISK_FileHandle *fin;
+
+ /**
+ * file handle for processes output
+ */
+ struct GNUNET_DISK_FileHandle *fout;
+
+ /**
* salt hash used for authentication
*/
struct GNUNET_HashCode salt;
@@ -72,6 +124,11 @@
GNUNET_SCHEDULER_TaskIdentifier timeout_task;
/**
+ * task to read the output from the process
+ */
+ GNUNET_SCHEDULER_TaskIdentifier fout_task;
+
+ /**
* the file descriptor associated with the client connection
*/
int conn_fd;
@@ -79,12 +136,98 @@
/**
+ * Context associated with each client instance
+ */
+struct ClientCtx
+{
+ /**
+ * The client handle
+ */
+ struct GNUNET_SERVER_Client *client;
+
+ /**
+ * The server to which this client has connected to
+ */
+ //struct GNUNET_SERVER_Handle *serv;
+
+ /**
+ * the transmission handle
+ */
+ struct GNUNET_SERVER_TransmitHandle *tx;
+
+ /**
+ * message queue head
+ */
+ struct MessageQueue *mq_head;
+
+ /**
+ * message queue tail
+ */
+ struct MessageQueue *mq_tail;
+
+ /**
+ * execution context. Set this for remote clients which ask us to execute a
+ * command
+ */
+ struct ExecCtx *exec_ctx;
+};
+
+
+/**
+ * Destroys an execution context
+ *
+ * @param ctx execution context
+ */
+static void
+destroy_exec_ctx (struct ExecCtx *ctx)
+{
+ unsigned int cnt;
+
+ GNUNET_break (0);
+ if (NULL != ctx->args)
+ {
+ for (cnt = 0; NULL != ctx->args[cnt]; cnt++)
+ GNUNET_free (ctx->args[cnt]);
+ GNUNET_free (ctx->args);
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != ctx->timeout_task)
+ GNUNET_SCHEDULER_cancel (ctx->timeout_task);
+ GNUNET_free (ctx);
+}
+
+
+/**
+ * Destroys a client context
+ *
+ * @param ctx the client context
+ */
+static void
+destroy_client_ctx (struct ClientCtx *ctx)
+{
+ struct MessageQueue *mq;
+
+ GNUNET_SERVER_client_drop (ctx->client);
+ if (NULL != ctx->tx)
+ GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx);
+ while (NULL != (mq = ctx->mq_head))
+ {
+ GNUNET_free (mq->msg);
+ GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq);
+ GNUNET_free (mq);
+ }
+ if (NULL != ctx->exec_ctx)
+ destroy_exec_ctx (ctx->exec_ctx);
+ GNUNET_free (ctx);
+}
+
+
+/**
* Function called to notify a client about the connection
* begin ready to queue more data. "buf" will be
* NULL and "size" zero if the connection was closed for
* writing in the meantime.
*
- * @param cls closure
+ * @param cls client context
* @param size number of bytes available in buf
* @param buf where the callee should write the message
* @return number of bytes written to buf
@@ -92,43 +235,67 @@
static size_t
transmit_ready_cb (void *cls, size_t size, void *buf)
{
- struct TransmitCtx *ctx = cls;
+ struct ClientCtx *ctx = cls;
struct GNUNET_SERVER_Client *client = ctx->client;
- struct GNUNET_MessageHeader *msg = ctx->msg;
+ struct MessageQueue *mq;
+ struct GNUNET_MessageHeader *msg;
size_t wrote;
+ ctx->tx = NULL;
wrote = 0;
if ((0 == size) || (NULL == buf))
- goto cleanup;
+ {
+ destroy_client_ctx (ctx);
+ return 0;
+ }
+ mq = ctx->mq_head;
+ msg = mq->msg;
wrote = ntohs (msg->size);
GNUNET_assert (size >= wrote);
(void) memcpy (buf, msg, wrote);
-
- cleanup:
- GNUNET_free (msg);
- GNUNET_SERVER_client_drop (client);
+ GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq);
+ GNUNET_free (mq->msg);
+ GNUNET_free (mq);
+ if (NULL != (mq = ctx->mq_head))
+ ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size),
+ MESSAGE_SEND_TIMEOUT (30),
+ &transmit_ready_cb, ctx);
GNUNET_SERVER_receive_done (client, GNUNET_YES);
return wrote;
}
+/**
+ * Queue a message into a clients message queue
+ *
+ * @param ctx the context associated with the client
+ * @param msg the message to queue. Will be consumed
+ */
static void
-send_message (struct GNUNET_SERVER_Client *client,
- struct GNUNET_MessageHeader *msg)
+queue_message (struct ClientCtx *ctx, struct GNUNET_MessageHeader *msg)
{
- struct TransmitCtx *ctx;
+ struct MessageQueue *mq;
+ struct GNUNET_SERVER_Client *client = ctx->client;
GNUNET_SERVER_client_keep (client);
- ctx = GNUNET_malloc (sizeof (struct TransmitCtx));
- ctx->client = client;
- ctx->msg = msg;
- (void) GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size),
- MESSAGE_SEND_TIMEOUT (30),
- &transmit_ready_cb, ctx);
-
+ mq = GNUNET_malloc (sizeof (struct MessageQueue));
+ mq->msg = msg;
+ GNUNET_CONTAINER_DLL_insert_tail (ctx->mq_head, ctx->mq_tail, mq);
+ if (NULL == ctx->tx)
+ ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size),
+ MESSAGE_SEND_TIMEOUT (30),
+ &transmit_ready_cb, ctx);
}
+/**
+ * Parse contingious 0-terminated strings from a buffer of given length
+ *
+ * @param buf the buffer
+ * @param size the size of the buffer
+ * @param s will contain the array of strings upon return
+ * @return the number of strings returned in the array
+ */
static int
parse_strings (const char *buf, size_t size, char ***s)
{
@@ -155,8 +322,15 @@
return cnt;
}
+
+/**
+ * Create a challenge message
+ *
+ * @param ctx the execution context
+ * @return the challenge message
+ */
static struct GNUNET_MessageHeader *
-create_challenge_message (struct ExecConnCtx *ctx)
+create_challenge_message (struct ExecCtx *ctx)
{
struct MSH_MSG_Challenge *msg;
uint16_t size;
@@ -171,25 +345,6 @@
}
-static void
-destroy_ctx (struct ExecConnCtx *ctx)
-{
- unsigned int cnt;
-
- if (NULL != ctx->client)
- GNUNET_SERVER_client_drop (ctx->client);
- if (NULL != ctx->args)
- {
- for (cnt = 0; NULL != ctx->args[cnt]; cnt++)
- GNUNET_free (ctx->args[cnt]);
- GNUNET_free (ctx->args);
- }
- if (GNUNET_SCHEDULER_NO_TASK != ctx->timeout_task)
- GNUNET_SCHEDULER_cancel (ctx->timeout_task);
- GNUNET_free (ctx);
-}
-
-
/**
* Functions with this signature are called whenever a message is
* received.
@@ -199,58 +354,22 @@
* @param message the actual message
*/
static void
-handle_runcmd (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader* message)
-{
- struct ExecConnCtx *ctx;
- const struct MSH_MSG_RunCmd *msg;
- struct GNUNET_MessageHeader *reply;
- uint16_t size;
-
- ctx = GNUNET_SERVER_client_get_user_context (client, struct ExecConnCtx);
- size = ntohs (message->size);
- if ( size <= sizeof (struct MSH_MSG_RunCmd))
- goto close_conn;
- msg = (const struct MSH_MSG_RunCmd *) message;
- if (0 == parse_strings (msg->cmd,
- size - sizeof (struct MSH_MSG_RunCmd),
- &ctx->args))
- goto close_conn;
- reply = create_challenge_message (ctx);
- send_message (client, reply);
- return;
-
- close_conn:
- GNUNET_break_op (0);
- destroy_ctx (ctx);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-}
-
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
handle_addresslookup (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader* message)
{
+ struct ClientCtx *ctx;
const struct MSH_MSG_AddressLookup *msg;
struct MSH_MSG_AddressLookupReply *reply;
- struct TransmitCtx *ctx;
struct InstanceAddr *iaddr;
char *emsg;
in_addr_t ip;
uint16_t port;
uint16_t reply_size;
-
+
emsg = NULL;
port = 0;
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx);
+ GNUNET_assert (NULL != ctx);
msg = (const struct MSH_MSG_AddressLookup *) message;
ip = ntohl (msg->ip);
if (GNUNET_NO == reversemap_check (rmap, ip))
@@ -272,11 +391,27 @@
reply->port = htons (port);
if (NULL != emsg)
(void) strcpy (reply->emsg, emsg);
- send_message (client, &reply->header);
+ queue_message (ctx, &reply->header);
}
/**
+ * Generate the credential for the given challenge
+ *
+ * @param c the challenge
+ * @param cred output parameter for the credential
+ */
+static void
+auth_challenge_cred (struct GNUNET_HashCode *c, struct GNUNET_HashCode *cred)
+{
+ struct GNUNET_HashCode xor;
+
+ GNUNET_CRYPTO_hash_xor (c, &shash, &xor);
+ GNUNET_CRYPTO_hash (&xor, sizeof (struct GNUNET_HashCode), cred);
+}
+
+
+/**
* Functions with this signature are called whenever a message is
* received.
*
@@ -288,23 +423,25 @@
handle_auth_challenge (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader* message)
{
+ struct ClientCtx *ctx;
const struct MSH_MSG_Challenge *msg;
struct MSH_MSG_ChallengeResponse *reply;
- struct GNUNET_HashCode salt;
- struct GNUNET_HashCode xor;
+ struct GNUNET_HashCode c;
+ struct GNUNET_HashCode cred;
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx);
+ GNUNET_assert (NULL != ctx);
msg = (const struct MSH_MSG_Challenge *) message;
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_hash_from_string2 (msg->salt.encoding,
sizeof (msg->salt),
- &salt));
- GNUNET_CRYPTO_hash_xor (&salt, &shash, &xor);
- GNUNET_CRYPTO_hash (&xor, sizeof (struct GNUNET_HashCode), &salt);
+ &c));
+ auth_challenge_cred (&c, &cred);
reply = GNUNET_malloc (sizeof (struct MSH_MSG_ChallengeResponse));
reply->header.size = htons (sizeof (struct MSH_MSG_ChallengeResponse));
reply->header.type = htons (MSH_MTYPE_CHALLENGE_RESPONSE);
- GNUNET_CRYPTO_hash_to_enc (&salt, &reply->auth);
- send_message (client, &reply->header);
+ GNUNET_CRYPTO_hash_to_enc (&cred, &reply->auth);
+ queue_message (ctx, &reply->header);
}
@@ -329,6 +466,24 @@
}
+/**
+ * Callback to be called when ever a client connects to the local server
+ *
+ * @param cls NULL
+ * @param client the client handle
+ */
+static void
+local_server_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+ struct ClientCtx *ctx;
+
+ ctx = GNUNET_malloc (sizeof (struct ClientCtx ));
+ ctx->client = client;
+ GNUNET_SERVER_client_set_user_context (client, ctx);
+}
+
+
+
int
init_local_server (const char *unixpath)
{
@@ -363,6 +518,7 @@
return GNUNET_SYSERR;
}
GNUNET_SERVER_add_handlers (local_serv, handlers);
+ GNUNET_SERVER_connect_notify (local_serv, &local_server_client_connect,
NULL);
return GNUNET_OK;
}
@@ -374,7 +530,69 @@
}
+/******************************************************************************/
+/* Daemon server. Responsbile for executing commands submitted by remote MSH
*/
+/* clients
*/
+/******************************************************************************/
+
+
/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_runcmd (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader* message)
+{
+ struct ClientCtx *ctx;
+ struct ExecCtx *exec_ctx;
+ const struct MSH_MSG_RunCmd *msg;
+ struct GNUNET_MessageHeader *reply;
+ uint16_t size;
+
+ LOG_DEBUG ("Received a RUN_CMD message\n");
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx);
+ exec_ctx = ctx->exec_ctx;
+ GNUNET_assert (NULL != exec_ctx);
+ if (NULL != exec_ctx->args)
+ {
+ GNUNET_break (0);
+ goto close_conn;
+ }
+ size = ntohs (message->size);
+ if ( size <= sizeof (struct MSH_MSG_RunCmd))
+ {
+ GNUNET_break_op (0);
+ goto close_conn;
+ }
+ msg = (const struct MSH_MSG_RunCmd *) message;
+ exec_ctx = GNUNET_malloc (sizeof (struct ExecCtx));
+ ctx->exec_ctx = exec_ctx;
+ if (0 == parse_strings (msg->cmd,
+ size - sizeof (struct MSH_MSG_RunCmd),
+ &exec_ctx->args))
+ {
+ GNUNET_break_op (0);
+ goto close_conn;
+ }
+ reply = create_challenge_message (exec_ctx);
+ LOG_DEBUG ("Sending AUTH_CHALLENGE\n");
+ queue_message (ctx, reply);
+ return;
+
+ close_conn:
+ GNUNET_break_op (0);
+ destroy_client_ctx (ctx);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
* Function to call for access control checks.
*
* @param cls closure
@@ -394,6 +612,122 @@
/**
+ * Task to read the output from a process and send it to client
+ *
+ * @param cls the execution context
+ * @param tc scheduler task context
+ */
+static void
+read_fout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ExecCtx *ctx = cls;
+ struct MSH_MSG_CmdIO *msg;
+ static char data[MAX_IO_DATA];
+ ssize_t size;
+ uint16_t msize;
+
+ ctx->fout_task = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+ {
+ return;
+ }
+ size = GNUNET_DISK_file_read_non_blocking (ctx->fout, data, MAX_IO_DATA);
+ GNUNET_assert (size > 0);
+ msize = size + sizeof (struct MSH_MSG_CmdIO);
+ msg = GNUNET_malloc (msize);
+ msg->header.type = htons (MSH_MTYPE_CMD_STREAM_STDOUT);
+ msg->header.size = htons (msize);
+ memcpy (msg->data, data, size);
+ queue_message (ctx->client_ctx, &msg->header);
+}
+
+
+/**
+ * start the process from the execution process
+ *
+ * @param ctx the execution context
+ * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ */
+static int
+exec_proc (struct ExecCtx *ctx)
+{
+ ctx->pin = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 0, 0);
+ ctx->pout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 0, 0);
+ GNUNET_assert ((NULL != ctx->pin && (NULL != ctx->pout)));
+ ctx->fin = GNUNET_DISK_pipe_detach_end (ctx->pin,
GNUNET_DISK_PIPE_END_WRITE);
+ ctx->fout = GNUNET_DISK_pipe_detach_end (ctx->pin,
GNUNET_DISK_PIPE_END_READ);
+ GNUNET_assert ((NULL != ctx->fin && (NULL != ctx->fout)));
+ ctx->proc = GNUNET_OS_start_process_vap (GNUNET_NO,
+ GNUNET_OS_INHERIT_STD_NONE,
+ ctx->pin,
+ ctx->pout,
+ ctx->args[0],
+ ctx->args);
+ if (NULL == ctx->proc)
+ return GNUNET_SYSERR;
+ ctx->fout_task =
+ GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ ctx->fout, read_fout, ctx);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_auth_challenge_response (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader* message)
+{
+ const struct MSH_MSG_ChallengeResponse *msg;
+ struct GNUNET_MessageHeader *reply;
+ struct ClientCtx *ctx;
+ struct ExecCtx *exec_ctx;
+ struct GNUNET_HashCode cred;
+ struct GNUNET_CRYPTO_HashAsciiEncoded enc;
+
+ ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx);
+ if (NULL == ctx)
+ {
+ GNUNET_break_op (0);
+ goto err_ret;
+ }
+ exec_ctx = ctx->exec_ctx;
+ GNUNET_assert (NULL != exec_ctx);
+ auth_challenge_cred (&exec_ctx->salt, &cred);
+ GNUNET_CRYPTO_hash_to_enc (&cred, &enc);
+ msg = (const struct MSH_MSG_ChallengeResponse *) message;
+ if (0 != memcmp (&msg->auth, &cred,
+ sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
+ {
+ GNUNET_break (0);
+ goto err_ret;
+ }
+ if (GNUNET_OK != exec_proc (exec_ctx))
+ {
+ GNUNET_break (0);
+ goto err_ret;
+ }
+ reply = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
+ reply->size = htons (sizeof (struct GNUNET_MessageHeader));
+ reply->type = htons (MSH_MTYPE_EXEC_BEGIN);
+ queue_message (ctx, reply);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+
+ err_ret:
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ destroy_client_ctx (ctx);
+}
+
+
+/**
* Initialises the server which spawns processes and forwards it stdin and
stdout
*
* @param h the network handle of the socket to listen for incoming connections
@@ -403,6 +737,8 @@
{
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
{&handle_runcmd, NULL, MSH_MTYPE_RUNCMD, 0},
+ {&handle_auth_challenge_response, NULL, MSH_MTYPE_CHALLENGE_RESPONSE,
+ sizeof (struct MSH_MSG_ChallengeResponse)},
{NULL, NULL, 0, 0}
};
@@ -421,10 +757,11 @@
static void
timeout_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct ExecConnCtx *ctx = cls;
+ struct ClientCtx *ctx = cls;
+ struct ExecCtx *exec_ctx = ctx->exec_ctx;
- ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- destroy_ctx (ctx);
+ exec_ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ destroy_client_ctx (ctx);
}
@@ -432,13 +769,17 @@
daemon_server_add_connection (struct GNUNET_CONNECTION_Handle *conn,
int conn_fd)
{
- struct ExecConnCtx *ctx;
+ struct ClientCtx *ctx;
+ struct ExecCtx *exec_ctx;
- ctx = GNUNET_malloc (sizeof (struct ExecConnCtx));
- ctx->conn_fd = conn_fd;
+ ctx = GNUNET_malloc (sizeof (struct ClientCtx));
+ exec_ctx = GNUNET_malloc (sizeof (struct ExecCtx));
+ exec_ctx->client_ctx = ctx;
+ ctx->exec_ctx = exec_ctx;
+ exec_ctx->conn_fd = conn_fd;
ctx->client = GNUNET_SERVER_connect_socket (daemon_serv, conn);
GNUNET_SERVER_client_set_user_context (ctx->client, ctx);
- ctx->timeout_task =
+ exec_ctx->timeout_task =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &timeout_cb,
ctx);
}
Modified: msh/src/mshd.c
===================================================================
--- msh/src/mshd.c 2013-08-08 17:30:02 UTC (rev 28479)
+++ msh/src/mshd.c 2013-08-08 21:00:16 UTC (rev 28480)
@@ -178,6 +178,11 @@
static struct GNUNET_NETWORK_Handle *listen_socket;
/**
+ * The process handle of the process started by instance running with rank 0
+ */
+static struct GNUNET_OS_Process *proc;
+
+/**
* Task for running a round
*/
static GNUNET_SCHEDULER_TaskIdentifier rtask;
@@ -425,8 +430,18 @@
(void) unlink (unixpath);
setenv (MSHD_SOCK_NAME, unixpath, 1);
- GNUNET_break (0); /* FIXME: start process */
- /* process = GNUNET_OS_start_process_vap () */
+ proc = GNUNET_OS_start_process_vap (GNUNET_NO,
+ GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+ NULL,
+ NULL,
+ run_args[0],
+ run_args);
+ if (NULL == proc)
+ {
+ GNUNET_break (0);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
}
}
Modified: msh/src/mtypes.h
===================================================================
--- msh/src/mtypes.h 2013-08-08 17:30:02 UTC (rev 28479)
+++ msh/src/mtypes.h 2013-08-08 21:00:16 UTC (rev 28480)
@@ -108,8 +108,6 @@
#define MSH_MTYPE_RUNCMD 200
-#define MSH_MTYPE_RUNCMDSTATUS 201
-
#define MSH_MTYPE_CMD_STREAM_STDIN 202
#define MSH_MTYPE_CMD_STREAM_STDOUT 203
@@ -122,6 +120,8 @@
#define MSH_MTYPE_CHALLENGE_RESPONSE 207
+#define MSH_MTYPE_EXEC_BEGIN 208
+
/**
* Message for sending a remote command and its arguments to MSHD
*/
@@ -175,6 +175,7 @@
char data[0];
};
+#define MAX_IO_DATA (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct
MSH_MSG_CmdIO))
struct MSH_MSG_AddressLookup
{
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r28480 - msh/src,
gnunet <=