Ejemplo n.º 1
0
static int
test_env (void)
{
  const char * test_key = "TR_TEST_ENV";
  int x;
  char * s;

  unsetenv (test_key);

  check (!tr_env_key_exists (test_key));
  x = tr_env_get_int (test_key, 123);
  check_int_eq (123, x);
  s = tr_env_get_string (test_key, NULL);
  check (s == NULL);
  s = tr_env_get_string (test_key, "a");
  check_streq ("a", s);
  tr_free (s);

  setenv (test_key, "", 1);

  check (tr_env_key_exists (test_key));
  x = tr_env_get_int (test_key, 456);
  check_int_eq (456, x);
  s = tr_env_get_string (test_key, NULL);
  check_streq ("", s);
  tr_free (s);
  s = tr_env_get_string (test_key, "b");
  check_streq ("", s);
  tr_free (s);

  setenv (test_key, "135", 1);

  check (tr_env_key_exists (test_key));
  x = tr_env_get_int (test_key, 789);
  check_int_eq (135, x);
  s = tr_env_get_string (test_key, NULL);
  check_streq ("135", s);
  tr_free (s);
  s = tr_env_get_string (test_key, "c");
  check_streq ("135", s);
  tr_free (s);

  return 0;
}
Ejemplo n.º 2
0
static CURL* tr_curl_easy_init(struct evbuffer* writebuf)
{
    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_USERAGENT, MY_NAME "/" LONG_VERSION_STRING);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, writebuf);
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, tr_env_key_exists("TR_CURL_VERBOSE"));
    curl_easy_setopt(curl, CURLOPT_ENCODING, "");
    return curl;
}
Ejemplo n.º 3
0
static void
on_scrape_done (tr_session   * session,
                bool           did_connect,
                bool           did_timeout,
                long           response_code,
                const void   * msg,
                size_t         msglen,
                void         * vdata)
{
    tr_scrape_response * response;
    struct scrape_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg (data->log_name, "Got scrape response for \"%s\"", response->url);

    if (response_code != HTTP_OK)
    {
        const char * fmt = _("Tracker gave HTTP response code %1$ld (%2$s)");
        const char * response_str = tr_webGetResponseStr (response_code);
        response->errmsg = tr_strdup_printf (fmt, response_code, response_str);
    }
    else
    {
        tr_variant top;
        int64_t intVal;
        tr_variant * files;
        tr_variant * flags;
        size_t len;
        const char * str;
        const bool variant_loaded = !tr_variantFromBenc (&top, msg, msglen);

        if (tr_env_key_exists ("TR_CURL_VERBOSE"))
        {
            if (!variant_loaded)
                fprintf (stderr, "%s", "Scrape response was not in benc format\n");
            else {
                size_t i, len;
                char * str = tr_variantToStr (&top, TR_VARIANT_FMT_JSON, &len);
                fprintf (stderr, "%s", "Scrape response:\n< ");
                for (i=0; i<len; ++i)
                    fputc (str[i], stderr);
                fputc ('\n', stderr);
                tr_free (str);
            }
        }

        if (variant_loaded)
        {
            if (tr_variantDictFindStr (&top, TR_KEY_failure_reason, &str, &len))
                response->errmsg = tr_strndup (str, len);

            if (tr_variantDictFindDict (&top, TR_KEY_flags, &flags))
                if (tr_variantDictFindInt (flags, TR_KEY_min_request_interval, &intVal))
                    response->min_request_interval = intVal;

            if (tr_variantDictFindDict (&top, TR_KEY_files, &files))
            {
                int i = 0;

                for (;;)
                {
                    int j;
                    tr_quark key;
                    tr_variant * val;

                    /* get the next "file" */
                    if (!tr_variantDictChild (files, i++, &key, &val))
                        break;

                    /* populate the corresponding row in our response array */
                    for (j=0; j<response->row_count; ++j)
                    {
                        struct tr_scrape_response_row * row = &response->rows[j];
                        if (memcmp (tr_quark_get_string (key, NULL), row->info_hash, SHA_DIGEST_LENGTH) == 0)
                        {
                            if (tr_variantDictFindInt (val, TR_KEY_complete, &intVal))
                                row->seeders = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_incomplete, &intVal))
                                row->leechers = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_downloaded, &intVal))
                                row->downloads = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_downloaders, &intVal))
                                row->downloaders = intVal;
                            break;
                        }
                    }
                }
            }

            tr_variantFree (&top);
        }
    }

    tr_runInEventThread (session, on_scrape_done_eventthread, data);
}
Ejemplo n.º 4
0
static void
on_announce_done (tr_session   * session,
                  bool           did_connect,
                  bool           did_timeout,
                  long           response_code,
                  const void   * msg,
                  size_t         msglen,
                  void         * vdata)
{
    tr_announce_response * response;
    struct announce_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg (data->log_name, "Got announce response");

    if (response_code != HTTP_OK)
    {
        const char * fmt = _("Tracker gave HTTP response code %1$ld (%2$s)");
        const char * response_str = tr_webGetResponseStr (response_code);
        response->errmsg = tr_strdup_printf (fmt, response_code, response_str);
    }
    else
    {
        tr_variant benc;
        const bool variant_loaded = !tr_variantFromBenc (&benc, msg, msglen);

        if (tr_env_key_exists ("TR_CURL_VERBOSE"))
        {
            if (!variant_loaded)
                fprintf (stderr, "%s", "Announce response was not in benc format\n");
            else {
                size_t i, len;
                char * str = tr_variantToStr (&benc, TR_VARIANT_FMT_JSON, &len);
                fprintf (stderr, "%s", "Announce response:\n< ");
                for (i=0; i<len; ++i)
                    fputc (str[i], stderr);
                fputc ('\n', stderr);
                tr_free (str);
            }
        }

        if (variant_loaded && tr_variantIsDict (&benc))
        {
            int64_t i;
            size_t len;
            tr_variant * tmp;
            const char * str;
            const uint8_t * raw;

            if (tr_variantDictFindStr (&benc, TR_KEY_failure_reason, &str, &len))
                response->errmsg = tr_strndup (str, len);

            if (tr_variantDictFindStr (&benc, TR_KEY_warning_message, &str, &len))
                response->warning = tr_strndup (str, len);

            if (tr_variantDictFindInt (&benc, TR_KEY_interval, &i))
                response->interval = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_min_interval, &i))
                response->min_interval = i;

            if (tr_variantDictFindStr (&benc, TR_KEY_tracker_id, &str, &len))
                response->tracker_id_str = tr_strndup (str, len);

            if (tr_variantDictFindInt (&benc, TR_KEY_complete, &i))
                response->seeders = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_incomplete, &i))
                response->leechers = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_downloaded, &i))
                response->downloads = i;

            if (tr_variantDictFindRaw (&benc, TR_KEY_peers6, &raw, &len)) {
                dbgmsg (data->log_name, "got a peers6 length of %zu", len);
                response->pex6 = tr_peerMgrCompact6ToPex (raw, len,
                                              NULL, 0, &response->pex6_count);
            }

            if (tr_variantDictFindRaw (&benc, TR_KEY_peers, &raw, &len)) {
                dbgmsg (data->log_name, "got a compact peers length of %zu", len);
                response->pex = tr_peerMgrCompactToPex (raw, len,
                                               NULL, 0, &response->pex_count);
            } else if (tr_variantDictFindList (&benc, TR_KEY_peers, &tmp)) {
                response->pex = listToPex (tmp, &response->pex_count);
                dbgmsg (data->log_name, "got a peers list with %zu entries",
                        response->pex_count);
            }
        }

        if (variant_loaded)
            tr_variantFree (&benc);
    }

    tr_runInEventThread (session, on_announce_done_eventthread, data);
}
Ejemplo n.º 5
0
int
tr_dhtInit (tr_session *ss)
{
    tr_variant benc;
    int rc;
    bool have_id = false;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if (session) /* already initialized */
        return -1;

    tr_logAddNamedDbg ("DHT", "Initializing DHT");

    if (tr_env_key_exists ("TR_DHT_VERBOSE"))
        dht_debug = stderr;

    dat_file = tr_buildPath (ss->configDir, "dht.dat", NULL);
    rc = tr_variantFromFile (&benc, TR_VARIANT_FMT_BENC, dat_file, NULL) ? 0 : -1;
    tr_free (dat_file);
    if (rc == 0) {
        have_id = tr_variantDictFindRaw (&benc, TR_KEY_id, &raw, &len);
        if (have_id && len==20)
            memcpy (myid, raw, len);
        if (ss->udp_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes, &raw, &len) && ! (len%6)) {
                nodes = tr_memdup (raw, len);
        }
        if (ss->udp6_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes6, &raw, &len6) && ! (len6%18)) {
            nodes6 = tr_memdup (raw, len6);
        }
        tr_variantFree (&benc);
    }

    if (nodes == NULL)
        len = 0;
    if (nodes6 == NULL)
        len6 = 0;

    if (have_id)
        tr_logAddNamedInfo ("DHT", "Reusing old id");
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_logAddNamedInfo ("DHT", "Generating new id");
        tr_rand_buffer (myid, 20);
    }

    rc = dht_init (ss->udp_socket, ss->udp6_socket, myid, NULL);
    if (rc < 0)
        goto fail;

    session = ss;

    cl = tr_new (struct bootstrap_closure, 1);
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew (dht_bootstrap, cl);

    dht_timer = evtimer_new (session->event_base, timer_callback, session);
    tr_timerAdd (dht_timer, 0, tr_rand_int_weak (1000000));

    tr_logAddNamedDbg ("DHT", "DHT initialized");

    return 1;

 fail:
    tr_logAddNamedDbg ("DHT", "DHT initialization failed (errno = %d)", errno);
    session = NULL;
    return -1;
}