Exemplo n.º 1
0
/**
 * Close the connection and free associated resources.  There must
 * not be any pending requests for reading or writing to the
 * connection at this time.
 *
 * @param connection connection to destroy
 */
void
GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
{
  struct AddressProbe *pos;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection);
  GNUNET_assert (NULL == connection->nth.notify_ready);
  GNUNET_assert (NULL == connection->receiver);
  if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
  {
    GNUNET_SCHEDULER_cancel (connection->write_task);
    connection->write_task = GNUNET_SCHEDULER_NO_TASK;
    connection->write_buffer_off = 0;
  }
  if (GNUNET_SCHEDULER_NO_TASK != connection->read_task)
  {
    GNUNET_SCHEDULER_cancel (connection->read_task);
    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
  }
  if (GNUNET_SCHEDULER_NO_TASK != connection->nth.timeout_task)
  {
    GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
  }
  connection->nth.notify_ready = NULL;
  if (NULL != connection->dns_active)
  {
    GNUNET_RESOLVER_request_cancel (connection->dns_active);
    connection->dns_active = NULL;
  }
  while (NULL != (pos = connection->ap_head))
  {
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
    GNUNET_SCHEDULER_cancel (pos->task);
    GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos);
    GNUNET_free (pos);
  }
  if ( (NULL != connection->sock) &&
       (GNUNET_YES != connection->persist) )
  {
    if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && 
	(ENOTCONN != errno) && 
	(ECONNRESET != errno) )
      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown");    
  }
  if (NULL != connection->sock)
  {
    if (GNUNET_YES != connection->persist)
      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
    else
      GNUNET_free (connection->sock); /* at least no memory leak (we deliberately
				       * leak the socket in this special case) ... */
  }
  GNUNET_free_non_null (connection->addr);
  GNUNET_free_non_null (connection->hostname);
  GNUNET_free (connection->write_buffer);
  GNUNET_free (connection);
}
Exemplo n.º 2
0
/**
 * A DNS resolution timed out. Notify the application.
 *
 * @param cls the `struct GNUNET_RESOLVER_RequestHandle *`
 * @param tc scheduler context
 */
static void
handle_lookup_timeout (void *cls,
                       const struct GNUNET_SCHEDULER_TaskContext *tc)
{
    struct GNUNET_RESOLVER_RequestHandle *rh = cls;

    rh->task = NULL;
    rh->addr_callback (rh->cls,
                       NULL,
                       0);
    GNUNET_RESOLVER_request_cancel (rh);
}
Exemplo n.º 3
0
/**
 * Process response with a hostname for a DNS lookup.
 *
 * @param cls our `struct GNUNET_RESOLVER_RequestHandle *` context
 * @param msg message with the hostname, NULL on error
 */
