Example #1
0
static CURL *
createEasy (tr_session * s, struct tr_web * web, struct tr_web_task * task)
{
  bool is_default_value;
  const tr_address * addr;
  CURL * e = task->curl_easy = curl_easy_init ();

  task->timeout_secs = getTimeoutFromURL (task);

  curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L);
  curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity");
  curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L);
  curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L);
  curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L);
  curl_easy_setopt (e, CURLOPT_PRIVATE, task);
#ifdef USE_LIBCURL_SOCKOPT
  curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction);
  curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task);
#endif
  if (web->curl_ssl_verify)
    {
      curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle);
    }
  else
    {
      curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L);
      curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L);
    }
  curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs);
  curl_easy_setopt (e, CURLOPT_URL, task->url);
  curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING);
  curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0));
  curl_easy_setopt (e, CURLOPT_WRITEDATA, task);
  curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc);

  if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value)
    curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
  else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value)
    curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));

  if (task->cookies != NULL)
    curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies);

  if (web->cookie_filename != NULL)
    curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename);

  if (task->range != NULL)
    {
      curl_easy_setopt (e, CURLOPT_RANGE, task->range);
      /* don't bother asking the server to compress webseed fragments */
      curl_easy_setopt (e, CURLOPT_ENCODING, "identity");
    }

  return e;
}
Example #2
0
static CURL *
createEasy( tr_session * s, struct tr_web_task * task )
{
    const tr_address * addr;
    tr_bool is_default_value;
    CURL * e = curl_easy_init( );
    const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL;
    char * cookie_filename = tr_buildPath( s->configDir, "cookies.txt", NULL );

    task->timeout_secs = getTimeoutFromURL( task );

    curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L );
    curl_easy_setopt( e, CURLOPT_COOKIEFILE, cookie_filename );
    curl_easy_setopt( e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity" );
    curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L );
    curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L );
    curl_easy_setopt( e, CURLOPT_NOSIGNAL, 1L );
    curl_easy_setopt( e, CURLOPT_PRIVATE, task );
#ifdef USE_LIBCURL_SOCKOPT
    curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction );
    curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task );
#endif
    curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L );
    curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L );
    curl_easy_setopt( e, CURLOPT_TIMEOUT, task->timeout_secs );
    curl_easy_setopt( e, CURLOPT_URL, task->url );
    curl_easy_setopt( e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING );
    curl_easy_setopt( e, CURLOPT_VERBOSE, verbose );
    curl_easy_setopt( e, CURLOPT_WRITEDATA, task );
    curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc );

    if((( addr = tr_sessionGetPublicAddress( s, TR_AF_INET, &is_default_value ))) && !is_default_value )
        curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) );
    else if ((( addr = tr_sessionGetPublicAddress( s, TR_AF_INET6, &is_default_value ))) && !is_default_value )
        curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) );

    if( task->range )
        curl_easy_setopt( e, CURLOPT_RANGE, task->range );

    if( s->curl_easy_config_func != NULL )
        s->curl_easy_config_func( s, e, task->url );

    tr_free( cookie_filename );
    return e;
}
Example #3
0
static CURL *
createEasy( tr_session * s, struct tr_web_task * task )
{
    const tr_address * addr;
    CURL * e = curl_easy_init( );
    const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL;

    if( !task->range && s->isProxyEnabled ) {
        const long proxyType = getCurlProxyType( s->proxyType );
        curl_easy_setopt( e, CURLOPT_PROXY, s->proxy );
        curl_easy_setopt( e, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
        curl_easy_setopt( e, CURLOPT_PROXYPORT, s->proxyPort );
        curl_easy_setopt( e, CURLOPT_PROXYTYPE, proxyType );
    }

    if( !task->range && s->isProxyAuthEnabled ) {
        char * str = tr_strdup_printf( "%s:%s", s->proxyUsername,
                                                s->proxyPassword );
        curl_easy_setopt( e, CURLOPT_PROXYUSERPWD, str );
        tr_free( str );
    }

    curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L );
    curl_easy_setopt( e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity" );
    curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L );
    curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L );
    curl_easy_setopt( e, CURLOPT_NOSIGNAL, 1L );
    curl_easy_setopt( e, CURLOPT_PRIVATE, task );
