コード例 #1
0
ファイル: ats_api_scheduling.c プロジェクト: muggenhor/GNUnet
/**
 * Release the session slot from the session table (ATS service is
 * also done using it).
 *
 * @param sh our handle
 * @param session_id identifies session that is no longer valid
 */
static void
release_session (struct GNUNET_ATS_SchedulingHandle *sh,
                 uint32_t session_id)
{
  struct GNUNET_ATS_AddressRecord *ar;

  if (NOT_FOUND == session_id)
    return;
  if (session_id >= sh->session_array_size)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  /* this slot should have been removed from remove_session before */
  ar = sh->session_array[session_id];
  if (NULL != ar->session)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  GNUNET_HELLO_address_free (ar->address);
  GNUNET_free (ar);
  sh->session_array[session_id] = NULL;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: gns_api.c プロジェクト: GNUnet/gnunet
/**
 * Generic error handler, called with the appropriate error code and
 * the same closure specified at the creation of the message queue.
 * Not every message queue implementation supports an error handler.
 *
 * @param cls closure with the `struct GNUNET_GNS_Handle *`
 * @param error error code
 */
static void
mq_error_handler (void *cls,
                  enum GNUNET_MQ_Error error)
{
    struct GNUNET_GNS_Handle *handle = cls;
    LOG (GNUNET_ERROR_TYPE_WARNING, "Problem with message queue. error: %i\n",
         error);
    force_reconnect (handle);
}
コード例 #4
0
void wait_server_backoff(unsigned int timeout /* seconds */,
		jsonrpc_server_t* server, bool delay)
{
	if(!server) {
		ERR("Trying to close/reconnect a NULL server\n");
		return;
	}

	if(delay == false) {
		if (requests_using_server(server) <= 0) {
			if(server->status == JSONRPC_SERVER_RECONNECTING) {
				bev_connect(server);
			} else if(server->status == JSONRPC_SERVER_CLOSING) {
				close_server(server);
			}
			return;
		}
	}

	const struct timeval tv = {timeout, 0};

	server_backoff_args_t* args = pkg_malloc(sizeof(server_backoff_args_t));
	CHECK_MALLOC_VOID(args);
	memset(args, 0, sizeof(server_backoff_args_t));

	args->ev = evtimer_new(global_ev_base, server_backoff_cb, (void*)args);
	CHECK_MALLOC_GOTO(args->ev, error);

	args->server = server;
	args->timeout = timeout;

	if(evtimer_add(args->ev, &tv)<0) {
		ERR("event_add failed while setting request timer (%s).", strerror(errno));
		goto error;
	}

	return;

error:
	ERR("schedule_server failed.\n");

	if(args) {
		if(args->ev) {
			evtimer_del(args->ev);
		}
		pkg_free(args);
	}

	if (server->status == JSONRPC_SERVER_CLOSING) {
		ERR("Closing server now...\n");
		close_server(server);
	} else if (server->status == JSONRPC_SERVER_RECONNECTING) {
		ERR("Reconnecting server now...\n");
		force_reconnect(server);
	}
}
コード例 #5
0
ファイル: ats_api_scheduling.c プロジェクト: muggenhor/GNUnet
/**
 * We encountered an error handling the MQ to the
 * ATS service.  Reconnect.
 *
 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
 * @param error details about the error
 */
static void
error_handler (void *cls,
               enum GNUNET_MQ_Error error)
{
  struct GNUNET_ATS_SchedulingHandle *sh = cls;

  LOG (GNUNET_ERROR_TYPE_ERROR,
       "ATS connection died (code %d), reconnecting\n",
       (int) error);
  force_reconnect (sh);
}
コード例 #6
0
ファイル: gns_api.c プロジェクト: amatus/gnunet-debian
/**
 * Process a given reply that might match the given
 * request.
 *
 * @param qe a queue entry
 * @param msg the shorten msg received
 */
static void
process_shorten_reply (struct GNUNET_GNS_ShortenRequest *qe,
                       const struct GNUNET_GNS_ClientShortenResultMessage *msg)
{
  struct GNUNET_GNS_Handle *handle = qe->gns_handle;
  struct PendingMessage *p = (struct PendingMessage *)&qe[1];
  const char *short_name;
  size_t mlen;
  
  if (GNUNET_YES != p->transmitted)
  {
    /* service send reply to query we never managed to send!? */
    GNUNET_break (0);
    force_reconnect (handle);
    return;
  }
  mlen = ntohs (msg->header.size);
  if (ntohs (msg->header.size) == sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
  {
    /* service reports resolution failed */
    short_name = NULL;
  }
  else
  {
    short_name = (const char *) &msg[1];
    if ('\0' != short_name[mlen - sizeof (struct GNUNET_GNS_ClientShortenResultMessage) - 1])
    {
      GNUNET_break (0);
      force_reconnect (handle);
      return;
    } 
  }
  GNUNET_CONTAINER_DLL_remove (handle->shorten_head, handle->shorten_tail, qe);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received shortened reply `%s' from GNS service\n",
              short_name);
  qe->shorten_proc (qe->proc_cls, short_name);
  GNUNET_free (qe);
}
コード例 #7
0
ファイル: gns_api.c プロジェクト: amatus/gnunet-debian
/**
 * Process a given reply that might match the given
 * request.
 *
 * @param qe the handle to the request
 * @param msg the message to process
 */
static void
process_get_auth_reply (struct GNUNET_GNS_GetAuthRequest *qe,
                       const struct GNUNET_GNS_ClientGetAuthResultMessage *msg)
{
  struct GNUNET_GNS_Handle *handle = qe->gns_handle;
  struct PendingMessage *p = (struct PendingMessage *)&qe[1];
  const char *auth_name;
  size_t mlen;

  if (GNUNET_YES != p->transmitted)
  {
    /* service send reply to query we never managed to send!? */
    GNUNET_break (0);
    force_reconnect (handle);
    return;
  }
  mlen = ntohs (msg->header.size);
  if (mlen == sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
  {
    auth_name = NULL;
  }
  else
  {
    auth_name = (const char*) &msg[1];
    if ('\0' != auth_name[mlen - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage) - 1])
    {
      GNUNET_break (0);
      force_reconnect (handle);
      return;
    }
  }
  GNUNET_CONTAINER_DLL_remove (handle->get_auth_head, handle->get_auth_tail, qe);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received GET_AUTH reply `%s' from GNS service\n",
              auth_name);
  qe->auth_proc (qe->proc_cls, auth_name);
  GNUNET_free (qe);
}
コード例 #8
0
ファイル: janssonrpc_io.c プロジェクト: AndreiPlesa/kamailio
void bev_read_cb(struct bufferevent* bev, void* arg)
{
	jsonrpc_server_t* server = (jsonrpc_server_t*)arg;
	int retval = 0;
	while (retval == 0) {
		int retval = netstring_read_evbuffer(bev, &server->buffer);

		if (retval == NETSTRING_INCOMPLETE) {
			return;
		} else if (retval < 0) {
			char* msg = "";
			switch(retval) {
			case NETSTRING_ERROR_TOO_LONG:
				msg = "too long";
				break;
			case NETSTRING_ERROR_NO_COLON:
				msg = "no colon after length field";
				break;
			case NETSTRING_ERROR_TOO_SHORT:
				msg = "too short";
				break;
			case NETSTRING_ERROR_NO_COMMA:
				msg = "missing comma";
				break;
			case NETSTRING_ERROR_LEADING_ZERO:
				msg = "length field has a leading zero";
				break;
			case NETSTRING_ERROR_NO_LENGTH:
				msg = "missing length field";
				break;
			case NETSTRING_INCOMPLETE:
				msg = "incomplete";
				break;
			default:
				ERR("bad netstring: unknown error (%d)\n", retval);
				goto reconnect;
			}
			ERR("bad netstring: %s\n", msg);
reconnect:
			force_reconnect(server);
			return;
		}

		handle_netstring(server);
		free_netstring(server->buffer);
		server->buffer = NULL;
	}
}
コード例 #9
0
ファイル: ats_api_scheduling.c プロジェクト: muggenhor/GNUnet
/**
 * Re-establish the connection to the ATS service.
 *
 * @param sh handle to use to re-connect.
 */
static void
reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
{
  static const struct GNUNET_MQ_MessageHandler handlers[] =
    { { &process_ats_session_release_message,
        GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE,
        sizeof (struct GNUNET_ATS_SessionReleaseMessage) },
      { &process_ats_address_suggestion_message,
        GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION,
        sizeof (struct AddressSuggestionMessage) },
      { NULL, 0, 0 } };
  struct GNUNET_MQ_Envelope *ev;
  struct ClientStartMessage *init;
  unsigned int i;
  struct GNUNET_ATS_AddressRecord *ar;

  GNUNET_assert (NULL == sh->client);
  sh->client = GNUNET_CLIENT_connect ("ats",
                                      sh->cfg);
  if (NULL == sh->client)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  sh->mq = GNUNET_MQ_queue_for_connection_client (sh->client,
                                                  handlers,
                                                  &error_handler,
                                                  sh);
  ev = GNUNET_MQ_msg (init,
                      GNUNET_MESSAGE_TYPE_ATS_START);
  init->start_flag = htonl (START_FLAG_SCHEDULING);
  GNUNET_MQ_send (sh->mq, ev);
  if (NULL == sh->mq)
    return;
  for (i=0;i<sh->session_array_size;i++)
  {
    ar = sh->session_array[i];
    if (NULL == ar)
      continue;
    send_add_address_message (sh, ar);
    if (NULL == sh->mq)
      return;
  }
}
コード例 #10
0
ファイル: gns_api.c プロジェクト: amatus/gnunet-debian
/**
 * 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;
}
コード例 #11
0
ファイル: gns_api.c プロジェクト: amatus/gnunet-debian
/**
 * Process a given reply to the lookup request
 *
 * @param qe a queue entry
 * @param msg the lookup message received
 */
static void
process_lookup_reply (struct GNUNET_GNS_LookupRequest *qe,
                      const struct GNUNET_GNS_ClientLookupResultMessage *msg)
{
  struct GNUNET_GNS_Handle *handle = qe->gns_handle;
  struct PendingMessage *p = (struct PendingMessage *) &qe[1];
  uint32_t rd_count = ntohl (msg->rd_count);
  struct GNUNET_NAMESTORE_RecordData rd[rd_count];
  size_t mlen;

  if (GNUNET_YES != p->transmitted)
  {
    /* service send reply to query we never managed to send!? */
    GNUNET_break (0);
    force_reconnect (handle);
    return;
  }
  mlen = ntohs (msg->header.size);
  mlen -= sizeof (struct GNUNET_GNS_ClientLookupResultMessage);
  if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (mlen,
                                                             (const char*) &msg[1],
                                                             rd_count,
                                                             rd))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to serialize lookup reply from GNS service!\n"));
    qe->lookup_proc (qe->proc_cls, 0, NULL);
  }
  else
  { 
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received lookup reply from GNS service (%u records)\n",
                (unsigned int) rd_count);
    qe->lookup_proc (qe->proc_cls, rd_count, rd);
  }
  GNUNET_CONTAINER_DLL_remove (handle->lookup_head, handle->lookup_tail, qe);
  GNUNET_free (qe);
}
コード例 #12
0
/**
 * Type of a function to call when we receive a message
 * from the service.
 *
 * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle'
 * @param msg message received, NULL on timeout or fatal error
 */
