示例#1
0
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls closure
 * @param msg message received, NULL on timeout or fatal error
 */
static void
message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
    struct GNUNET_NSE_Handle *h = cls;
    const struct GNUNET_NSE_ClientMessage *client_msg;

    if (msg == NULL)
    {
        /* Error, timeout, death */
        GNUNET_CLIENT_disconnect (h->client);
        h->client = NULL;
        h->reconnect_task =
            GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
        return;
    }
    if ((ntohs (msg->size) != sizeof (struct GNUNET_NSE_ClientMessage)) ||
            (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_NSE_ESTIMATE))
    {
        GNUNET_break (0);
        return;
    }
    client_msg = (const struct GNUNET_NSE_ClientMessage *) msg;
    h->recv_cb (h->recv_cb_cls, GNUNET_TIME_absolute_ntoh (client_msg->timestamp),
                GNUNET_ntoh_double (client_msg->size_estimate),
                GNUNET_ntoh_double (client_msg->std_deviation));
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
}
示例#2
0
/**
 * Transmit START message to service.
 *
 * @param cls unused
 * @param size number of bytes available in buf
 * @param buf where to copy the message
 * @return number of bytes copied to buf
 */
static size_t
send_start (void *cls, size_t size, void *buf)
{
    struct GNUNET_NSE_Handle *h = cls;
    struct GNUNET_MessageHeader *msg;

    h->th = NULL;
    if (buf == NULL)
    {
        /* Connect error... */
        LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Shutdown while trying to transmit `%s' request.\n", "START");
        reschedule_connect (h);
        return 0;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "START");
    GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));

    msg = (struct GNUNET_MessageHeader *) buf;
    msg->size = htons (sizeof (struct GNUNET_MessageHeader));
    msg->type = htons (GNUNET_MESSAGE_TYPE_NSE_START);
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
    return sizeof (struct GNUNET_MessageHeader);
}
示例#3
0
文件: client.c 项目: muggenhor/GNUnet
/**
 * Send the 'TEST' message to the service.  If successful, prepare to
 * receive the reply.
 *
 * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test
 * @param size number of bytes available in @a buf
 * @param buf where to write the message
 * @return number of bytes written to @a buf
 */
static size_t
write_test (void *cls, size_t size, void *buf)
{
  struct GNUNET_CLIENT_TestHandle *th = cls;
  struct GNUNET_MessageHeader *msg;

  th->th = NULL;
  if (size < sizeof (struct GNUNET_MessageHeader))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "Failed to transmit TEST request.\n");
    service_test_report (th, GNUNET_NO);
    return 0;                   /* client disconnected */
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmitting `%s' request.\n",
       "TEST");
  msg = (struct GNUNET_MessageHeader *) buf;
  msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
  GNUNET_CLIENT_receive (th->client,
			 &confirm_handler, th,
                         GNUNET_TIME_absolute_get_remaining
                         (th->test_deadline));
  return sizeof (struct GNUNET_MessageHeader);
}
示例#4
0
/**
 * Handler for ARM 'termination' reply (failure to receive).
 *
 * @param cls our "struct GNUNET_ARM_Handle"
 * @param msg expected to be NULL
 */
static void
arm_termination_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_ARM_Handle *h = cls;
  struct ARMControlMessage *cm;

  if (NULL != msg)
  {
    GNUNET_break (0);
    GNUNET_CLIENT_receive (h->client, &arm_termination_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    return;
  }
  cm = h->thm;
  h->thm = NULL;
  h->currently_down = GNUNET_YES;
  GNUNET_CLIENT_disconnect (h->client);
  h->client = NULL;
  if (NULL != cm->result_cont)
    cm->result_cont (cm->cont_cls,
		     GNUNET_ARM_REQUEST_SENT_OK,
		     (const char *) &cm->msg[1],
		     GNUNET_ARM_RESULT_STOPPED);
  GNUNET_free (cm->msg);
  GNUNET_free (cm);
}
/**
 * If possible, write a shutdown message to the target
 * buffer and destroy the client connection.
 *
 * @param cls the "struct GNUNET_CLIENT_Connection" to destroy
 * @param size number of bytes available in buf
 * @param buf NULL on error, otherwise target buffer
 * @return number of bytes written to buf
 */
static size_t
write_shutdown (void *cls, size_t size, void *buf)
{
  struct GNUNET_MessageHeader *msg;
  struct ShutdownContext *shutdown_ctx = cls;

  if (size < sizeof (struct GNUNET_MessageHeader))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		  _("Failed to transmit shutdown request to client.\n"));
      shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR);
      GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
      GNUNET_free (shutdown_ctx);
      return 0;			/* client disconnected */
    }

  GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler,
			 shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL);
  shutdown_ctx->cancel_task =
    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
				  (shutdown_ctx->timeout),
				  &service_shutdown_cancel, shutdown_ctx);
  msg = (struct GNUNET_MessageHeader *) buf;
  msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN);
  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
  return sizeof (struct GNUNET_MessageHeader);
}
示例#6
0
/**
 * We've transmitted the iteration request.  Now get ready to process
 * the results (or handle transmission error).
 *
 * @param cls the 'struct GNUNET_PEERINFO_IteratorContext'
 * @param emsg error message, NULL if transmission worked
 */
