void tr_rcReset( tr_ratecontrol_t * r ) { tr_lockLock( &r->lock ); r->transferStart = 0; r->transferStop = 0; tr_lockUnlock( &r->lock ); }
void tr_fdFileClose( const char * filename ) { int i; tr_lockLock( gFd->lock ); for( i = 0; i < TR_MAX_OPEN_FILES; ++i ) { struct tr_openfile * o = &gFd->open[i]; if( !fileIsOpen( o ) || strcmp( filename, o->filename ) ) continue; dbgmsg( "tr_fdFileClose closing '%s'", filename ); if( !o->isCheckedOut ) { dbgmsg( "not checked out, so closing it now... '%s'", filename ); TrCloseFile( i ); } else { dbgmsg( "flagging file '%s', slot #%d to be closed when checked in", gFd->open[i].filename, i ); o->closeWhenDone = 1; } } tr_lockUnlock( gFd->lock ); }
void tr_runInEventThread( struct tr_handle * handle, void func( void* ), void * user_data ) { assert( handle ); assert( handle->events ); if( tr_amInThread( handle->events->thread ) ) { (func)( user_data ); } else { const char ch = 'r'; int fd = handle->events->fds[1]; tr_lock * lock = handle->events->lock; struct tr_run_data data; tr_lockLock( lock ); pipewrite( fd, &ch, 1 ); data.func = func; data.user_data = user_data; pipewrite( fd, &data, sizeof( data ) ); tr_lockUnlock( lock ); } }
int tr_rcCanGlobalTransfer( tr_handle_t * h, int isUpload ) { tr_torrent_t * tor; tr_ratecontrol_t * r; float rate = 0; int limit = isUpload ? h->uploadLimit : h->downloadLimit; if( limit <= 0 ) { return limit < 0; } tr_sharedLock( h->shared ); for( tor = h->torrentList; tor; tor = tor->next ) { if( isUpload ? tor->customUploadLimit : tor->customDownloadLimit ) { continue; } r = isUpload ? tor->upload : tor->download; tr_lockLock( &r->lock ); rate += rateForInterval( r, SHORT_INTERVAL ); tr_lockUnlock( &r->lock ); if( rate >= (float)limit ) { tr_sharedUnlock( h->shared ); return 0; } } tr_sharedUnlock( h->shared ); return 1; }
struct tr_web_task * tr_webRunWithBuffer( tr_session * session, const char * url, const char * range, const char * cookies, tr_web_done_func done_func, void * done_func_user_data, struct evbuffer * buffer ) { struct tr_web * web = session->web; if( web != NULL ) { struct tr_web_task * task = tr_new0( struct tr_web_task, 1 ); task->session = session; task->url = tr_strdup( url ); task->range = tr_strdup( range ); task->cookies = tr_strdup( cookies); task->done_func = done_func; task->done_func_user_data = done_func_user_data; task->response = buffer ? buffer : evbuffer_new( ); task->freebuf = buffer ? NULL : task->response; tr_lockLock( web->taskLock ); task->next = web->tasks; web->tasks = task; tr_lockUnlock( web->taskLock ); return task; } return NULL; }
void tr_runInEventThread( tr_session * session, void func( void* ), void * user_data ) { assert( tr_isSession( session ) ); assert( session->events != NULL ); if( tr_amInThread( session->events->thread ) ) { (func)( user_data ); } else { const char ch = 'r'; int fd = session->events->fds[1]; tr_lock * lock = session->events->lock; struct tr_run_data data; tr_lockLock( lock ); pipewrite( fd, &ch, 1 ); data.func = func; data.user_data = user_data; pipewrite( fd, &data, sizeof( data ) ); tr_lockUnlock( lock ); } }
/*********************************************************************** * tr_netResolveInit *********************************************************************** * Adds an address to the resolution queue. **********************************************************************/ tr_resolve_t * tr_netResolveInit( const char * address ) { tr_resolve_t * r; r = malloc( sizeof( tr_resolve_t ) ); r->status = TR_NET_WAIT; r->address = strdup( address ); r->refcount = 2; r->next = NULL; tr_lockLock( &resolveLock ); if( !resolveQueue ) { resolveQueue = r; } else { tr_resolve_t * iter; for( iter = resolveQueue; iter->next; iter = iter->next ); iter->next = r; } tr_lockUnlock( &resolveLock ); tr_condSignal( &resolveCond ); return r; }
void tr_globalUnlock( tr_session * session ) { assert( tr_isSession( session ) ); tr_lockUnlock( session->lock ); }
void tr_webRunWithBuffer( tr_session * session, const char * url, const char * range, tr_web_done_func done_func, void * done_func_user_data, struct evbuffer * buffer ) { struct tr_web * web = session->web; if( web != NULL ) { struct tr_web_task * task = tr_new0( struct tr_web_task, 1 ); task->session = session; task->url = tr_strdup( url ); task->range = tr_strdup( range ); task->done_func = done_func; task->done_func_user_data = done_func_user_data; task->response = buffer ? buffer : evbuffer_new( ); task->freebuf = buffer ? NULL : task->response; tr_lockLock( web->taskLock ); tr_list_append( &web->tasks, task ); tr_lockUnlock( web->taskLock ); } }
/*********************************************************************** * tr_netResolveThreadClose *********************************************************************** * Notices the gethostbyname thread that is should terminate. Doesn't * wait until it does, in case it is stuck in a resolution: we let it * die and clean itself up. **********************************************************************/ void tr_netResolveThreadClose() { tr_lockLock( &resolveLock ); resolveDie = 1; tr_lockUnlock( &resolveLock ); tr_condSignal( &resolveCond ); tr_wait( 200 ); }
void tr_upnpForwardPort( tr_upnp_t * upnp, int port ) { tr_lockLock( &upnp->lock ); tr_dbg( "upnp port changed from %i to %i", upnp->port, port ); upnp->port = port; tr_lockUnlock( &upnp->lock ); }
float tr_rcRate( tr_ratecontrol_t * r ) { float ret; tr_lockLock( &r->lock ); ret = rateForInterval( r, LONG_INTERVAL ); tr_lockUnlock( &r->lock ); return ret; }
void tr_upnpPulse( tr_upnp_t * upnp ) { tr_upnp_device_t ** ii; tr_lockLock( &upnp->lock ); if( upnp->active ) { /* pulse on all known devices */ upnp->discovering = 1; for( ii = &upnp->devices; NULL != *ii; ii = &(*ii)->next ) { if( devicePulse( *ii, upnp->fdlimit, upnp->port ) ) { upnp->discovering = 0; } } /* send an SSDP discover message */ if( upnp->discovering && upnp->lastdelay + upnp->lastdiscover < tr_date() ) { upnp->outfd = sendSSDP( upnp->fdlimit, upnp->outfd ); upnp->lastdiscover = tr_date(); upnp->lastdelay = MIN( upnp->lastdelay * 2, SSDP_MAX_DELAY ); } /* try to receive SSDP messages */ watchSSDP( &upnp->devices, upnp->infd ); if( watchSSDP( &upnp->devices, upnp->outfd ) ) { killSock( upnp->fdlimit, &upnp->outfd ); } } else { /* delete all mappings then delete devices */ ii = &upnp->devices; while( NULL != *ii ) { if( deviceStop( *ii ) ) { deviceRemove( ii, upnp->fdlimit ); } else { devicePulse( *ii, upnp->fdlimit, 0 ); ii = &(*ii)->next; } } } tr_lockUnlock( &upnp->lock ); }
int tr_rcCanTransfer( tr_ratecontrol_t * r ) { int ret; tr_lockLock( &r->lock ); ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) : ( rateForInterval( r, SHORT_INTERVAL ) < r->limit ); tr_lockUnlock( &r->lock ); return ret; }
bool tr_rand_buffer(void* buffer, size_t length) { bool ret; tr_lock* rng_lock = get_rng_lock(); TR_ASSERT(buffer != NULL); tr_lockLock(rng_lock); ret = check_result(API(RNG_GenerateBlock)(get_rng(), buffer, length)); tr_lockUnlock(rng_lock); return ret; }
tr_log_message * tr_logGetQueue (void) { tr_log_message * ret; tr_lockLock (getMessageLock ()); ret = myQueue; myQueue = NULL; myQueueTail = &myQueue; myQueueLength = 0; tr_lockUnlock (getMessageLock ()); return ret; }
static void node_free (tr_list* node) { tr_lock * lock = getRecycledNodesLock (); if (node != NULL) { *node = TR_LIST_CLEAR; tr_lockLock (lock); node->next = recycled_nodes; recycled_nodes = node; tr_lockUnlock (lock); } }
/*********************************************************************** * tr_netResolvePulse *********************************************************************** * Checks the current status of a resolution. **********************************************************************/ tr_tristate_t tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr ) { tr_tristate_t ret; tr_lockLock( &resolveLock ); ret = r->status; if( ret == TR_NET_OK ) { *addr = r->addr; } tr_lockUnlock( &resolveLock ); return ret; }
bool tr_dh_make_key (tr_dh_ctx_t raw_handle, size_t private_key_length UNUSED, uint8_t * public_key, size_t * public_key_length) { struct tr_dh_ctx * handle = raw_handle; word32 my_private_key_length, my_public_key_length; tr_lock * rng_lock = get_rng_lock (); assert (handle != NULL); assert (public_key != NULL); if (handle->private_key == NULL) handle->private_key = tr_malloc (handle->key_length); tr_lockLock (rng_lock); if (!check_result (DhGenerateKeyPair (&handle->dh, get_rng (), handle->private_key, &my_private_key_length, public_key, &my_public_key_length))) { tr_lockUnlock (rng_lock); return false; } tr_lockUnlock (rng_lock); tr_dh_align_key (public_key, my_public_key_length, handle->key_length); handle->private_key_length = my_private_key_length; if (public_key_length != NULL) *public_key_length = handle->key_length; return true; }
tr_msg_list * tr_getQueuedMessages( void ) { tr_msg_list * ret; tr_lockLock( getMessageLock( ) ); ret = messageQueue; messageQueue = NULL; messageQueueTail = &messageQueue; messageQueueCount = 0; tr_lockUnlock( getMessageLock( ) ); return ret; }
void tr_fdSocketClose( int s ) { tr_lockLock( gFd->lock ); if( s >= 0 ) { socketClose( s ); --gFd->socketCount; } assert( gFd->socketCount >= 0 ); tr_lockUnlock( gFd->lock ); }
void tr_chokingSetLimit( tr_choking_t * c, int limit ) { tr_lockLock( &c->lock ); if( limit < 0 ) c->slots = 4242; else /* Reckon a number of slots from the upload limit. There is no official right way to do this, the formula below e.g. gives: 10 KB/s -> 4 * 2.50 KB/s 20 KB/s -> 6 * 3.33 KB/s 50 KB/s -> 10 * 5.00 KB/s 100 KB/s -> 14 * 7.14 KB/s */ c->slots = lrintf( sqrt( 2 * limit ) ); tr_lockUnlock( &c->lock ); }
void tr_upnpStop( tr_upnp_t * upnp ) { tr_lockLock( &upnp->lock ); if( upnp->active ) { tr_inf( "stopping upnp" ); upnp->active = 0; killSock( upnp->fdlimit, &upnp->infd ); killSock( upnp->fdlimit, &upnp->outfd ); } tr_lockUnlock( &upnp->lock ); }
void tr_upnpStart( tr_upnp_t * upnp ) { tr_lockLock( &upnp->lock ); if( !upnp->active ) { tr_inf( "starting upnp" ); upnp->active = 1; upnp->discovering = 1; upnp->infd = mcastStart( upnp->fdlimit ); upnp->lastdiscover = 0; upnp->lastdelay = SSDP_FIRST_DELAY / 2; } tr_lockUnlock( &upnp->lock ); }
int tr_fdSocketAccept( int b, tr_address * addr, tr_port * port ) { int s = -1; unsigned int len; struct sockaddr_storage sock; assert( addr ); assert( port ); tr_lockLock( gFd->lock ); if( gFd->socketCount < getSocketMax( gFd ) ) { len = sizeof( struct sockaddr ); s = accept( b, (struct sockaddr *) &sock, &len ); } if( s > -1 ) { /* "The ss_family field of the sockaddr_storage structure will always * align with the family field of any protocol-specific structure." */ if( sock.ss_family == AF_INET ) { struct sockaddr_in * sock4 = (struct sockaddr_in *)&sock; addr->type = TR_AF_INET; addr->addr.addr4.s_addr = sock4->sin_addr.s_addr; *port = sock4->sin_port; } else { struct sockaddr_in6 * sock6 = (struct sockaddr_in6 *)&sock; addr->type = TR_AF_INET6; memcpy( &addr->addr, &sock6->sin6_addr, sizeof( struct sockaddr_in6 ) ); *port = sock6->sin6_port; } ++gFd->socketCount; } tr_lockUnlock( gFd->lock ); return s; }
int tr_fdSocketCreate( int type ) { int s = -1; tr_lockLock( gFd->lock ); if( gFd->socketCount < getSocketMax( gFd ) ) if( ( s = socket( AF_INET, type, 0 ) ) < 0 ) tr_err( _( "Couldn't create socket: %s" ), tr_strerror( sockerrno ) ); if( s > -1 ) ++gFd->socketCount; assert( gFd->socketCount >= 0 ); tr_lockUnlock( gFd->lock ); return s; }
static struct tr_web_task * tr_webRunImpl (tr_session * session, int torrentId, const char * url, const char * range, const char * cookies, tr_web_done_func done_func, void * done_func_user_data, struct evbuffer * buffer) { struct tr_web_task * task = NULL; if (!session->isClosing) { if (session->web == NULL) { tr_threadNew (tr_webThreadFunc, session); while (session->web == NULL) tr_wait_msec (20); } task = tr_new0 (struct tr_web_task, 1); task->session = session; task->torrentId = torrentId; task->url = tr_strdup (url); task->range = tr_strdup (range); task->cookies = tr_strdup (cookies); task->done_func = done_func; task->done_func_user_data = done_func_user_data; task->response = buffer ? buffer : evbuffer_new (); task->freebuf = buffer ? NULL : task->response; tr_lockLock (session->web->taskLock); task->next = session->web->tasks; session->web->tasks = task; tr_lockUnlock (session->web->taskLock); } return task; }
int tr_upnpStatus( tr_upnp_t * upnp ) { tr_upnp_device_t * ii; int ret; tr_lockLock( &upnp->lock ); if( !upnp->active ) { ret = ( NULL == upnp->devices ? TR_NAT_TRAVERSAL_DISABLED : TR_NAT_TRAVERSAL_UNMAPPING ); } else if( NULL == upnp->devices ) { ret = TR_NAT_TRAVERSAL_NOTFOUND; } else { ret = TR_NAT_TRAVERSAL_MAPPING; for( ii = upnp->devices; NULL != ii; ii = ii->next ) { if( UPNPDEV_STATE_ERROR == ii->state ) { ret = TR_NAT_TRAVERSAL_ERROR; } else if( 0 < ii->mappedport ) { ret = TR_NAT_TRAVERSAL_MAPPED; break; } } } tr_lockUnlock( &upnp->lock ); return ret; }
void tr_rcTransferred( tr_ratecontrol_t * r, int size ) { tr_transfer_t * t; if( size < 100 ) { /* Don't count small messages */ return; } tr_lockLock( &r->lock ); r->transferStop = ( r->transferStop + 1 ) % HISTORY_SIZE; if( r->transferStop == r->transferStart ) /* History is full, forget about the first (oldest) item */ r->transferStart = ( r->transferStart + 1 ) % HISTORY_SIZE; t = &r->transfers[r->transferStop]; t->date = tr_date(); t->size = size; tr_lockUnlock( &r->lock ); }
void tr_fdFileReturn( int fd ) { int i; tr_lockLock( gFd->lock ); for( i = 0; i < TR_MAX_OPEN_FILES; ++i ) { struct tr_openfile * o = &gFd->open[i]; if( o->fd != fd ) continue; dbgmsg( "releasing file '%s' in slot #%d", o->filename, i ); o->isCheckedOut = 0; if( o->closeWhenDone ) TrCloseFile( i ); break; } tr_lockUnlock( gFd->lock ); }