static void
process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_NAMESTORE_Handle *h = cls;
  struct GNUNET_NAMESTORE_Header * gm;
  struct GNUNET_NAMESTORE_QueueEntry *qe;
  struct GNUNET_NAMESTORE_ZoneIterator *ze;
  uint16_t size;
  uint16_t type;
  uint32_t r_id = UINT32_MAX;

  if (NULL == msg)
  {
    force_reconnect (h);
    return;
  }

  size = ntohs (msg->size);
  type = ntohs (msg->type);

  if (size < sizeof (struct GNUNET_NAMESTORE_Header))
  {
    GNUNET_break_op (0);
    GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
    return;
  }

  gm = (struct GNUNET_NAMESTORE_Header *) msg;
  r_id = ntohl (gm->r_id);

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, r_id);

  /* Find matching operation */
  if (r_id > h->op_id)
  {
    /* No matching pending operation found */
    GNUNET_break_op (0);
    GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
                           GNUNET_TIME_UNIT_FOREVER_REL);
    return;
  }

  /* Is it a record related operation ? */
  for (qe = h->op_head; qe != NULL; qe = qe->next)
  {
    if (qe->op_id == r_id)
      break;
  }
  if (qe != NULL)
  {
    manage_record_operations (qe, msg, type, size);
  }

  /* Is it a zone iteration operation ? */
  for (ze = h->z_head; ze != NULL; ze = ze->next)
  {
    if (ze->op_id == r_id)
      break;
  }
  if (ze != NULL)
  {
    manage_zone_operations (ze, msg, type, size);
  }

  GNUNET_CLIENT_receive (h->client, &process_namestore_message, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);

  if (GNUNET_YES == h->reconnect)
    force_reconnect (h);

}
コード例 #13
0
ファイル: gns_api.c プロジェクト: amatus/gnunet-debian
/**
 * Handler for messages received from the GNS service
 *
 * @param cls the 'struct GNUNET_GNS_Handle'
 * @param msg the incoming message
 */