static void
iterator_start_receive (void *cls, const char *emsg)
{
  struct GNUNET_PEERINFO_IteratorContext *ic = cls;
  struct GNUNET_PEERINFO_Handle *h = ic->h;
  GNUNET_PEERINFO_Processor cb;
  void *cb_cls;

  ic->ac = NULL;
  if (NULL != emsg)
  {
    cb = ic->callback;
    cb_cls = ic->callback_cls;
    GNUNET_PEERINFO_iterate_cancel (ic);
    reconnect (h);
    if (NULL != cb)
      cb (cb_cls, NULL, NULL, emsg);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n",
       "PEERINFO");
  ic->in_receive = GNUNET_YES;
  if (GNUNET_NO == h->in_receive)
  {
    h->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (h->client, &peerinfo_handler, h,
			   GNUNET_TIME_absolute_get_remaining (ic->timeout));
  }
}
示例#7
0
文件: client.c 项目: muggenhor/GNUnet
/**
 * Function called to notify a client about the socket
 * begin ready to queue the message.  @a buf will be
 * NULL and @a size zero if the socket was closed for
 * writing in the meantime.
 *
 * @param cls closure of type `struct TransmitGetResponseContext *`
 * @param size number of bytes available in @a buf
 * @param buf where the callee should write the message
 * @return number of bytes written to @a buf
 */
static size_t
transmit_for_response (void *cls,
		       size_t size,
		       void *buf)
{
  struct TransmitGetResponseContext *tc = cls;
  uint16_t msize;

  tc->client->tag = NULL;
  msize = ntohs (tc->hdr->size);
  if (NULL == buf)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Could not submit request, not expecting to receive a response.\n");
    if (NULL != tc->rn)
      tc->rn (tc->rn_cls, NULL);
    GNUNET_free (tc);
    return 0;
  }
  GNUNET_assert (size >= msize);
  memcpy (buf, tc->hdr, msize);
  GNUNET_CLIENT_receive (tc->client,
                         tc->rn,
                         tc->rn_cls,
                         GNUNET_TIME_absolute_get_remaining (tc->timeout));
  GNUNET_free (tc);
  return msize;
}
示例#8
0
/**
 * We can now transmit a message to NAMESTORE. Do it.
 *
 * @param cls the 'struct GNUNET_NAMESTORE_Handle'
 * @param size number of bytes we can transmit
 * @param buf where to copy the messages
 * @return number of bytes copied into buf
 */
static size_t
transmit_message_to_namestore (void *cls, size_t size, void *buf)
{
  struct GNUNET_NAMESTORE_Handle *h = cls;
  struct PendingMessage *p;
  size_t ret;
  char *cbuf;

  h->th = NULL;
  if ((size == 0) || (buf == NULL))
  {
    force_reconnect (h);
    return 0;
  }
  ret = 0;
  cbuf = buf;
  while ((NULL != (p = h->pending_head)) && (p->size <= size))
  {
    memcpy (&cbuf[ret], &p[1], p->size);
    ret += p->size;
    size -= p->size;
    GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p);
    if (GNUNET_YES == p->is_init)
      GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
                             GNUNET_TIME_UNIT_FOREVER_REL);
    GNUNET_free (p);
  }
  do_transmit (h);
  return ret;
}
示例#9
0
文件: dns_api.c 项目: tg-x/gnunet
/**
 * Callback called by notify_transmit_ready; sends DNS replies
 * to the DNS service.
 *
 * @param cls the struct GNUNET_DNS_Handle
 * @param size number of bytes available in buf
 * @param buf where to copy the message for transmission
 * @return number of bytes copied to buf
 */
static size_t
send_response (void *cls, size_t size, void *buf)
{
  struct GNUNET_DNS_Handle *dh = cls;
  struct ReplyQueueEntry *qe;
  size_t len;

  dh->dns_transmit_handle = NULL;
  if (NULL == buf)
  {
    disconnect (dh);
    dh->reconnect_task =
      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
				    &reconnect, dh);
    return 0;
  }
  qe = dh->rq_head;
  if (NULL == qe)
    return 0;
  len = ntohs (qe->msg->size);
  if (len > size)
  {
    dh->dns_transmit_handle =
      GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
					   len,
					   GNUNET_TIME_UNIT_FOREVER_REL,
					   GNUNET_NO,
					   &send_response, dh);
    return 0;
  }
  memcpy (buf, qe->msg, len);
  GNUNET_CONTAINER_DLL_remove (dh->rq_head,
			       dh->rq_tail,
			       qe);
  GNUNET_free (qe);
  if (GNUNET_NO == dh->in_receive)
  {
    dh->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (dh->dns_connection,
			   &request_handler, dh,
			   GNUNET_TIME_UNIT_FOREVER_REL);
  }
  if (NULL != (qe = dh->rq_head))
  {
    dh->dns_transmit_handle =
      GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection,
					   ntohs (qe->msg->size),
					   GNUNET_TIME_UNIT_FOREVER_REL,
					   GNUNET_NO,
					   &send_response, dh);
  }
  return len;
}
示例#10
0
/**
 * Transmit a join request to the chat service.
 *
 * @param cls closure, pointer to the 'struct GNUNET_CHAT_Room'
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
transmit_join_request (void *cls, size_t size, void *buf)
{
  struct GNUNET_CHAT_Room *chat_room = cls;
  struct JoinRequestMessage *join_msg;
  char *room;
  char *meta;
  size_t room_len;
  ssize_t meta_len;
  size_t size_of_join;

  if (NULL == buf)
  {
#if DEBUG_CHAT
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Could not transmit join request, retrying...\n");
#endif
    rejoin_room (chat_room);
    return 0;
  }
#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Transmitting join request to the service\n");
#endif
  room_len = strlen (chat_room->room_name);
  meta_len =
      GNUNET_CONTAINER_meta_data_get_serialized_size (chat_room->member_info);
  size_of_join = sizeof (struct JoinRequestMessage) + meta_len + room_len;
  GNUNET_assert (size >= size_of_join);
  join_msg = buf;
  join_msg->header.size = htons (size);
  join_msg->header.type = htons (GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST);
  join_msg->msg_options = htonl (chat_room->msg_options);
  join_msg->room_name_len = htons (room_len);
  join_msg->reserved = htons (0);
  join_msg->reserved2 = htonl (0);
  GNUNET_CRYPTO_rsa_key_get_public (chat_room->my_private_key,
                                    &join_msg->public_key);
  room = (char *) &join_msg[1];
  memcpy (room, chat_room->room_name, room_len);
  meta = &room[room_len];
  if (GNUNET_SYSERR ==
      GNUNET_CONTAINER_meta_data_serialize (chat_room->member_info, &meta,
                                            meta_len,
                                            GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not serialize metadata\n"));
    return 0;
  }
  GNUNET_CLIENT_receive (chat_room->client, &receive_results, chat_room,
                         GNUNET_TIME_UNIT_FOREVER_REL);
  return size_of_join;
}
示例#11
0
/**
 * Transmit the next pending message, called by notify_transmit_ready
 *
 * @param cls the DHT handle
 * @param size number of bytes available in @a buf for transmission
 * @param buf where to copy messages for the service
 * @return number of bytes written to @a buf
 */
