Changeset 11632
- Timestamp:
- Jan 6, 2011, 1:00:21 AM (12 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/peer-common.h
r11599 r11632 86 86 struct tr_peer; 87 87 88 typedef void tr_peer_callback( struct tr_peer * peer,89 const tr_peer_event * event,90 void * client_data );88 typedef void tr_peer_callback( struct tr_peer * peer, 89 const tr_peer_event * event, 90 void * client_data ); 91 91 92 92 #ifdef WIN32 -
trunk/libtransmission/peer-mgr.c
r11599 r11632 161 161 tr_atomAddrStr( const struct peer_atom * atom ) 162 162 { 163 return tr_peerIoAddrStr( &atom->addr, atom->port );163 return atom ? tr_peerIoAddrStr( &atom->addr, atom->port ) : "[no atom]"; 164 164 } 165 165 … … 1200 1200 for( it=t->requests, end=it+n; it!=end; ++it ) 1201 1201 { 1202 if( ( it->sentAt <= too_old ) && !tr_peerMsgsIsReadingBlock( it->peer->msgs, it->block ) )1202 if( ( it->sentAt <= too_old ) && it->peer->msgs && !tr_peerMsgsIsReadingBlock( it->peer->msgs, it->block ) ) 1203 1203 cancel[cancelCount++] = *it; 1204 1204 else … … 1408 1408 1409 1409 /* update our atom */ 1410 if( peer && e->wasPieceData )1410 if( peer && peer->atom && e->wasPieceData ) 1411 1411 peer->atom->piece_data_time = now; 1412 1412 … … 1435 1435 pieceListRemoveRequest( t, block ); 1436 1436 1437 if( peer != NULL)1437 if( peer && peer->blocksSentToClient ) 1438 1438 tr_historyAdd( peer->blocksSentToClient, tr_time( ), 1 ); 1439 1439 … … 1483 1483 * to manage the swarms, not the web server and does not fit 1484 1484 * into the jurisdiction of the tracker." */ 1485 if( peer != NULL ) {1485 if( peer->msgs != NULL ) { 1486 1486 const uint32_t n = tr_torPieceCountBytes( tor, p ); 1487 1487 tr_announcerAddBytes( tor, TR_ANN_DOWN, n ); -
trunk/libtransmission/ratecontrol.c
r10998 r11632 74 74 75 75 void 76 tr_rcTransferred( tr_ratecontrol * r, 77 size_t size ) 76 tr_rcTransferred( tr_ratecontrol * r, size_t size ) 78 77 { 79 78 const uint64_t now = tr_time_msec ( ); -
trunk/libtransmission/web.c
r11610 r11632 74 74 long code; 75 75 struct evbuffer * response; 76 struct evbuffer * freebuf; 76 77 char * url; 77 78 char * range; … … 84 85 task_free( struct tr_web_task * task ) 85 86 { 86 evbuffer_free( task->response ); 87 if( task->freebuf ) 88 evbuffer_free( task->freebuf ); 87 89 tr_free( task->range ); 88 90 tr_free( task->url ); … … 215 217 void * done_func_user_data ) 216 218 { 219 tr_webRunWithBuffer( session, url, range, 220 done_func, done_func_user_data, 221 NULL ); 222 } 223 224 void 225 tr_webRunWithBuffer( tr_session * session, 226 const char * url, 227 const char * range, 228 tr_web_done_func done_func, 229 void * done_func_user_data, 230 struct evbuffer * buffer ) 231 { 217 232 struct tr_web * web = session->web; 218 233 … … 226 241 task->done_func = done_func; 227 242 task->done_func_user_data = done_func_user_data; 228 task->response = evbuffer_new( ); 243 task->response = buffer ? buffer : evbuffer_new( ); 244 task->freebuf = buffer ? NULL : task->response; 229 245 230 246 tr_lockLock( web->taskLock ); -
trunk/libtransmission/web.h
r11599 r11632 51 51 const char * tr_webGetResponseStr( long response_code ); 52 52 53 void 54 55 56 57 53 void tr_webRun( tr_session * session, 54 const char * url, 55 const char * range, 56 tr_web_done_func done_func, 57 void * done_func_user_data ); 58 58 59 59 struct evbuffer; 60 61 void tr_webRunWithBuffer( tr_session * session, 62 const char * url, 63 const char * range, 64 tr_web_done_func done_func, 65 void * done_func_user_data, 66 struct evbuffer * buffer ); 60 67 61 68 void tr_http_escape( struct evbuffer *out, const char *str, int len, tr_bool escape_slashes ); -
trunk/libtransmission/webseed.c
r11599 r11632 11 11 */ 12 12 13 #include <string.h> /* strlen */13 #include <string.h> /* strlen() */ 14 14 15 15 #include <event2/buffer.h> 16 #include <event2/event.h> 16 17 17 18 #include "transmission.h" 18 #include "inout.h" 19 #include "cache.h" 20 #include "inout.h" /* tr_ioFindFileLocation() */ 21 #include "list.h" 19 22 #include "ratecontrol.h" 23 #include "peer-mgr.h" 20 24 #include "torrent.h" 21 25 #include "utils.h" … … 23 27 #include "webseed.h" 24 28 29 struct tr_webseed_task 30 { 31 tr_session * session; 32 struct evbuffer * content; 33 struct tr_webseed * webseed; 34 tr_block_index_t block; 35 tr_piece_index_t piece_index; 36 uint32_t piece_offset; 37 uint32_t length; 38 int torrent_id; 39 }; 40 25 41 struct tr_webseed 26 42 { 27 tr_bool busy; 28 tr_bool dead; 29 30 uint8_t hash[SHA_DIGEST_LENGTH]; 31 32 char * url; 33 34 tr_peer_callback * callback; 35 void * callback_data; 36 37 tr_piece_index_t pieceIndex; 38 uint32_t pieceOffset; 39 uint32_t byteCount; 40 41 tr_ratecontrol rateDown; 42 43 tr_session * session; 44 45 struct evbuffer * content; 43 tr_peer parent; 44 tr_ratecontrol download_rate; 45 tr_session * session; 46 tr_peer_callback * callback; 47 void * callback_data; 48 tr_list * tasks; 49 struct event * timer; 50 char * base_url; 51 size_t base_url_len; 52 int torrent_id; 53 tr_bool is_stopping; 46 54 }; 55 56 static void 57 webseed_free( struct tr_webseed * w ) 58 { 59 tr_bitsetDestructor( &w->parent.have ); 60 tr_free( w->parent.client ); 61 62 event_free( w->timer ); 63 tr_rcDestruct( &w->download_rate ); 64 tr_free( w->base_url ); 65 tr_free( w ); 66 } 47 67 48 68 /*** … … 56 76 { 57 77 if( w->callback != NULL ) 58 w->callback( NULL, e, w->callback_data ); 59 } 60 61 static void 62 fireNeedReq( tr_webseed * w ) 63 { 64 #if 0 78 w->callback( &w->parent, e, w->callback_data ); 79 } 80 81 static void 82 fireClientGotBlock( tr_torrent * tor, tr_webseed * w, tr_block_index_t block ) 83 { 65 84 tr_peer_event e = blankEvent; 66 e.eventType = TR_PEER_NEED_REQ; 67 publish( w, &e ); 68 #endif 69 } 70 71 static void 72 fireClientGotBlock( tr_webseed * w, uint32_t pieceIndex, uint32_t offset, uint32_t length ) 73 { 74 tr_peer_event e = blankEvent; 85 e.pieceIndex = tr_torBlockPiece( tor, block ); 86 e.offset = tor->blockSize * block - tor->info.pieceSize * e.pieceIndex; 87 e.length = tr_torBlockCountBytes( tor, block ); 75 88 e.eventType = TR_PEER_CLIENT_GOT_BLOCK; 76 e.pieceIndex = pieceIndex;77 e.offset = offset;78 e.length = length;79 89 publish( w, &e ); 80 90 } … … 94 104 ***/ 95 105 106 static void 107 on_content_changed( struct evbuffer * buf UNUSED, 108 const struct evbuffer_cb_info * info, 109 void * vw ) 110 { 111 tr_webseed * w = vw; 112 113 if( ( info->n_added > 0 ) && !w->is_stopping ) 114 { 115 tr_rcTransferred( &w->download_rate, info->n_added ); 116 fireClientGotData( w, info->n_added ); 117 } 118 } 119 120 static void task_request_next_chunk( struct tr_webseed_task * task ); 121 122 static void 123 on_idle( tr_webseed * w ) 124 { 125 tr_torrent * tor = tr_torrentFindFromId( w->session, w->torrent_id ); 126 127 if( w->is_stopping && !tr_webseedIsActive( w ) ) 128 { 129 webseed_free( w ); 130 } 131 else if( !w->is_stopping && tor && tor->isRunning && !tr_torrentIsSeed( tor ) ) 132 { 133 int i; 134 int got = 0; 135 const int max = tor->blockCountInPiece; 136 const int want = max - tr_list_size( w->tasks ); 137 tr_block_index_t * blocks = NULL; 138 139 if( want > 0 ) 140 { 141 blocks = tr_new( tr_block_index_t, want ); 142 tr_peerMgrGetNextRequests( tor, &w->parent, want, blocks, &got ); 143 } 144 145 for( i=0; i<got; ++i ) 146 { 147 const tr_block_index_t b = blocks[i]; 148 struct tr_webseed_task * task = tr_new( struct tr_webseed_task, 1 ); 149 task->webseed = w; 150 task->session = w->session; 151 task->torrent_id = w->torrent_id; 152 task->block = b; 153 task->piece_index = tr_torBlockPiece( tor, b ); 154 task->piece_offset = ( tor->blockSize * b ) 155 - ( tor->info.pieceSize * task->piece_index ); 156 task->length = tr_torBlockCountBytes( tor, b ); 157 task->content = evbuffer_new( ); 158 evbuffer_add_cb( task->content, on_content_changed, w ); 159 tr_list_append( &w->tasks, task ); 160 task_request_next_chunk( task ); 161 } 162 163 tr_free( blocks ); 164 } 165 } 166 167 168 static void 169 web_response_func( tr_session * session, 170 long response_code, 171 const void * response UNUSED, 172 size_t response_byte_count UNUSED, 173 void * vtask ) 174 { 175 struct tr_webseed_task * t = vtask; 176 tr_torrent * tor = tr_torrentFindFromId( session, t->torrent_id ); 177 const int success = ( response_code == 206 ); 178 179 if( success && tor ) 180 { 181 if( evbuffer_get_length( t->content ) < t->length ) 182 { 183 task_request_next_chunk( t ); 184 } 185 else 186 { 187 tr_webseed * w = t->webseed; 188 189 tr_cacheWriteBlock( session->cache, tor, 190 t->piece_index, t->piece_offset, t->length, 191 evbuffer_pullup( t->content, -1 ) ); 192 fireClientGotBlock( tor, w, t->block ); 193 194 tr_list_remove_data( &w->tasks, t ); 195 evbuffer_free( t->content ); 196 tr_free( t ); 197 198 on_idle( w ); 199 } 200 } 201 } 202 96 203 static char* 97 makeURL( tr_webseed * w, 98 const tr_file * file ) 204 make_url( tr_webseed * w, const tr_file * file ) 99 205 { 100 206 struct evbuffer * out = evbuffer_new( ); 101 const char * url = w->url; 102 const size_t url_len = strlen( url ); 103 104 evbuffer_add( out, url, url_len ); 207 208 evbuffer_add( out, w->base_url, w->base_url_len ); 105 209 106 210 /* if url ends with a '/', add the torrent name */ 107 if( url[url_len - 1] == '/' && file->name )211 if( w->base_url[w->base_url_len - 1] == '/' && file->name ) 108 212 tr_http_escape( out, file->name, strlen(file->name), FALSE ); 109 213 … … 111 215 } 112 216 113 static void requestNextChunk( tr_webseed * w ); 114 115 static void 116 webResponseFunc( tr_session * session, 117 long response_code, 118 const void * response, 119 size_t response_byte_count, 120 void * vw ) 121 { 122 tr_webseed * w = vw; 123 tr_torrent * tor = tr_torrentFindFromHash( session, w->hash ); 124 const int success = ( response_code == 206 ); 125 126 /*fprintf( stderr, "server responded with code %ld and %lu bytes\n", 127 response_code, (unsigned long)response_byte_count );*/ 128 if( !success ) 129 { 130 /* FIXME */ 131 } 132 else if( tor != NULL ) 133 { 134 evbuffer_add( w->content, response, response_byte_count ); 135 if( !w->dead ) 136 { 137 fireClientGotData( w, response_byte_count ); 138 tr_rcTransferred( &w->rateDown, response_byte_count ); 139 } 140 141 if( evbuffer_get_length( w->content ) < w->byteCount ) 142 requestNextChunk( w ); 143 else { 144 tr_ioWrite( tor, w->pieceIndex, w->pieceOffset, w->byteCount, evbuffer_pullup( w->content, -1 ) ); 145 evbuffer_drain( w->content, evbuffer_get_length( w->content ) ); 146 w->busy = 0; 147 if( w->dead ) 148 tr_webseedFree( w ); 149 else { 150 fireClientGotBlock( w, w->pieceIndex, w->pieceOffset, w->byteCount ); 151 fireNeedReq( w ); 152 } 153 } 154 } 155 } 156 157 static void 158 requestNextChunk( tr_webseed * w ) 159 { 160 tr_torrent * tor = tr_torrentFindFromHash( w->session, w->hash ); 161 217 static void 218 task_request_next_chunk( struct tr_webseed_task * t ) 219 { 220 tr_torrent * tor = tr_torrentFindFromId( t->session, t->torrent_id ); 162 221 if( tor != NULL ) 163 222 { 223 char * url; 224 char range[64]; 225 164 226 const tr_info * inf = tr_torrentInfo( tor ); 165 const uint32_t have = evbuffer_get_length( w->content ); 166 const uint32_t left = w->byteCount - have; 167 const uint32_t pieceOffset = w->pieceOffset + have; 168 tr_file_index_t fileIndex; 169 uint64_t fileOffset; 170 uint32_t thisPass; 171 char * url; 172 char * range; 173 174 tr_ioFindFileLocation( tor, w->pieceIndex, pieceOffset, 175 &fileIndex, &fileOffset ); 176 thisPass = MIN( left, inf->files[fileIndex].length - fileOffset ); 177 178 url = makeURL( w, &inf->files[fileIndex] ); 179 /*fprintf( stderr, "url is [%s]\n", url );*/ 180 range = tr_strdup_printf( "%"PRIu64"-%"PRIu64, fileOffset, fileOffset + thisPass - 1 ); 181 /*fprintf( stderr, "range is [%s] ... we want %lu total, we have %lu, so %lu are left, and we're asking for %lu this time\n", range, (unsigned long)w->byteCount, (unsigned long)have, (unsigned long)left, (unsigned long)thisPass );*/ 182 tr_webRun( w->session, url, range, webResponseFunc, w ); 183 tr_free( range ); 227 const uint32_t remain = t->length - evbuffer_get_length( t->content ); 228 229 const uint64_t total_offset = inf->pieceSize * t->piece_index 230 + t->piece_offset 231 + evbuffer_get_length( t->content ); 232 const tr_piece_index_t step_piece = total_offset / inf->pieceSize; 233 const uint32_t step_piece_offset = total_offset - ( inf->pieceSize * step_piece ); 234 235 tr_file_index_t file_index; 236 uint64_t file_offset; 237 const tr_file * file; 238 uint32_t this_pass; 239 240 tr_ioFindFileLocation( tor, step_piece, step_piece_offset, 241 &file_index, &file_offset ); 242 file = &inf->files[file_index]; 243 this_pass = MIN( remain, file->length - file_offset ); 244 245 url = make_url( t->webseed, file ); 246 tr_snprintf( range, sizeof range, "%"PRIu64"-%"PRIu64, 247 file_offset, file_offset + this_pass - 1 ); 248 tr_webRunWithBuffer( t->session, url, range, 249 web_response_func, t, t->content ); 184 250 tr_free( url ); 185 251 } 186 252 } 187 253 188 tr_addreq_t 189 tr_webseedAddRequest( tr_webseed * w, 190 uint32_t pieceIndex, 191 uint32_t pieceOffset, 192 uint32_t byteCount ) 193 { 194 int ret; 195 196 if( w->busy || w->dead ) 197 { 198 ret = TR_ADDREQ_FULL; 199 } 200 else 201 { 202 w->busy = 1; 203 w->pieceIndex = pieceIndex; 204 w->pieceOffset = pieceOffset; 205 w->byteCount = byteCount; 206 evbuffer_drain( w->content, evbuffer_get_length( w->content ) ); 207 requestNextChunk( w ); 208 ret = TR_ADDREQ_OK; 209 } 210 211 return ret; 212 } 213 214 int 254 tr_bool 215 255 tr_webseedIsActive( const tr_webseed * w ) 216 256 { 217 return w-> busy != 0;218 } 219 220 int 257 return w->tasks != NULL; 258 } 259 260 tr_bool 221 261 tr_webseedGetSpeed_Bps( const tr_webseed * w, uint64_t now, int * setme_Bps ) 222 262 { 223 const int isActive = tr_webseedIsActive( w );224 *setme_Bps = is Active ? tr_rcRate_Bps( &w->rateDown, now ) : 0;225 return is Active;263 const tr_bool is_active = tr_webseedIsActive( w ); 264 *setme_Bps = is_active ? tr_rcRate_Bps( &w->download_rate, now ) : 0; 265 return is_active; 226 266 } 227 267 … … 230 270 ***/ 231 271 272 static void 273 webseed_timer_func( evutil_socket_t foo UNUSED, short bar UNUSED, void * vw ) 274 { 275 tr_webseed * w = vw; 276 on_idle( w ); 277 tr_timerAddMsec( w->timer, 1000 ); 278 } 279 232 280 tr_webseed* 233 tr_webseedNew( struct tr_torrent * tor rent,281 tr_webseedNew( struct tr_torrent * tor, 234 282 const char * url, 235 283 tr_peer_callback * callback, … … 237 285 { 238 286 tr_webseed * w = tr_new0( tr_webseed, 1 ); 239 240 memcpy( w->hash, torrent->info.hash, SHA_DIGEST_LENGTH ); 241 w->session = torrent->session; 242 w->content = evbuffer_new( ); 243 w->url = tr_strdup( url ); 287 tr_peer * peer = &w->parent; 288 289 peer->peerIsChoked = TRUE; 290 peer->peerIsInterested = FALSE; 291 peer->clientIsChoked = FALSE; 292 peer->clientIsChoked = FALSE; 293 peer->clientIsInterested = !tr_torrentIsSeed( tor ); 294 tr_bitsetConstructor( &peer->have, tor->info.pieceCount ); 295 tr_bitsetSetHaveAll( &peer->have ); 296 peer->progress = 1.0; 297 peer->client = tr_strdup( "webseed" ); 298 299 w->torrent_id = tr_torrentId( tor ); 300 w->session = tor->session; 301 302 w->base_url_len = strlen( url ); 303 w->base_url = tr_strndup( url, w->base_url_len ); 244 304 w->callback = callback; 245 305 w->callback_data = callback_data; 246 tr_rcConstruct( &w->rateDown ); 306 tr_rcConstruct( &w->download_rate ); 307 w->timer = evtimer_new( w->session->event_base, webseed_timer_func, w ); 308 tr_timerAddMsec( w->timer, 1000 ); 247 309 return w; 248 310 } … … 253 315 if( w ) 254 316 { 255 if( w->busy ) 256 { 257 w->dead = 1; 258 } 317 if( tr_webseedIsActive( w ) ) 318 w->is_stopping = TRUE; 259 319 else 260 { 261 evbuffer_free( w->content ); 262 tr_rcDestruct( &w->rateDown ); 263 tr_free( w->url ); 264 tr_free( w ); 265 } 266 } 267 } 320 webseed_free( w ); 321 } 322 } -
trunk/libtransmission/webseed.h
r11599 r11632 29 29 void tr_webseedFree( tr_webseed * ); 30 30 31 tr_addreq_t tr_webseedAddRequest( tr_webseed * w,32 uint32_t index,33 uint32_t offset,34 uint32_t length );35 36 31 /** @return true if a request is being processed, or false if idle */ 37 inttr_webseedGetSpeed_Bps( const tr_webseed * w,32 tr_bool tr_webseedGetSpeed_Bps( const tr_webseed * w, 38 33 uint64_t now, 39 34 int * setme_Bps ); 40 35 41 36 /** @return true if a request is being processed, or false if idle */ 42 inttr_webseedIsActive( const tr_webseed * w );37 tr_bool tr_webseedIsActive( const tr_webseed * w ); 43 38 44 39
Note: See TracChangeset
for help on using the changeset viewer.