static void
process_message (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_GNS_Handle *handle = cls;
  struct GNUNET_GNS_LookupRequest *lr;
  struct GNUNET_GNS_ShortenRequest *sr;
  struct GNUNET_GNS_GetAuthRequest *gar;
  const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg;
  const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg;
  const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg;
  uint32_t r_id;
  
  if (NULL == msg)
  {
    force_reconnect (handle);
    return;
  }
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT:
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Got LOOKUP_RESULT msg\n");
    if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientLookupResultMessage))
    {
      GNUNET_break (0);
      force_reconnect (handle);
      return;
    }
    lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg;
    r_id = ntohl (lookup_msg->id);   
    for (lr = handle->lookup_head; NULL != lr; lr = lr->next)    
      if (lr->r_id == r_id)
      {
	process_lookup_reply(lr, lookup_msg);    
	break;
      }
    break;
  case GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT:  
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Got SHORTEN_RESULT msg\n");
    if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
    {
      GNUNET_break (0);
      force_reconnect (handle);
      return;
    }
    shorten_msg = (const struct GNUNET_GNS_ClientShortenResultMessage *) msg;   
    r_id = ntohl (shorten_msg->id);
    for (sr = handle->shorten_head; NULL != sr; sr = sr->next)    
      if (sr->r_id == r_id)
      {
	process_shorten_reply (sr, shorten_msg);
	break;
      }
    break;
  case GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT:
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Got GET_AUTH_RESULT msg\n");
    if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
    {
      GNUNET_break (0);
      force_reconnect (handle);
      return;
    }
    get_auth_msg = (const struct GNUNET_GNS_ClientGetAuthResultMessage *) msg;
    r_id = ntohl (get_auth_msg->id);
    for (gar = handle->get_auth_head; NULL != gar; gar = gar->next)
      if (gar->r_id == r_id)
      {
	process_get_auth_reply (gar, get_auth_msg);
	break;
      }
    break;
  default:
    GNUNET_break (0);
    force_reconnect (handle);
    return;
  }
  GNUNET_CLIENT_receive (handle->client, &process_message, handle,
			 GNUNET_TIME_UNIT_FOREVER_REL);
}
コード例 #14
0
ファイル: ats_api_scheduling.c プロジェクト: muggenhor/GNUnet
/**
 * Type of a function to call when we receive a address suggestion
 * message from the service.
 *
 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
 * @param msg message received, NULL on timeout or fatal error
 */