static size_t
transmit_pending (void *cls,
		  size_t size,
		  void *buf)
{
  struct GNUNET_DHT_Handle *handle = cls;
  struct PendingMessage *head;
  size_t tsize;


  handle->th = NULL;
  if (NULL == buf)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmission to DHT service failed!  Reconnecting!\n");
    do_disconnect (handle);
    return 0;
  }
  if (NULL == (head = handle->pending_head))
    return 0;

  tsize = ntohs (head->msg->size);
  if (size < tsize)
  {
    process_pending_messages (handle);
    return 0;
  }
  memcpy (buf, head->msg, tsize);
  GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail,
                               head);
  head->in_pending_queue = GNUNET_NO;
  if (NULL != head->cont)
  {
    head->cont (head->cont_cls, NULL);
    head->cont = NULL;
    head->cont_cls = NULL;
  }
  if (GNUNET_YES == head->free_on_send)
    GNUNET_free (head);
  process_pending_messages (handle);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Forwarded request of %u bytes to DHT service\n", (unsigned int) tsize);
  if (GNUNET_NO == handle->in_receive)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting to process replies from DHT\n");
    handle->in_receive = GNUNET_YES;
    
    GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle,
                           GNUNET_TIME_UNIT_FOREVER_REL);
  }
  return tsize;
}
示例#12
0
/**
 * Function called on each response from the FS
 * service with information about indexed files.
 *
 * @param cls closure (of type "struct GNUNET_FS_GetIndexedContext*")
 * @param msg message with indexing information
 */
static void
handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_FS_GetIndexedContext *gic = cls;
  const struct IndexInfoMessage *iim;
  uint16_t msize;
  const char *filename;

  if (NULL == msg)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _
                ("Failed to receive response for `%s' request from `%s' service.\n"),
                "GET_INDEXED", "fs");
    (void) gic->iterator (gic->iterator_cls, NULL, NULL);
    GNUNET_FS_get_indexed_files_cancel (gic);
    return;
  }
  if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END)
  {
    /* normal end-of-list */
    (void) gic->iterator (gic->iterator_cls, NULL, NULL);
    GNUNET_FS_get_indexed_files_cancel (gic);
    return;
  }
  msize = ntohs (msg->size);
  iim = (const struct IndexInfoMessage *) msg;
  filename = (const char *) &iim[1];
  if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY) ||
      (msize <= sizeof (struct IndexInfoMessage)) ||
      (filename[msize - sizeof (struct IndexInfoMessage) - 1] != '\0'))
  {
    /* bogus reply */
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _
                ("Failed to receive valid response for `%s' request from `%s' service.\n"),
                "GET_INDEXED", "fs");
    (void) gic->iterator (gic->iterator_cls, NULL, NULL);
    GNUNET_FS_get_indexed_files_cancel (gic);
    return;
  }
  if (GNUNET_OK != gic->iterator (gic->iterator_cls, filename, &iim->file_id))
  {
    GNUNET_FS_get_indexed_files_cancel (gic);
    return;
  }
  /* get more */
  GNUNET_CLIENT_receive (gic->client, &handle_index_info, gic,
                         GNUNET_CONSTANTS_SERVICE_TIMEOUT);
}
示例#13
0
/**
 * Callback function for data received from the network.  Note that
 * both "available" and "errCode" would be 0 if the read simply timed out.
 *
 * @param cls closure
 * @param buf pointer to received data
 * @param available number of bytes availabe in "buf",
 *        possibly 0 (on errors)
 * @param addr address of the sender
 * @param addrlen size of addr
 * @param errCode value of errno (on errors receiving)
 */