static void
handle_response (void *cls,
                 const struct GNUNET_MessageHeader *msg)
{
    struct GNUNET_RESOLVER_RequestHandle *rh = cls;
    uint16_t size;
    char *nret;

    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Receiving response from DNS service\n");
    if (NULL == msg)
    {
        char buf[INET6_ADDRSTRLEN];

        if (NULL != rh->name_callback)
            LOG (GNUNET_ERROR_TYPE_INFO,
                 _("Timeout trying to resolve IP address `%s'.\n"),
                 inet_ntop (rh->af,
                            (const void *) &rh[1],
                            buf,
                            sizeof(buf)));
        else
            LOG (GNUNET_ERROR_TYPE_INFO,
                 _("Timeout trying to resolve hostname `%s'.\n"),
                 (const char *) &rh[1]);
        /* check if request was canceled */
        if (GNUNET_SYSERR != rh->was_transmitted)
        {
            if (NULL != rh->name_callback)
            {
                /* no reverse lookup was successful, return IP as string */
                if (GNUNET_NO == rh->received_response)
                {
                    nret = no_resolve (rh->af,
                                       &rh[1],
                                       rh->data_len);
                    rh->name_callback (rh->cls, nret);
                    GNUNET_free (nret);
                }
                /* finally, make termination call */
                rh->name_callback (rh->cls,
                                   NULL);
            }
            if (NULL != rh->addr_callback)
                rh->addr_callback (rh->cls,
                                   NULL,
                                   0);
        }
        rh->was_transmitted = GNUNET_NO;
        GNUNET_RESOLVER_request_cancel (rh);
        GNUNET_CLIENT_disconnect (client);
        client = NULL;
        reconnect ();
        return;
    }
    if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type))
    {
        GNUNET_break (0);
        GNUNET_CLIENT_disconnect (client);
        client = NULL;
        reconnect ();
        return;
    }
    size = ntohs (msg->size);
    if (size == sizeof (struct GNUNET_MessageHeader))
    {
        LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Received empty response from DNS service\n");
        /* message contains not data, just header; end of replies */
        /* check if request was canceled */
        if (GNUNET_SYSERR != rh->was_transmitted)
        {
            /* no reverse lookup was successful, return IP as string */
            if (NULL != rh->name_callback)
            {
                if (GNUNET_NO == rh->received_response)
                {
                    nret = no_resolve (rh->af,
                                       &rh[1],
                                       rh->data_len);
                    rh->name_callback (rh->cls, nret);
                    GNUNET_free (nret);
                }
                /* finally, make termination call */
                rh->name_callback (rh->cls,
                                   NULL);
            }
            if (NULL != rh->addr_callback)
                rh->addr_callback (rh->cls,
                                   NULL,
                                   0);
        }
        rh->was_transmitted = GNUNET_NO;
        GNUNET_RESOLVER_request_cancel (rh);
        process_requests ();
        return;
    }
    /* return reverse lookup results to caller */
    if (NULL != rh->name_callback)
    {
        const char *hostname;

        hostname = (const char *) &msg[1];
        if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
        {
            GNUNET_break (0);
            if (GNUNET_SYSERR != rh->was_transmitted)
                rh->name_callback (rh->cls,
                                   NULL);
            rh->was_transmitted = GNUNET_NO;
            GNUNET_RESOLVER_request_cancel (rh);
            GNUNET_CLIENT_disconnect (client);
            client = NULL;
            reconnect ();
            return;
        }
        LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Resolver returns `%s' for IP `%s'.\n",
             hostname,
             GNUNET_a2s ((const void *) &rh[1],
                         rh->data_len));
        if (rh->was_transmitted != GNUNET_SYSERR)
            rh->name_callback (rh->cls,
                               hostname);
        rh->received_response = GNUNET_YES;
    }
    /* return lookup results to caller */
    if (NULL != rh->addr_callback)
    {
        struct sockaddr_in v4;
        struct sockaddr_in6 v6;
        const struct sockaddr *sa;
        socklen_t salen;
        const void *ip;
        size_t ip_len;

        ip = &msg[1];
        ip_len = size - sizeof (struct GNUNET_MessageHeader);
        if (ip_len == sizeof (struct in_addr))
        {
            memset (&v4, 0, sizeof (v4));
            v4.sin_family = AF_INET;
            v4.sin_addr = *(struct in_addr*) ip;
#if HAVE_SOCKADDR_IN_SIN_LEN
            v4.sin_len = sizeof (v4);
#endif
            salen = sizeof (v4);
            sa = (const struct sockaddr *) &v4;
        }
        else if (ip_len == sizeof (struct in6_addr))
        {
            memset (&v6, 0, sizeof (v6));
            v6.sin6_family = AF_INET6;
            v6.sin6_addr = *(struct in6_addr*) ip;
#if HAVE_SOCKADDR_IN_SIN_LEN
            v6.sin6_len = sizeof (v6);
#endif
            salen = sizeof (v6);
            sa = (const struct sockaddr *) &v6;
        }
        else
        {
            GNUNET_break (0);
            if (GNUNET_SYSERR != rh->was_transmitted)
                rh->addr_callback (rh->cls,
                                   NULL,
                                   0);
            rh->was_transmitted = GNUNET_NO;
            GNUNET_RESOLVER_request_cancel (rh);
            GNUNET_CLIENT_disconnect (client);
            client = NULL;
            reconnect ();
            return;
        }
        LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Received IP from DNS service\n");
        if (GNUNET_SYSERR != rh->was_transmitted)
            rh->addr_callback (rh->cls,
                               sa,
                               salen);
    }
    GNUNET_CLIENT_receive (client,
                           &handle_response,
                           rh,
                           GNUNET_TIME_absolute_get_remaining (rh->timeout));
}