/** * Transmit the given message to the client. * * @param client target of the message * @param msg message to transmit, will be freed! */ static void transmit (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg) { struct TransmitCallbackContext *tcc; if (GNUNET_YES == cleaning_done) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Shutdown in progress, aborting transmission.\n")); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free (msg); return; } tcc = GNUNET_new (struct TransmitCallbackContext); tcc->msg = msg; tcc->client = client; if (NULL == (tcc->th = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_callback, tcc))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free (msg); GNUNET_free (tcc); return; } GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert (tcc_head, tcc_tail, tcc); }
/** * Queues a message in send queue for sending to the service * * @param client the client to whom the queued message has to be sent * @param msg the message to queue */ void GST_queue_message (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq_entry; uint16_t type; uint16_t size; type = ntohs (msg->type); size = ntohs (msg->size); GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); mq_entry = GNUNET_new (struct MessageQueue); mq_entry->msg = msg; mq_entry->client = client; GNUNET_SERVER_client_keep (client); LOG_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_entry); if (NULL == transmit_handle) transmit_handle = GNUNET_SERVER_notify_transmit_ready (client, size, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_ready_notify, NULL); }
/** * Handle STOP-message. * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static void handle_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ServiceList *sl; const char *servicename; uint16_t size; size = ntohs (message->size); size -= sizeof (struct GNUNET_MessageHeader); servicename = (const char *) &message[1]; if ((size == 0) || (servicename[size - 1] != '\0')) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Preparing to stop `%s'\n"), servicename); sl = find_service (servicename); if (sl == NULL) { signal_result (client, servicename, GNUNET_ARM_PROCESS_UNKNOWN); return; } sl->is_default = GNUNET_NO; if (GNUNET_YES == in_shutdown) { /* shutdown in progress */ signal_result (client, servicename, GNUNET_ARM_PROCESS_SHUTDOWN); return; } if (sl->killing_client != NULL) { /* killing already in progress */ signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_STOPPING); return; } if (sl->proc == NULL) { /* process is down */ signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_DOWN); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kill signal to service `%s', waiting for process to die.\n", servicename); sl->killed_at = GNUNET_TIME_absolute_get (); if (0 != GNUNET_OS_process_kill (sl->proc, SIGTERM)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); sl->killing_client = client; GNUNET_SERVER_client_keep (client); }
/** * Create a new transmission context for the * given client. * * @param client client to create the context for. * @return NULL on error */ struct GNUNET_SERVER_TransmitContext * GNUNET_SERVER_transmit_context_create (struct GNUNET_SERVER_Client *client) { struct GNUNET_SERVER_TransmitContext *tc; GNUNET_assert (NULL != client); tc = GNUNET_new (struct GNUNET_SERVER_TransmitContext); GNUNET_SERVER_client_keep (client); tc->client = client; return tc; }
static void recv_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_assert (ok == 2); ok = 3; GNUNET_SERVER_client_keep (client); GNUNET_SCHEDULER_add_now (&server_disconnect, client); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); GNUNET_assert (MY_TYPE == ntohs (message->type)); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_server_client (struct GNUNET_SERVER_Client *client) { struct GNUNET_MQ_Handle *mq; struct ServerClientSocketState *scss; mq = GNUNET_new (struct GNUNET_MQ_Handle); scss = GNUNET_new (struct ServerClientSocketState); mq->impl_state = scss; scss->client = client; GNUNET_SERVER_client_keep (client); mq->send_impl = server_client_send_impl; mq->destroy_impl = server_client_destroy_impl; return mq; }
static void recv_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_assert (ok == 2); ok = 3; argclient = client; GNUNET_SERVER_client_keep (argclient); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); GNUNET_assert (MY_TYPE == ntohs (message->type)); GNUNET_assert (NULL != GNUNET_SERVER_notify_transmit_ready (client, ntohs (message->size), TIMEOUT, &reply_msg, NULL)); }
/** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void handle_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_InitMessage *msg; struct GNUNET_TESTBED_Host *host; const char *controller_hostname; char *ss_str; struct GNUNET_TESTING_SharedService *ss; unsigned int cnt; uint16_t msize; if (NULL != GST_context) { LOG_DEBUG ("We are being connected to laterally\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } msg = (const struct GNUNET_TESTBED_InitMessage *) message; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize -= sizeof (struct GNUNET_TESTBED_InitMessage); controller_hostname = (const char *) &msg[1]; if ('\0' != controller_hostname[msize - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ss_str = NULL; ss = NULL; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED", "SHARED_SERVICES", &ss_str)) { ss = parse_shared_services (ss_str, GST_config); GNUNET_free (ss_str); ss_str = NULL; } GST_context = GNUNET_new (struct Context); GNUNET_SERVER_client_keep (client); GST_context->client = client; GST_context->host_id = ntohl (msg->host_id); GST_context->master_ip = GNUNET_strdup (controller_hostname); LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip); GST_context->system = GNUNET_TESTING_system_create ("testbed", GST_context->master_ip, hostname, ss); if (NULL != ss) { for (cnt = 0; NULL != ss[cnt].service; cnt++) { ss_str = (char *) ss[cnt].service; GNUNET_free (ss_str); } GNUNET_free (ss); ss = NULL; } host = GNUNET_TESTBED_host_create_with_id (GST_context->host_id, GST_context->master_ip, NULL, GST_config, 0); host_list_add (host); LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Client asked for transmission to a peer. Process the request. * * @param cls unused * @param client the client * @param message the send message that was sent */ static void clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct OutboundMessage *obm; const struct GNUNET_MessageHeader *obmm; struct SendTransmitContinuationContext *stcc; uint16_t size; uint16_t msize; struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) { /* client asked for transmission before 'START' */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size = ntohs (message->size); if (size < sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } obm = (const struct OutboundMessage *) message; obmm = (const struct GNUNET_MessageHeader *) &obm[1]; msize = size - sizeof (struct OutboundMessage); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n", "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize); if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) { /* not connected, not allowed to send; can happen due to asynchronous operations */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not send message to peer `%s': not connected\n", GNUNET_i2s (&obm->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload dropped (other peer was not connected)"), msize, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); stcc = GNUNET_new (struct SendTransmitContinuationContext); stcc->target = obm->peer; stcc->client = client; GNUNET_SERVER_client_keep (client); GST_manipulation_send (&obm->peer, obmm, msize, GNUNET_TIME_relative_ntoh (obm->timeout), &handle_send_transmit_continuation, stcc); }
/** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_ControllerLinkRequest *msg; struct LCFContextQueue *lcfq; struct Route *route; struct Route *new_route; uint64_t op_id; uint32_t delegated_host_id; uint32_t slave_host_id; if (NULL == GST_context) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message; delegated_host_id = ntohl (msg->delegated_host_id); if (delegated_host_id == GST_context->host_id) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if ((delegated_host_id >= GST_host_list_size) || (NULL == GST_host_list[delegated_host_id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host %u not registered with us\n", delegated_host_id); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } slave_host_id = ntohl (msg->slave_host_id); if ((slave_host_id >= GST_host_list_size) || (NULL == GST_host_list[slave_host_id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n", slave_host_id); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (slave_host_id == delegated_host_id) { LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } op_id = GNUNET_ntohll (msg->operation_id); if (slave_host_id == GST_context->host_id) /* Link from us */ { struct Slave *slave; struct LinkControllersContext *lcc; if (1 != msg->is_subordinate) { struct Neighbour *n; struct NeighbourConnectCtxt *ncc; if ((delegated_host_id < neighbour_list_size) && (NULL != neighbour_list[delegated_host_id])) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG_DEBUG ("Received request to establish a link to host %u\n", delegated_host_id); n = GST_create_neighbour (GST_host_list[delegated_host_id]); ncc = GNUNET_new (struct NeighbourConnectCtxt); ncc->n = n; ncc->op_id = op_id; ncc->client = client; GNUNET_SERVER_client_keep (client); ncc->nh = GST_neighbour_get_connection (n, neighbour_connect_cb, ncc); ncc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_neighbour_connect, ncc); GNUNET_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if ((delegated_host_id < GST_slave_list_size) && (NULL != GST_slave_list[delegated_host_id])) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG_DEBUG ("Received request to start and establish a link to host %u\n", delegated_host_id); slave = GNUNET_new (struct Slave); slave->host_id = delegated_host_id; slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); slave_list_add (slave); lcc = GNUNET_new (struct LinkControllersContext); lcc->operation_id = op_id; GNUNET_SERVER_client_keep (client); lcc->client = client; slave->lcc = lcc; slave->controller_proc = GNUNET_TESTBED_controller_start (GST_context->master_ip, GST_host_list[slave->host_id], &slave_status_cb, slave); new_route = GNUNET_new (struct Route); new_route->dest = delegated_host_id; new_route->thru = GST_context->host_id; route_list_add (new_route); return; } /* Route the request */ if (slave_host_id >= route_list_size) { LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } lcfq = GNUNET_new (struct LCFContextQueue); lcfq->lcf = GNUNET_new (struct LCFContext); lcfq->lcf->delegated_host_id = delegated_host_id; lcfq->lcf->slave_host_id = slave_host_id; route = GST_find_dest_route (slave_host_id); GNUNET_assert (NULL != route); /* because we add routes carefully */ GNUNET_assert (route->dest < GST_slave_list_size); GNUNET_assert (NULL != GST_slave_list[route->dest]); lcfq->lcf->is_subordinate = msg->is_subordinate; lcfq->lcf->state = INIT; lcfq->lcf->operation_id = op_id; lcfq->lcf->gateway = GST_slave_list[route->dest]; GNUNET_SERVER_client_keep (client); lcfq->lcf->client = client; if (NULL == lcfq_head) { GNUNET_assert (NULL == lcf_proc_task_id); GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf); } else GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); /* FIXME: Adding a new route should happen after the controllers are linked * successfully */ if (1 != msg->is_subordinate) { GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if ((delegated_host_id < route_list_size) && (NULL != route_list[delegated_host_id])) { GNUNET_break_op (0); /* Are you trying to link delegated host twice * with is subordinate flag set to GNUNET_YES? */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } new_route = GNUNET_new (struct Route); new_route->dest = delegated_host_id; new_route->thru = route->dest; route_list_add (new_route); GNUNET_SERVER_receive_done (client, GNUNET_OK); }