static void
process_ats_address_suggestion_message (void *cls,
                                        const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_ATS_SchedulingHandle *sh = cls;
  const struct AddressSuggestionMessage *m;
  struct GNUNET_ATS_AddressRecord *ar;
  uint32_t session_id;

  m = (const struct AddressSuggestionMessage *) msg;
  session_id = ntohl (m->session_id);
  if (0 == session_id)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  ar = find_session (sh,
                     session_id,
                     &m->peer);
  if (NULL == ar)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  if (NULL == sh->suggest_cb)
    return;
  if (GNUNET_YES == ar->in_destroy)
  {
    /* ignore suggestion, as this address is dying, unless BW is 0,
       in that case signal 'disconnect' via BW 0 */
    if ( (0 == ntohl (m->bandwidth_out.value__)) &&
         (0 == ntohl (m->bandwidth_in.value__)) )
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "ATS suggests disconnect from peer `%s' with BW %u/%u\n",
           GNUNET_i2s (&ar->address->peer),
           (unsigned int) ntohl (m->bandwidth_out.value__),
           (unsigned int) ntohl (m->bandwidth_in.value__));
      sh->suggest_cb (sh->suggest_cb_cls,
                      &m->peer,
                      NULL,
                      NULL,
                      m->bandwidth_out,
                      m->bandwidth_in);
    }
    return;
  }
  if ( (NULL == ar->session) &&
       (GNUNET_HELLO_address_check_option (ar->address,
                                           GNUNET_HELLO_ADDRESS_INFO_INBOUND)) )
  {
    GNUNET_break (0);
    return;
  }
  sh->backoff = GNUNET_TIME_UNIT_ZERO;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "ATS suggests address slot %u for peer `%s' using plugin %s\n",
       ar->slot,
       GNUNET_i2s (&ar->address->peer),
       ar->address->transport_name);
  sh->suggest_cb (sh->suggest_cb_cls,
                  &m->peer,
                  ar->address,
                  ar->session,
                  m->bandwidth_out,
                  m->bandwidth_in);
}