#ifdef USE_LIBCURL_SOCKOPT
    curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction );
    curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task );
#endif
    curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L );
    curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L );
    curl_easy_setopt( e, CURLOPT_TIMEOUT, getTimeoutFromURL( task->url ) );
    curl_easy_setopt( e, CURLOPT_URL, task->url );
    curl_easy_setopt( e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING );
    curl_easy_setopt( e, CURLOPT_VERBOSE, verbose );
    curl_easy_setopt( e, CURLOPT_WRITEDATA, task );
    curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc );

    if(( addr = tr_sessionGetPublicAddress( s, TR_AF_INET )))
        curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) );

    if( task->range )
        curl_easy_setopt( e, CURLOPT_RANGE, task->range );

    return e;
}
Example #4
0
struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const* addr, tr_port port, bool clientIsSeed)
{
    TR_ASSERT(tr_address_is_valid(addr));

    struct tr_peer_socket ret = TR_PEER_SOCKET_INIT;

    static int const domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
    tr_socket_t s;
    struct sockaddr_storage sock;
    socklen_t addrlen;
    tr_address const* source_addr;
    socklen_t sourcelen;
    struct sockaddr_storage source_sock;
    char err_buf[512];

    if (!tr_address_is_valid_for_peers(addr, port))
    {
        return ret;
    }

    s = tr_fdSocketCreate(session, domains[addr->type], SOCK_STREAM);

    if (s == TR_BAD_SOCKET)
    {
        return ret;
    }

    /* seeds don't need much of a read buffer... */
    if (clientIsSeed)
    {
        int n = 8192;

        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void const*)&n, sizeof(n)) == -1)
        {
            tr_logAddInfo("Unable to set SO_RCVBUF on socket %" PRIdMAX ": %s", (intmax_t)s,
                tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
        }
    }

    if (evutil_make_socket_nonblocking(s) == -1)
    {
        tr_netClose(session, s);
        return ret;
    }

    addrlen = setup_sockaddr(addr, port, &sock);

    /* set source address */
    source_addr = tr_sessionGetPublicAddress(session, addr->type, NULL);
    TR_ASSERT(source_addr != NULL);
    sourcelen = setup_sockaddr(source_addr, 0, &source_sock);

    if (bind(s, (struct sockaddr*)&source_sock, sourcelen) == -1)
    {
        tr_logAddError(_("Couldn't set source address %s on %" PRIdMAX ": %s"), tr_address_to_string(source_addr), (intmax_t)s,
            tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
        tr_netClose(session, s);
        return ret;
    }

    if (connect(s, (struct sockaddr*)&sock, addrlen) == -1 &&
#ifdef _WIN32
        sockerrno != WSAEWOULDBLOCK &&
#endif
        sockerrno != EINPROGRESS)
    {
        int const tmperrno = sockerrno;

        if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr->type == TR_AF_INET)
        {
            tr_logAddError(_("Couldn't connect socket %" PRIdMAX " to %s, port %d (errno %d - %s)"), (intmax_t)s,
                tr_address_to_string(addr), (int)ntohs(port), tmperrno, tr_net_strerror(err_buf, sizeof(err_buf), tmperrno));
        }

        tr_netClose(session, s);
    }
    else
    {
        ret = tr_peer_socket_tcp_create(s);
    }

    tr_logAddDeep(__FILE__, __LINE__, NULL, "New OUTGOING connection %" PRIdMAX " (%s)", (intmax_t)s,
        tr_peerIoAddrStr(addr, port));

    return ret;
}
Example #5
0
void
tr_udpInit (tr_session *ss)
{
    bool is_default;
    const struct tr_address * public_addr;
    struct sockaddr_in sin;
    int rc;

    assert (ss->udp_socket < 0);
    assert (ss->udp6_socket < 0);

    ss->udp_port = tr_sessionGetPeerPort (ss);
    if (ss->udp_port <= 0)
        return;

    ss->udp_socket = socket (PF_INET, SOCK_DGRAM, 0);
    if (ss->udp_socket < 0) {
        tr_logAddNamedError ("UDP", "Couldn't create IPv4 socket");
        goto ipv6;
    }

    memset (&sin, 0, sizeof (sin));
    sin.sin_family = AF_INET;
    public_addr = tr_sessionGetPublicAddress (ss, TR_AF_INET, &is_default);
    if (public_addr && !is_default)
        memcpy (&sin.sin_addr, &public_addr->addr.addr4, sizeof (struct in_addr));
    sin.sin_port = htons (ss->udp_port);
    rc = bind (ss->udp_socket, (struct sockaddr*)&sin, sizeof (sin));
    if (rc < 0) {
        tr_logAddNamedError ("UDP", "Couldn't bind IPv4 socket");
        close (ss->udp_socket);
        ss->udp_socket = -1;
        goto ipv6;
    }
    ss->udp_event =
        event_new (ss->event_base, ss->udp_socket, EV_READ | EV_PERSIST,
                  event_callback, ss);
    if (ss->udp_event == NULL)
        tr_logAddNamedError ("UDP", "Couldn't allocate IPv4 event");

 ipv6:
    if (tr_globalIPv6 ())
        rebind_ipv6 (ss, true);
    if (ss->udp6_socket >= 0) {
        ss->udp6_event =
            event_new (ss->event_base, ss->udp6_socket, EV_READ | EV_PERSIST,
                      event_callback, ss);
        if (ss->udp6_event == NULL)
            tr_logAddNamedError ("UDP", "Couldn't allocate IPv6 event");
    }

    tr_udpSetSocketBuffers (ss);

    if (ss->isDHTEnabled)
        tr_dhtInit (ss);

    if (ss->udp_event)
        event_add (ss->udp_event, NULL);
    if (ss->udp6_event)
        event_add (ss->udp6_event, NULL);
}
Example #6
0
static void
rebind_ipv6 (tr_session *ss, bool force)
{
    bool is_default;
    const struct tr_address * public_addr;
    struct sockaddr_in6 sin6;
    const unsigned char *ipv6 = tr_globalIPv6 ();
    int s = -1, rc;
    int one = 1;

    /* We currently have no way to enable or disable IPv6 after initialisation.
       No way to fix that without some surgery to the DHT code itself. */
    if (ipv6 == NULL || (!force && ss->udp6_socket < 0)) {
        if (ss->udp6_bound) {
            free (ss->udp6_bound);
            ss->udp6_bound = NULL;
        }
        return;
    }

    if (ss->udp6_bound != NULL && memcmp (ipv6, ss->udp6_bound, 16) == 0)
        return;

    s = socket (PF_INET6, SOCK_DGRAM, 0);
    if (s < 0)
        goto fail;

#ifdef IPV6_V6ONLY
        /* Since we always open an IPv4 socket on the same port, this
           shouldn't matter.  But I'm superstitious. */
        setsockopt (s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof (one));
#endif

    memset (&sin6, 0, sizeof (sin6));
    sin6.sin6_family = AF_INET6;
    if (ipv6)
        memcpy (&sin6.sin6_addr, ipv6, 16);
    sin6.sin6_port = htons (ss->udp_port);
    public_addr = tr_sessionGetPublicAddress (ss, TR_AF_INET6, &is_default);
    if (public_addr && !is_default)
        sin6.sin6_addr = public_addr->addr.addr6;

    rc = bind (s, (struct sockaddr*)&sin6, sizeof (sin6));
    if (rc < 0)
        goto fail;

    if (ss->udp6_socket < 0) {
        ss->udp6_socket = s;
    } else {
        rc = dup2 (s, ss->udp6_socket);
        if (rc < 0)
            goto fail;
        close (s);
    }

    if (ss->udp6_bound == NULL)
        ss->udp6_bound = malloc (16);
    if (ss->udp6_bound)
        memcpy (ss->udp6_bound, ipv6, 16);

    return;

 fail:
    /* Something went wrong.  It's difficult to recover, so let's simply
       set things up so that we try again next time. */
    tr_logAddNamedError ("UDP", "Couldn't rebind IPv6 socket");
    if (s >= 0)
        close (s);
    if (ss->udp6_bound) {
        free (ss->udp6_bound);
        ss->udp6_bound = NULL;
    }
}