static void
receive_helper (void *cls, const void *buf, size_t available,
                const struct sockaddr *addr, socklen_t addrlen, int errCode)
{
  struct GNUNET_CLIENT_Connection *client = cls;
  struct GNUNET_TIME_Relative remaining;
  GNUNET_CLIENT_MessageHandler receive_handler;
  void *receive_handler_cls;

  GNUNET_assert (GNUNET_NO == client->msg_complete);
  GNUNET_assert (GNUNET_YES == client->in_receive);
  client->in_receive = GNUNET_NO;
  if ((0 == available) || (NULL == client->connection) || (0 != errCode))
  {
    /* signal timeout! */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n",
         (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL",
         STRERROR (errCode));
    if (NULL != (receive_handler = client->receiver_handler))
    {
      receive_handler_cls = client->receiver_handler_cls;
      client->receiver_handler = NULL;
      receive_handler (receive_handler_cls, NULL);
    }
    return;
  }
  /* FIXME: optimize for common fast case where buf contains the
   * entire message and we need no copying... */

  /* slow path: append to array */
  if (client->received_size < client->received_pos + available)
    GNUNET_array_grow (client->received_buf, client->received_size,
                       client->received_pos + available);
  memcpy (&client->received_buf[client->received_pos], buf, available);
  client->received_pos += available;
  check_complete (client);
  /* check for timeout */
  remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout);
  if (0 == remaining.rel_value)
  {
    /* signal timeout! */
    if (NULL != client->receiver_handler)
      client->receiver_handler (client->receiver_handler_cls, NULL);
    return;
  }
  /* back to receive -- either for more data or to call callback! */
  GNUNET_CLIENT_receive (client, client->receiver_handler,
                         client->receiver_handler_cls, remaining);
}
示例#14
0
文件: regex_api.c 项目: tg-x/gnunet
/**
 * We got a response or disconnect after asking regex
 * to do the search.  Handle it.
 *
 * @param cls the `struct GNUNET_REGEX_Search` to handle reply for
 * @param msg NULL on disconnect, otherwise presumably a response
 */
static void
handle_search_response (void *cls,
			const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_REGEX_Search *s = cls;
  const struct ResultMessage *result;
  uint16_t size;
  uint16_t gpl;
  uint16_t ppl;

  if (NULL == msg)
  {
    GNUNET_CLIENT_disconnect (s->client);
    s->client = GNUNET_CLIENT_connect ("regex", s->cfg);
    retry_search (s);
    return;
  }
  size = ntohs (msg->size);
  if ( (GNUNET_MESSAGE_TYPE_REGEX_RESULT == ntohs (msg->type)) &&
       (size >= sizeof (struct ResultMessage)) )
  {
    result = (const struct ResultMessage *) msg;
    gpl = ntohs (result->get_path_length);
    ppl = ntohs (result->put_path_length);
    if (size == (sizeof (struct ResultMessage) +
		 (gpl + ppl) * sizeof (struct GNUNET_PeerIdentity)))
    {
      const struct GNUNET_PeerIdentity *pid;

      GNUNET_CLIENT_receive (s->client,
			     &handle_search_response, s,
			     GNUNET_TIME_UNIT_FOREVER_REL);
      pid = &result->id;
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Got regex result %s\n",
           GNUNET_i2s (pid));
      s->callback (s->callback_cls,
		   pid,
		   &pid[1], gpl,
		   &pid[1 + gpl], ppl);
      return;
    }
  }
  GNUNET_break (0);
  GNUNET_CLIENT_disconnect (s->client);
  s->client = GNUNET_CLIENT_connect ("regex", s->cfg);
  retry_search (s);
}
示例#15
0
/**
 * Handler for notification messages received from ARM.
 *
 * @param cls our "struct GNUNET_ARM_MonitorHandle"
 * @param msg the message received from the arm service
 */
