void tr_magnetCreateMetainfo (const tr_magnet_info * info, tr_variant * top) { int i; tr_variant * d; tr_variantInitDict (top, 4); /* announce list */ if (info->trackerCount == 1) { tr_variantDictAddStr (top, TR_KEY_announce, info->trackers[0]); } else { tr_variant * trackers = tr_variantDictAddList (top, TR_KEY_announce_list, info->trackerCount); for (i=0; i<info->trackerCount; ++i) tr_variantListAddStr (tr_variantListAddList (trackers, 1), info->trackers[i]); } /* webseeds */ if (info->webseedCount > 0) { tr_variant * urls = tr_variantDictAddList (top, TR_KEY_url_list, info->webseedCount); for (i=0; i<info->webseedCount; ++i) tr_variantListAddStr (urls, info->webseeds[i]); } /* nonstandard keys */ d = tr_variantDictAddDict (top, TR_KEY_magnet_info, 2); tr_variantDictAddRaw (d, TR_KEY_info_hash, info->hash, 20); if (info->displayName != NULL) tr_variantDictAddStr (d, TR_KEY_display_name, info->displayName); }
static void saveIdleLimits (tr_variant * dict, tr_torrent * tor) { tr_variant * d = tr_variantDictAddDict (dict, TR_KEY_idle_limit, 2); tr_variantDictAddInt (d, TR_KEY_idle_limit, tr_torrentGetIdleLimit (tor)); tr_variantDictAddInt (d, TR_KEY_idle_mode, tr_torrentGetIdleMode (tor)); }
static void saveRatioLimits (tr_variant * dict, tr_torrent * tor) { tr_variant * d = tr_variantDictAddDict (dict, TR_KEY_ratio_limit, 2); tr_variantDictAddReal (d, TR_KEY_ratio_limit, tr_torrentGetRatioLimit (tor)); tr_variantDictAddInt (d, TR_KEY_ratio_mode, tr_torrentGetRatioMode (tor)); }
static void handle_upload (struct evhttp_request * req, struct tr_rpc_server * server) { if (req->type != EVHTTP_REQ_POST) { send_simple_response (req, 405, NULL); } else { int i; int n; bool hasSessionId = false; tr_ptrArray parts = TR_PTR_ARRAY_INIT; const char * query = strchr (req->uri, '?'); const bool paused = query && strstr (query + 1, "paused=true"); extract_parts_from_multipart (req->input_headers, req->input_buffer, &parts); n = tr_ptrArraySize (&parts); /* first look for the session id */ for (i=0; i<n; ++i) { struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); if (tr_memmem (p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen (TR_RPC_SESSION_ID_HEADER))) break; } if (i<n) { const struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); const char * ours = get_current_session_id (server); const size_t ourlen = strlen (ours); hasSessionId = ourlen <= p->body_len && memcmp (p->body, ours, ourlen) == 0; } if (!hasSessionId) { int code = 409; const char * codetext = tr_webGetResponseStr (code); struct evbuffer * body = evbuffer_new (); evbuffer_add_printf (body, "%s", "{ \"success\": false, \"msg\": \"Bad Session-Id\" }");; evhttp_send_reply (req, code, codetext, body); evbuffer_free (body); } else for (i=0; i<n; ++i) { struct tr_mimepart * p = tr_ptrArrayNth (&parts, i); size_t body_len = p->body_len; tr_variant top, *args; tr_variant test; bool have_source = false; char * body = p->body; if (body_len >= 2 && memcmp (&body[body_len - 2], "\r\n", 2) == 0) body_len -= 2; tr_variantInitDict (&top, 2); tr_variantDictAddStr (&top, TR_KEY_method, "torrent-add"); args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2); tr_variantDictAddBool (args, TR_KEY_paused, paused); if (tr_urlIsValid (body, body_len)) { tr_variantDictAddRaw (args, TR_KEY_filename, body, body_len); have_source = true; } else if (!tr_variantFromBenc (&test, body, body_len)) { char * b64 = tr_base64_encode (body, body_len, NULL); tr_variantDictAddStr (args, TR_KEY_metainfo, b64); tr_free (b64); have_source = true; } if (have_source) tr_rpc_request_exec_json (server->session, &top, NULL, NULL); tr_variantFree (&top); } tr_ptrArrayDestruct (&parts, (PtrArrayForeachFunc)tr_mimepart_free); /* send "success" response */ { int code = HTTP_OK; const char * codetext = tr_webGetResponseStr (code); struct evbuffer * body = evbuffer_new (); evbuffer_add_printf (body, "%s", "{ \"success\": true, \"msg\": \"Torrent Added\" }");; evhttp_send_reply (req, code, codetext, body); evbuffer_free (body); } } }
static void saveProgress(tr_variant* dict, tr_torrent* tor) { tr_variant* l; tr_variant* prog; tr_info const* inf = tr_torrentInfo(tor); time_t const now = tr_time(); prog = tr_variantDictAddDict(dict, TR_KEY_progress, 3); /* add the file/piece check timestamps... */ l = tr_variantDictAddList(prog, TR_KEY_time_checked, inf->fileCount); for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi) { time_t oldest_nonzero = now; time_t newest = 0; bool has_zero = false; time_t const mtime = tr_torrentGetFileMTime(tor, fi); tr_file const* f = &inf->files[fi]; /* get the oldest and newest nonzero timestamps for pieces in this file */ for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i) { tr_piece const* const p = &inf->pieces[i]; if (p->timeChecked == 0) { has_zero = true; } else if (oldest_nonzero > p->timeChecked) { oldest_nonzero = p->timeChecked; } if (newest < p->timeChecked) { newest = p->timeChecked; } } /* If some of a file's pieces have been checked more recently than the file's mtime, and some less recently, then that file will have a list containing timestamps for each piece. However, the most common use case is that the file doesn't change after it's downloaded. To reduce overhead in the .resume file, only a single timestamp is saved for the file if *all* or *none* of the pieces were tested more recently than the file's mtime. */ if (!has_zero && mtime <= oldest_nonzero) /* all checked */ { tr_variantListAddInt(l, oldest_nonzero); } else if (newest < mtime) /* none checked */ { tr_variantListAddInt(l, newest); } else /* some are checked, some aren't... so list piece by piece */ { int const offset = oldest_nonzero - 1; tr_variant* ll = tr_variantListAddList(l, 2 + f->lastPiece - f->firstPiece); tr_variantListAddInt(ll, offset); for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i) { tr_piece const* const p = &inf->pieces[i]; tr_variantListAddInt(ll, p->timeChecked != 0 ? p->timeChecked - offset : 0); } } } /* add the progress */ if (tor->completeness == TR_SEED) { tr_variantDictAddStr(prog, TR_KEY_have, "all"); } /* add the blocks bitfield */ bitfieldToBenc(&tor->completion.blockBitfield, tr_variantDictAdd(prog, TR_KEY_blocks)); }
static void saveSpeedLimits(tr_variant* dict, tr_torrent* tor) { saveSingleSpeedLimit(tr_variantDictAddDict(dict, TR_KEY_speed_limit_down, 0), tor, TR_DOWN); saveSingleSpeedLimit(tr_variantDictAddDict(dict, TR_KEY_speed_limit_up, 0), tor, TR_UP); }