static void
monitor_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_ARM_MonitorHandle *h = cls;
  uint16_t msize;
  const struct GNUNET_ARM_StatusMessage *res;
  enum GNUNET_ARM_ServiceStatus status;

  if (NULL == msg)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Monitoring client was disconnected from arm service, trying to reconnect.\n"));
    reconnect_arm_monitor_later (h);
    return;
  }
  msize = ntohs (msg->size);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Processing message of type %u and size %u from arm service\n",
       ntohs (msg->type), msize);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_ARM_STATUS:
    if (msize <= sizeof (struct GNUNET_ARM_StatusMessage))
    {
      GNUNET_break (0);
      reconnect_arm_monitor_later (h);
      return;
    }
    if (NULL != h->init_timeout_task_id)
    {
      GNUNET_SCHEDULER_cancel (h->init_timeout_task_id);
      h->init_timeout_task_id = NULL;
    }
    res = (const struct GNUNET_ARM_StatusMessage *) msg;
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received response from ARM for service `%s': %u\n",
         (const char *) &res[1], ntohs (msg->type));
    status = (enum GNUNET_ARM_ServiceStatus) ntohl (res->status);
    GNUNET_CLIENT_receive (h->monitor, &monitor_notify_handler, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
    if (NULL != h->service_status)
      h->service_status (h->cls, (const char *) &res[1], status);
    break;
  default:
    reconnect_arm_monitor_later (h);
    return;
  }
}
示例#16
0
文件: dns_api.c 项目: tg-x/gnunet
/**
 * This receives packets from the DNS service and calls the application to
 * handle it.
 *
 * @param cls the struct GNUNET_DNS_Handle
 * @param msg message from the service (request)
 */
static void
request_handler (void *cls,
		 const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_DNS_Handle *dh = cls;
  const struct GNUNET_DNS_Request *req;
  struct GNUNET_DNS_RequestHandle *rh;
  size_t payload_length;

  /* the service disconnected, reconnect after short wait */
  if (msg == NULL)
  {
    disconnect (dh);
    dh->reconnect_task =
        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
                                      &reconnect, dh);
    return;
  }
  if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST) ||
       (ntohs (msg->size) < sizeof (struct GNUNET_DNS_Request)) )
  {
    /* the service did something strange, reconnect immediately */
    GNUNET_break (0);
    disconnect (dh);
    dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);
    return;
  }
  req = (const struct GNUNET_DNS_Request *) msg;
  GNUNET_break (ntohl (req->reserved) == 0);
  payload_length = ntohs (req->header.size) - sizeof (struct GNUNET_DNS_Request);
  GNUNET_CLIENT_receive (dh->dns_connection,
			 &request_handler, dh,
                         GNUNET_TIME_UNIT_FOREVER_REL);

  /* finally, pass request to callback for answers */
  rh = GNUNET_new (struct GNUNET_DNS_RequestHandle);
  rh->dh =dh;
  rh->request_id = req->request_id;
  rh->generation = dh->generation;
  dh->pending_requests++;
  dh->rh (dh->rh_cls,
	  rh,
	  payload_length,
	  (const char*) &req[1]);
}
示例#17
0
/**
 * Task executed once we are done transmitting the INIT message.
 * Starts our 'receive' loop.
 *
 * @param cls the 'struct GNUNET_CORE_Handle'
 * @param success were we successful
 */
static void
init_done_task (void *cls, int success)
{
  struct GNUNET_CORE_Handle *h = cls;

  if (GNUNET_SYSERR == success)
    return;                     /* shutdown */
  if (GNUNET_NO == success)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Failed to exchange INIT with core, retrying\n");
    if (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK)
      reconnect_later (h);
    return;
  }
  GNUNET_CLIENT_receive (h->client, &main_notify_handler, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}
示例#18
0
/**
 * Transmit next message to service.
 *
 * @param cls The 'struct GNUNET_PSYCSTORE_Handle'.
 * @param size Number of bytes available in buf.
 * @param buf Where to copy the message.
 * @return Number of bytes copied to buf.
 */
static size_t
send_next_message (void *cls, size_t size, void *buf)
{
  struct GNUNET_PSYCSTORE_Handle *h = cls;
  struct GNUNET_PSYCSTORE_OperationHandle *op = h->transmit_head;
  size_t ret;

  h->th = NULL;
  if (NULL == op)
    return 0;
  ret = ntohs (op->msg->size);
  if (ret > size)
  {
    reschedule_connect (h);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending message of type %d to PSYCstore service. ID: %" PRIu64 "\n",
       ntohs (op->msg->type), op->op_id);
  memcpy (buf, op->msg, ret);

  GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op);

  if (NULL == op->res_cb && NULL == op->data_cb)
  {
    GNUNET_free (op);
  }
  else
  {
    GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  }

  if (NULL != h->transmit_head)
    transmit_next (h);

  if (GNUNET_NO == h->in_receive)
  {
    h->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (h->client, &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
  }
  return ret;
}
示例#19
0
static void
task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct sockaddr_in sa;
  struct sockaddr *sap[2];
  socklen_t slens[2];

  /* test that ill-configured client fails instantly */
  GNUNET_assert (NULL == GNUNET_CLIENT_connect ("invalid-service", cfg));

  /* test IPC between client and server */
  sap[0] = (struct sockaddr *) &sa;
  slens[0] = sizeof (sa);
  sap[1] = NULL;
  slens[1] = 0;
  memset (&sa, 0, sizeof (sa));
#if HAVE_SOCKADDR_IN_SIN_LEN
  sa.sin_len = sizeof (sa);
#endif
  sa.sin_family = AF_INET;
  sa.sin_port = htons (PORT);
  server =
      GNUNET_SERVER_create (NULL, NULL, sap, slens,
                            GNUNET_TIME_relative_multiply
                            (GNUNET_TIME_UNIT_MILLISECONDS, 10000), GNUNET_NO);
  GNUNET_assert (server != NULL);
  handlers[0].callback_cls = cls;
  handlers[1].callback_cls = cls;
  GNUNET_SERVER_add_handlers (server, handlers);
  client = GNUNET_CLIENT_connect (MYNAME, cfg);
  GNUNET_assert (client != NULL);
  GNUNET_assert (NULL !=
                 GNUNET_CLIENT_notify_transmit_ready (client,
                                                      sizeof (struct
                                                              GNUNET_MessageHeader),
                                                      GNUNET_TIME_relative_multiply
                                                      (GNUNET_TIME_UNIT_SECONDS,5),
                                                      GNUNET_NO, &make_msg,
                                                      NULL));
  GNUNET_CLIENT_receive (client, &recv_bounce, cls,
                         GNUNET_TIME_relative_multiply
                         (GNUNET_TIME_UNIT_MILLISECONDS, 10000));
}
示例#20
0
/**
 * Transmit the next pending message, called by notify_transmit_ready
 *
 * @param cls the closure
 * @param size size of pending data
 * @param buf buffer with pending data
 * @return size data transmitted
 */
static size_t
transmit_pending (void *cls, size_t size, void *buf)
{
  struct GNUNET_GNS_Handle *handle = cls;
  char *cbuf = buf;
  struct PendingMessage *p;
  size_t tsize;

  handle->th = NULL;
  if ((0 == size) || (NULL == buf))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		"Transmission to GNS service failed!\n");
    force_reconnect (handle);
    return 0;
  }  
  if (NULL == (p = handle->pending_head))
    return 0;

  tsize = 0;
  while ((NULL != (p = handle->pending_head)) && (p->size <= size))
  {
    memcpy (&cbuf[tsize], &p[1], p->size);
    tsize += p->size;
    size -= p->size;
    p->transmitted = GNUNET_YES;
    GNUNET_CONTAINER_DLL_remove (handle->pending_head,
				 handle->pending_tail,
				 p);
    if (GNUNET_YES != handle->in_receive)
    {
      GNUNET_CLIENT_receive (handle->client, &process_message, handle,
                             GNUNET_TIME_UNIT_FOREVER_REL);
      handle->in_receive = GNUNET_YES;
    }
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending %u bytes\n",
	      (unsigned int) tsize);
  process_pending_messages (handle);
  return tsize;
}
示例#21
0
文件: mq.c 项目: tg-x/gnunet
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls closure
 * @param msg message received, NULL on timeout or fatal error
 */
static void
handle_client_message (void *cls,
                       const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_MQ_Handle *mq = cls;
  struct ClientConnectionState *state;

  state = mq->impl_state;

  if (NULL == msg)
  {
    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_READ);
    return;
  }

  GNUNET_CLIENT_receive (state->connection, handle_client_message, mq,
                         GNUNET_TIME_UNIT_FOREVER_REL);

  GNUNET_MQ_inject_message (mq, msg);
}
示例#22
0
/**
 * Transmit the monitoring initialization message to the arm service.
 *
 * @param cls closure with the 'struct GNUNET_ARM_MonitorHandle'
 * @param size number of bytes available in buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
transmit_monitoring_init_message (void *cls, size_t size, void *buf)
{
  struct GNUNET_ARM_MonitorHandle *h = cls;
  struct GNUNET_MessageHeader *msg;
  uint16_t msize;

  GNUNET_assert (NULL == h->reconnect_task);
  GNUNET_assert (NULL == h->init_timeout_task_id);
  h->cth = NULL;
  if (NULL == buf)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Transmission failed, initiating reconnect\n");
    reconnect_arm_monitor_later (h);
    return 0;
  }
  msize = sizeof (struct GNUNET_MessageHeader);
  if (size < msize)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Request is too big (%u < %u), not sending it\n", size, msize);
    h->cth = GNUNET_CLIENT_notify_transmit_ready (h->monitor, msize,
        GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO,
        transmit_monitoring_init_message, h);
    return 0;
  }

  msg = buf;
  msg->size = htons (msize);
  msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_MONITOR);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmitting ARM monitoring init message with %u bytes to arm.\n",
       (unsigned int) msize);

  h->init_timeout_task_id = GNUNET_SCHEDULER_add_delayed (
      INIT_TIMEOUT, init_timeout_task, h);
  GNUNET_CLIENT_receive (h->monitor, &monitor_notify_handler, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);
  return msize;
}
示例#23
0
/**
 * Transmit request from queue to datastore service.
 *
 * @param cls the 'struct GNUNET_DATASTORE_Handle'
 * @param size number of bytes that can be copied to buf
 * @param buf where to copy the drop message
 * @return number of bytes written to buf
 */
static size_t
transmit_request (void *cls, size_t size, void *buf)
{
  struct GNUNET_DATASTORE_Handle *h = cls;
  struct GNUNET_DATASTORE_QueueEntry *qe;
  size_t msize;

  h->th = NULL;
  if (NULL == (qe = h->queue_head))
    return 0;                   /* no entry in queue */
  if (buf == NULL)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to DATASTORE.\n");
    GNUNET_STATISTICS_update (h->stats,
                              gettext_noop ("# transmission request failures"),
                              1, GNUNET_NO);
    do_disconnect (h);
    return 0;
  }
  if (size < (msize = qe->message_size))
  {
    process_queue (h);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u byte request to DATASTORE\n",
       msize);
  memcpy (buf, &qe[1], msize);
  qe->was_transmitted = GNUNET_YES;
  GNUNET_SCHEDULER_cancel (qe->task);
  qe->task = GNUNET_SCHEDULER_NO_TASK;
  GNUNET_assert (GNUNET_NO == h->in_receive);
  h->in_receive = GNUNET_YES;
  GNUNET_CLIENT_receive (h->client, &receive_cb, h,
                         GNUNET_TIME_absolute_get_remaining (qe->timeout));
#if INSANE_STATISTICS
  GNUNET_STATISTICS_update (h->stats,
                            gettext_noop ("# bytes sent to datastore"), 1,
                            GNUNET_NO);
#endif
  return msize;
}
示例#24
0
static size_t
transmit_initial_message (void *cls, size_t size, void *buf)
{
  struct GNUNET_MessageHeader msg;

  GNUNET_assert (ok == 1);
  ok = 2;
  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
  msg.type = htons (MY_TYPE);
  msg.size = htons (sizeof (struct GNUNET_MessageHeader));
  memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader));
  GNUNET_assert (NULL !=
                 GNUNET_CLIENT_notify_transmit_ready (cc,
                                                      sizeof (struct
                                                              GNUNET_MessageHeader),
                                                      TIMEOUT, GNUNET_YES,
                                                      &transmit_second_message,
                                                      NULL));
  GNUNET_CLIENT_receive (cc, &first_reply_handler, NULL, TIMEOUT);
  return sizeof (struct GNUNET_MessageHeader);
}
示例#25
0
/**
 * Transmit next message to service.
 *
 * @param cls the `struct GNUNET_IDENTITY_Handle`.
 * @param size number of bytes available in @a buf
 * @param buf where to copy the message
 * @return number of bytes copied to buf
 */
static size_t
send_next_message (void *cls,
		   size_t size,
		   void *buf)
{
  struct GNUNET_IDENTITY_Handle *h = cls;
  struct GNUNET_IDENTITY_Operation *op = h->op_head;
  size_t ret;

  h->th = NULL;
  if (NULL == op)
    return 0;
  ret = ntohs (op->msg->size);
  if (ret > size)
  {
    reschedule_connect (h);
    return 0;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending message of type %d to identity service\n",
       ntohs (op->msg->type));
  memcpy (buf, op->msg, ret);
  if ( (NULL == op->cont) &&
       (NULL == op->cb) )
  {
    GNUNET_CONTAINER_DLL_remove (h->op_head,
				 h->op_tail,
				 op);
    GNUNET_free (op);
    transmit_next (h);
  }
  if (GNUNET_NO == h->in_receive)
  {
    h->in_receive = GNUNET_YES;
    GNUNET_CLIENT_receive (h->client,
			   &message_handler, h,
			   GNUNET_TIME_UNIT_FOREVER_REL);
  }
  return ret;
}
/**
 * Handler receiving response to service shutdown requests.
 * First call with NULL: service misbehaving, or something.
 * First call with GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN:
 *   - service will shutdown
 * Second call with NULL:
 *   - service has now really shut down.
 *
 * @param cls closure
 * @param msg NULL, indicating socket closure.
 */
static void
service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct ShutdownContext *shutdown_ctx = cls;

  if (msg == NULL) 
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n");
    if (shutdown_ctx->cont != NULL)
      shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO);
    
    GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task);
    GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
    GNUNET_free (shutdown_ctx);
    return;
  }
  GNUNET_assert (ntohs (msg->size) ==
		 sizeof (struct GNUNET_MessageHeader));
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN:
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		"Received confirmation for service shutdown.\n");
    shutdown_ctx->confirmed = GNUNET_YES;
    GNUNET_CLIENT_receive (shutdown_ctx->sock,
			   &service_shutdown_handler, shutdown_ctx,
			   GNUNET_TIME_UNIT_FOREVER_REL);
    break;
  default:		/* Fall through */
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		"Service shutdown refused!\n");
    if (shutdown_ctx->cont != NULL)
      shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES);
    
    GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task);
    GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
    GNUNET_free (shutdown_ctx);
    break;
  }
}
示例#27
0
/**
 * Send the 'TEST' message to the service.  If successful, prepare to
 * receive the reply.
 *
 * @param cls the 'struct GNUNET_CLIENT_Connection' of the connection to test
 * @param size number of bytes available in buf
 * @param buf where to write the message
 * @return number of bytes written to buf
 */
static size_t
write_test (void *cls, size_t size, void *buf)
{
  struct GNUNET_CLIENT_Connection *client = cls;
  struct GNUNET_MessageHeader *msg;

  if (size < sizeof (struct GNUNET_MessageHeader))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, _("Failure to transmit TEST request.\n"));
    service_test_error (client->test_cb, client->test_cb_cls);
    GNUNET_CLIENT_disconnect (client);
    return 0;                   /* client disconnected */
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "TEST");
  msg = (struct GNUNET_MessageHeader *) buf;
  msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
  GNUNET_CLIENT_receive (client, &confirm_handler, client,
                         GNUNET_TIME_absolute_get_remaining
                         (client->test_deadline));
  return sizeof (struct GNUNET_MessageHeader);
}
示例#28
0
/**
 * Listen for incoming messages on this chat room.  Also, support servers going
 * away/coming back (i.e. rejoin chat room to keep server state up to date).
 *
 * @param cls closure, pointer to the 'struct GNUNET_CHAT_Room'
 * @param msg message received, NULL on timeout or fatal error
 */
static void
receive_results (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_CHAT_Room *chat_room = cls;

#if DEBUG_CHAT
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a message from the service\n");
#endif
  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & GNUNET_SCHEDULER_get_reason ()))
    return;
  if (NULL == msg)
  {
    GNUNET_break (0);
    rejoin_room (chat_room);
    return;
  }
  process_result (chat_room, msg);
  if (NULL == chat_room->client)
    return;                     /* fatal error */
  /* continue receiving */
  GNUNET_CLIENT_receive (chat_room->client, &receive_results, chat_room,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}
示例#29
0
文件: mq.c 项目: tg-x/gnunet
/**
 * Transmit a queued message to the session's client.
 *
 * @param cls consensus session
 * @param size number of bytes available in @a buf
 * @param buf where the callee should write the message
 * @return number of bytes written to buf
 */
static size_t
connection_client_transmit_queued (void *cls,
                                   size_t size,
                                   void *buf)
{
  struct GNUNET_MQ_Handle *mq = cls;
  const struct GNUNET_MessageHeader *msg;
  struct ClientConnectionState *state = mq->impl_state;
  size_t msg_size;

  GNUNET_assert (NULL != mq);
  msg = GNUNET_MQ_impl_current (mq);

  if (NULL == buf)
  {
    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_READ);
    return 0;
  }

  if ( (GNUNET_YES == state->receive_requested) &&
       (GNUNET_NO == state->receive_active) )
  {
    state->receive_active = GNUNET_YES;
    GNUNET_CLIENT_receive (state->connection, handle_client_message, mq,
                           GNUNET_TIME_UNIT_FOREVER_REL);
  }

  msg_size = ntohs (msg->size);
  GNUNET_assert (size >= msg_size);
  memcpy (buf, msg, msg_size);
  state->th = NULL;

  GNUNET_MQ_impl_send_continue (mq);

  return msg_size;
}
示例#30
0
/**
 * Handler for notification messages received from the core.
 *
 * @param cls our `struct GNUNET_CORE_Handle`
 * @param msg the message received from the core service
 */
static void
main_notify_handler (void *cls,
                     const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_CORE_Handle *h = cls;
  const struct InitReplyMessage *m;
  const struct ConnectNotifyMessage *cnm;
  const struct DisconnectNotifyMessage *dnm;
  const struct NotifyTrafficMessage *ntm;
  const struct GNUNET_MessageHeader *em;
  const struct SendMessageReady *smr;
  const struct GNUNET_CORE_MessageHandler *mh;
  GNUNET_CORE_StartupCallback init;
  struct PeerRecord *pr;
  struct GNUNET_CORE_TransmitHandle *th;
  unsigned int hpos;
  int trigger;
  uint16_t msize;
  uint16_t et;
  if (NULL == msg)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Client was disconnected from core service, trying to reconnect.\n"));
    reconnect_later (h);
    return;
  }
  msize = ntohs (msg->size);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Processing message of type %u and size %u from core service\n",
       ntohs (msg->type), msize);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY:
    if (ntohs (msg->size) != sizeof (struct InitReplyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    m = (const struct InitReplyMessage *) msg;
    GNUNET_break (0 == ntohl (m->reserved));
    /* start our message processing loop */
    if (GNUNET_YES == h->currently_down)
    {
      h->currently_down = GNUNET_NO;
      trigger_next_request (h, GNUNET_NO);
    }
    h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
    h->me = m->my_identity;
    if (NULL != (init = h->init))
    {
      /* mark so we don't call init on reconnect */
      h->init = NULL;
      LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to core service of peer `%s'.\n",
           GNUNET_i2s (&h->me));
      init (h->cls, &h->me);
    }
    else
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Successfully reconnected to core service.\n");
    }
    /* fake 'connect to self' */
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &h->me);
    GNUNET_assert (NULL == pr);
    pr = GNUNET_new (struct PeerRecord);
    pr->peer = h->me;
    pr->ch = h;
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multipeermap_put (h->peers,
                                                      &h->me, pr,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
    if (NULL != h->connects)
      h->connects (h->cls, &h->me);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
    if (msize < sizeof (struct ConnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    cnm = (const struct ConnectNotifyMessage *) msg;
    if (msize !=
        sizeof (struct ConnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about connection from `%s'.\n",
         GNUNET_i2s (&cnm->peer));
    if (0 == memcmp (&h->me, &cnm->peer, sizeof (struct GNUNET_PeerIdentity)))
    {
      /* connect to self!? */
      GNUNET_break (0);
      return;
    }
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer);
    if (NULL != pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    pr = GNUNET_new (struct PeerRecord);
    pr->peer = cnm->peer;
    pr->ch = h;
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multipeermap_put (h->peers,
                                                      &cnm->peer, pr,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
    if (NULL != h->connects)
      h->connects (h->cls, &cnm->peer);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
    if (msize != sizeof (struct DisconnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    dnm = (const struct DisconnectNotifyMessage *) msg;
    if (0 == memcmp (&h->me, &dnm->peer, sizeof (struct GNUNET_PeerIdentity)))
    {
      /* connection to self!? */
      GNUNET_break (0);
      return;
    }
    GNUNET_break (0 == ntohl (dnm->reserved));
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about disconnect from `%s'.\n",
         GNUNET_i2s (&dnm->peer));
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer);
    if (NULL == pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    trigger = ((pr->prev != NULL) || (pr->next != NULL) ||
               (h->ready_peer_head == pr));
    disconnect_and_free_peer_entry (h, &dnm->peer, pr);
    if (trigger)
      trigger_next_request (h, GNUNET_NO);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
    if (msize < sizeof (struct NotifyTrafficMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    ntm = (const struct NotifyTrafficMessage *) msg;
    if ((msize <
         sizeof (struct NotifyTrafficMessage) +
         sizeof (struct GNUNET_MessageHeader)) )
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    em = (const struct GNUNET_MessageHeader *) &ntm[1];
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received message of type %u and size %u from peer `%4s'\n",
         ntohs (em->type), ntohs (em->size), GNUNET_i2s (&ntm->peer));
    if ((GNUNET_NO == h->inbound_hdr_only) &&
        (msize !=
         ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    et = ntohs (em->type);
    for (hpos = 0; hpos < h->hcnt; hpos++)
    {
      mh = &h->handlers[hpos];
      if (mh->type != et)
        continue;
      if ((mh->expected_size != ntohs (em->size)) && (mh->expected_size != 0))
      {
        LOG (GNUNET_ERROR_TYPE_ERROR,
	     "Unexpected message size %u for message of type %u from peer `%4s'\n",
	     htons (em->size), mh->type, GNUNET_i2s (&ntm->peer));
        GNUNET_break_op (0);
        continue;
      }
      pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer);
      if (NULL == pr)
      {
	GNUNET_break (0);
	reconnect_later (h);
	return;
      }
      if (GNUNET_OK !=
          h->handlers[hpos].callback (h->cls, &ntm->peer, em))
      {
        /* error in processing, do not process other messages! */
        break;
      }
    }
    if (NULL != h->inbound_notify)
      h->inbound_notify (h->cls, &ntm->peer, em);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
    if (msize < sizeof (struct NotifyTrafficMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    ntm = (const struct NotifyTrafficMessage *) msg;
    if ((msize <
         sizeof (struct NotifyTrafficMessage) +
         sizeof (struct GNUNET_MessageHeader)) )
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    em = (const struct GNUNET_MessageHeader *) &ntm[1];
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about transmission to `%s'.\n",
         GNUNET_i2s (&ntm->peer));
    if ((GNUNET_NO == h->outbound_hdr_only) &&
        (msize !=
         ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    if (NULL == h->outbound_notify)
    {
      GNUNET_break (0);
      break;
    }
    h->outbound_notify (h->cls, &ntm->peer, em);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_SEND_READY:
    if (msize != sizeof (struct SendMessageReady))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    smr = (const struct SendMessageReady *) msg;
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer);
    if (NULL == pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about transmission readiness to `%s'.\n",
         GNUNET_i2s (&smr->peer));
    if (NULL == pr->th.peer)
    {
      /* request must have been cancelled between the original request
       * and the response from core, ignore core's readiness */
      break;
    }

    th = &pr->th;
    if (ntohs (smr->smr_id) != th->smr_id)
    {
      /* READY message is for expired or cancelled message,
       * ignore! (we should have already sent another request) */
      break;
    }
    if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr))
    {
      /* we should not already be on the ready list... */
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    GNUNET_CONTAINER_DLL_insert (h->ready_peer_head, h->ready_peer_tail, pr);
    trigger_next_request (h, GNUNET_NO);
    break;
  default:
    reconnect_later (h);
    return;
  }
  GNUNET_CLIENT_receive (h->client, &main_notify_handler, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}