mirror of
https://github.com/transmission/transmission
synced 2024-12-24 16:52:39 +00:00
(gtk) use libT's curl wrapper for port testing & getting the blocklist
This commit is contained in:
parent
c46269805d
commit
0545e70f5b
2 changed files with 140 additions and 126 deletions
104
gtk/tr-prefs.c
104
gtk/tr-prefs.c
|
@ -14,9 +14,9 @@
|
|||
#include <unistd.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <third-party/miniupnp/miniwget.h>
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/web.h>
|
||||
#include "conf.h"
|
||||
#include "hig.h"
|
||||
#include "tr-core.h"
|
||||
|
@ -177,46 +177,48 @@ struct test_port_data
|
|||
gboolean * alive;
|
||||
};
|
||||
|
||||
static gpointer
|
||||
test_port( gpointer data_gpointer )
|
||||
static void
|
||||
testing_port_done( tr_handle * handle UNUSED,
|
||||
long response_code UNUSED,
|
||||
const void * response,
|
||||
size_t response_len,
|
||||
void * gdata )
|
||||
{
|
||||
struct test_port_data * data = data_gpointer;
|
||||
|
||||
struct test_port_data * data = gdata;
|
||||
if( *data->alive )
|
||||
{
|
||||
GObject * o = G_OBJECT( data->label );
|
||||
GtkSpinButton * spin = g_object_get_data( o, "tr-port-spin" );
|
||||
const int port = gtk_spin_button_get_value_as_int( spin );
|
||||
int isOpen;
|
||||
int size;
|
||||
char * text;
|
||||
char url[256];
|
||||
|
||||
g_usleep( G_USEC_PER_SEC * 3 ); /* give portmapping time to kick in */
|
||||
snprintf( url, sizeof(url), "http://portcheck.transmissionbt.com/%d", port );
|
||||
text = miniwget( url, &size );
|
||||
/*g_message(" got len %d, [%*.*s]", size, size, size, text );*/
|
||||
isOpen = text && *text=='1';
|
||||
free( text );
|
||||
|
||||
if( *data->alive )
|
||||
gtk_label_set_markup( GTK_LABEL(data->label), isOpen
|
||||
? _("Port is <b>open</b>")
|
||||
: _("Port is <b>closed</b>") );
|
||||
const int isOpen = response_len && *(char*)response=='1';
|
||||
gtk_label_set_markup( GTK_LABEL( data->label ), isOpen
|
||||
? _("Port is <b>open</b>")
|
||||
: _("Port is <b>closed</b>") );
|
||||
}
|
||||
}
|
||||
|
||||
g_free( data );
|
||||
return NULL;
|
||||
static gboolean
|
||||
testing_port_begin( gpointer gdata )
|
||||
{
|
||||
struct test_port_data * data = gdata;
|
||||
if( *data->alive )
|
||||
{
|
||||
GtkSpinButton * spin = g_object_get_data( G_OBJECT( data->label ), "tr-port-spin" );
|
||||
tr_handle * handle = g_object_get_data( G_OBJECT( data->label ), "handle" );
|
||||
const int port = gtk_spin_button_get_value_as_int( spin );
|
||||
char url[256];
|
||||
snprintf( url, sizeof(url), "http://portcheck.transmissionbt.com/%d", port );
|
||||
gtk_label_set_markup( GTK_LABEL( data->label ), _( "<i>Testing port...</i>" ) );
|
||||
tr_webRun( handle, url, testing_port_done, data );
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
testing_port_cb( GtkWidget * unused UNUSED, gpointer l )
|
||||
{
|
||||
/* wait three seconds to give the port forwarding time to kick in */
|
||||
struct test_port_data * data = g_new0( struct test_port_data, 1 );
|
||||
data->alive = g_object_get_data( G_OBJECT( l ), "alive" );
|
||||
data->label = l;
|
||||
gtk_label_set_markup( GTK_LABEL(l), _( "<i>Testing port...</i>" ) );
|
||||
g_thread_create( test_port, data, FALSE, NULL );
|
||||
data->alive = g_object_get_data( G_OBJECT( l ), "alive" );
|
||||
g_timeout_add( 3000, testing_port_begin, data );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -316,35 +318,30 @@ blocklistDialogAllowClose( gpointer dialog )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
updateBlocklist( gpointer vdata )
|
||||
static void
|
||||
got_blocklist( tr_handle * handle UNUSED,
|
||||
long response_code UNUSED,
|
||||
const void * response,
|
||||
size_t response_len,
|
||||
void * gdata )
|
||||
{
|
||||
struct blocklist_data * data = vdata;
|
||||
int size = 0;
|
||||
struct blocklist_data * data = gdata;
|
||||
const char * text = response;
|
||||
int size = response_len;
|
||||
int rules = 0;
|
||||
const char * url;
|
||||
char * text = NULL;
|
||||
gchar * filename = NULL;
|
||||
gchar * filename2 = NULL;
|
||||
int fd = -1;
|
||||
int ok = 1;
|
||||
|
||||
url = "http://download.m0k.org/transmission/files/level1.gz";
|
||||
|
||||
if( ok && !data->abortFlag )
|
||||
if( !data->abortFlag && ( !text || !size ) )
|
||||
{
|
||||
ok = FALSE;
|
||||
g_snprintf( data->secondary, sizeof( data->secondary ),
|
||||
_( "Retrieving blocklist..." ) );
|
||||
_( "Unable to get blocklist." ) );
|
||||
g_message( data->secondary );
|
||||
g_idle_add( blocklistDialogSetSecondary, data );
|
||||
text = miniwget( url, &size );
|
||||
if( !data->abortFlag && ( !text || !size ) ) {
|
||||
ok = FALSE;
|
||||
g_snprintf( data->secondary, sizeof( data->secondary ),
|
||||
_( "Unable to get blocklist." ) );
|
||||
g_message( data->secondary );
|
||||
g_idle_add( blocklistDialogSetSecondary, data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ok && !data->abortFlag )
|
||||
{
|
||||
|
@ -389,7 +386,6 @@ updateBlocklist( gpointer vdata )
|
|||
g_idle_add( updateBlocklistTextFromData, data );
|
||||
}
|
||||
|
||||
free( text );
|
||||
/* g_free( data ); */
|
||||
if( filename2 ) {
|
||||
unlink( filename2 );
|
||||
|
@ -399,7 +395,6 @@ updateBlocklist( gpointer vdata )
|
|||
unlink( filename );
|
||||
g_free( filename );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -419,12 +414,16 @@ onUpdateBlocklistCB( GtkButton * w, gpointer gdata )
|
|||
{
|
||||
GtkWidget * d;
|
||||
struct blocklist_data * data = gdata;
|
||||
tr_handle * handle = g_object_get_data( G_OBJECT( w ), "handle" );
|
||||
const char * url = "http://download.m0k.org/transmission/files/level1.gz";
|
||||
|
||||
d = gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( w ) ) ),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_NONE,
|
||||
_( "Updating Blocklist" ) );
|
||||
gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( d ),
|
||||
_( "Retrieving blocklist..." ) );
|
||||
gtk_dialog_add_buttons( GTK_DIALOG( d ),
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
|
@ -435,7 +434,8 @@ onUpdateBlocklistCB( GtkButton * w, gpointer gdata )
|
|||
|
||||
g_signal_connect( d, "response", G_CALLBACK(onUpdateBlocklistResponseCB), data );
|
||||
gtk_widget_show( d );
|
||||
g_thread_create( updateBlocklist, data, FALSE, NULL );
|
||||
|
||||
tr_webRun( handle, url, got_blocklist, data );
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
|
@ -462,6 +462,7 @@ peerPage( GObject * core )
|
|||
data->core = TR_CORE( core );
|
||||
data->check = w;
|
||||
|
||||
g_object_set_data( G_OBJECT( b ), "handle", tr_core_handle( TR_CORE( core ) ) );
|
||||
g_signal_connect( b, "clicked", G_CALLBACK(onUpdateBlocklistCB), data );
|
||||
gtk_box_pack_start( GTK_BOX(h), b, FALSE, FALSE, 0 );
|
||||
g_signal_connect( w, "toggled", G_CALLBACK(target_cb), b );
|
||||
|
@ -533,6 +534,7 @@ networkPage( GObject * core, gpointer alive )
|
|||
|
||||
g_object_set_data( G_OBJECT(l), "tr-port-spin", w2 );
|
||||
g_object_set_data( G_OBJECT(l), "alive", alive );
|
||||
g_object_set_data( G_OBJECT(l), "handle", tr_core_handle( TR_CORE( core ) ) );
|
||||
testing_port_cb( NULL, l );
|
||||
|
||||
g_signal_connect( w, "toggled", G_CALLBACK(testing_port_cb), l );
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
|
||||
/*
|
||||
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
|
||||
*
|
||||
* This file is licensed by the GPL version 2. Works owned by the
|
||||
* Transmission project are granted a special exemption to clause 2(b)
|
||||
|
@ -15,6 +16,7 @@
|
|||
#include <curl/curl.h>
|
||||
|
||||
#include "transmission.h"
|
||||
#include "trevent.h"
|
||||
#include "utils.h"
|
||||
#include "web.h"
|
||||
|
||||
|
@ -28,9 +30,7 @@
|
|||
#define USE_CURL_MULTI_SOCKET
|
||||
#else
|
||||
#define PULSE_MSEC 200
|
||||
static void pulse( int socket UNUSED, short action UNUSED, void * vweb );
|
||||
#endif
|
||||
static void processCompletedTasks( tr_web * );
|
||||
|
||||
#define dbgmsg(fmt...) tr_deepLog( __FILE__, __LINE__, "web", ##fmt )
|
||||
|
||||
|
@ -46,80 +46,24 @@ struct tr_web_task
|
|||
{
|
||||
unsigned long tag;
|
||||
struct evbuffer * response;
|
||||
char * url;
|
||||
tr_session * session;
|
||||
tr_web_done_func * done_func;
|
||||
void * done_func_user_data;
|
||||
};
|
||||
|
||||
static size_t
|
||||
writeFunc( void * ptr, size_t size, size_t nmemb, void * task )
|
||||
{
|
||||
const size_t byteCount = size * nmemb;
|
||||
evbuffer_add( ((struct tr_web_task*)task)->response, ptr, byteCount );
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
static void
|
||||
pump( tr_web * web )
|
||||
{
|
||||
int unused;
|
||||
CURLMcode rc;
|
||||
do
|
||||
#ifdef USE_CURL_MULTI_SOCKET
|
||||
rc = curl_multi_socket_all( web->cm, &unused );
|
||||
#else
|
||||
rc = curl_multi_perform( web->cm, &unused );
|
||||
#endif
|
||||
while( rc == CURLM_CALL_MULTI_PERFORM );
|
||||
if ( rc == CURLM_OK )
|
||||
processCompletedTasks( web );
|
||||
else
|
||||
tr_err( "%s", curl_multi_strerror(rc) );
|
||||
}
|
||||
|
||||
void
|
||||
tr_webRun( tr_session * session,
|
||||
const char * url,
|
||||
tr_web_done_func * done_func,
|
||||
void * done_func_user_data )
|
||||
{
|
||||
static unsigned long tag = 0;
|
||||
struct tr_web_task * task;
|
||||
struct tr_web * web = session->web;
|
||||
CURL * ch;
|
||||
|
||||
task = tr_new0( struct tr_web_task, 1 );
|
||||
task->done_func = done_func;
|
||||
task->done_func_user_data = done_func_user_data;
|
||||
task->tag = ++tag;
|
||||
task->response = evbuffer_new( );
|
||||
|
||||
dbgmsg( "adding task #%lu [%s]", task->tag, url );
|
||||
++web->remain;
|
||||
|
||||
ch = curl_easy_init( );
|
||||
curl_easy_setopt( ch, CURLOPT_PRIVATE, task );
|
||||
curl_easy_setopt( ch, CURLOPT_URL, url );
|
||||
curl_easy_setopt( ch, CURLOPT_WRITEFUNCTION, writeFunc );
|
||||
curl_easy_setopt( ch, CURLOPT_WRITEDATA, task );
|
||||
curl_easy_setopt( ch, CURLOPT_USERAGENT, TR_NAME "/" LONG_VERSION_STRING );
|
||||
curl_easy_setopt( ch, CURLOPT_SSL_VERIFYPEER, 0 );
|
||||
curl_multi_add_handle( web->cm, ch );
|
||||
|
||||
pump( web );
|
||||
}
|
||||
|
||||
static void
|
||||
processCompletedTasks( tr_web * web )
|
||||
{
|
||||
int more = 0;
|
||||
CURL * easy;
|
||||
CURLMsg * msg;
|
||||
CURLcode res;
|
||||
|
||||
do {
|
||||
/* find a completed task. this idea is from the "hiperinfo.c"
|
||||
* sample that questions the safety of removing an easy handle
|
||||
* inside the curl_multi_info_read loop */
|
||||
/* this convoluted loop is from the "hiperinfo.c" sample which
|
||||
* hints that removing an easy handle in curl_multi_info_read's
|
||||
* loop may be unsafe */
|
||||
int more;
|
||||
easy = NULL;
|
||||
while(( msg = curl_multi_info_read( web->cm, &more ))) {
|
||||
if( msg->msg == CURLMSG_DONE ) {
|
||||
|
@ -133,9 +77,8 @@ processCompletedTasks( tr_web * web )
|
|||
int response_code;
|
||||
curl_easy_getinfo( easy, CURLINFO_PRIVATE, &task );
|
||||
curl_easy_getinfo( easy, CURLINFO_RESPONSE_CODE, &response_code );
|
||||
|
||||
--web->remain;
|
||||
dbgmsg( "task #%lu done (%d tasks remain)", task->tag, web->remain );
|
||||
dbgmsg( "task #%lu done (%d remain)", task->tag, web->remain );
|
||||
task->done_func( web->session,
|
||||
response_code,
|
||||
EVBUFFER_DATA(task->response),
|
||||
|
@ -145,16 +88,85 @@ processCompletedTasks( tr_web * web )
|
|||
curl_multi_remove_handle( web->cm, easy );
|
||||
curl_easy_cleanup( easy );
|
||||
evbuffer_free( task->response );
|
||||
tr_free( task->url );
|
||||
tr_free( task );
|
||||
}
|
||||
} while( easy );
|
||||
}
|
||||
|
||||
static void
|
||||
pump( tr_web * web )
|
||||
{
|
||||
int unused;
|
||||
CURLMcode rc;
|
||||
do {
|
||||
#ifdef USE_CURL_MULTI_SOCKET
|
||||
rc = curl_multi_socket_all( web->cm, &unused );
|
||||
#else
|
||||
rc = curl_multi_perform( web->cm, &unused );
|
||||
#endif
|
||||
} while( rc == CURLM_CALL_MULTI_PERFORM );
|
||||
if ( rc == CURLM_OK )
|
||||
processCompletedTasks( web );
|
||||
else
|
||||
tr_err( "%s", curl_multi_strerror(rc) );
|
||||
}
|
||||
|
||||
static size_t
|
||||
writeFunc( void * ptr, size_t size, size_t nmemb, void * task )
|
||||
{
|
||||
const size_t byteCount = size * nmemb;
|
||||
evbuffer_add( ((struct tr_web_task*)task)->response, ptr, byteCount );
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
static void
|
||||
addTask( void * vtask )
|
||||
{
|
||||
struct tr_web_task * task = vtask;
|
||||
struct tr_web * web = task->session->web;
|
||||
CURL * ch;
|
||||
|
||||
dbgmsg( "adding task #%lu [%s]", task->tag, task->url );
|
||||
++web->remain;
|
||||
|
||||
ch = curl_easy_init( );
|
||||
curl_easy_setopt( ch, CURLOPT_PRIVATE, task );
|
||||
curl_easy_setopt( ch, CURLOPT_URL, task->url );
|
||||
curl_easy_setopt( ch, CURLOPT_WRITEFUNCTION, writeFunc );
|
||||
curl_easy_setopt( ch, CURLOPT_WRITEDATA, task );
|
||||
curl_easy_setopt( ch, CURLOPT_USERAGENT, TR_NAME "/" LONG_VERSION_STRING );
|
||||
curl_easy_setopt( ch, CURLOPT_SSL_VERIFYPEER, 0 );
|
||||
curl_multi_add_handle( web->cm, ch );
|
||||
|
||||
pump( web );
|
||||
}
|
||||
|
||||
void
|
||||
tr_webRun( tr_session * session,
|
||||
const char * url,
|
||||
tr_web_done_func * done_func,
|
||||
void * done_func_user_data )
|
||||
{
|
||||
static unsigned long tag = 0;
|
||||
struct tr_web_task * task;
|
||||
|
||||
task = tr_new0( struct tr_web_task, 1 );
|
||||
task->session = session;
|
||||
task->url = tr_strdup( url );
|
||||
task->done_func = done_func;
|
||||
task->done_func_user_data = done_func_user_data;
|
||||
task->tag = ++tag;
|
||||
task->response = evbuffer_new( );
|
||||
|
||||
tr_runInEventThread( session, addTask, task );
|
||||
}
|
||||
|
||||
#ifdef USE_CURL_MULTI_SOCKET
|
||||
|
||||
/* libevent says that sock is ready to be processed, so tell libcurl */
|
||||
static void
|
||||
event_callback( int sock, short action, void * vweb )
|
||||
ev_sock_cb( int sock, short action, void * vweb )
|
||||
{
|
||||
tr_web * web = vweb;
|
||||
CURLMcode rc;
|
||||
|
@ -167,13 +179,14 @@ event_callback( int sock, short action, void * vweb )
|
|||
default: tr_err( "Unknown event %hd\n", action ); return;
|
||||
}
|
||||
|
||||
do rc = curl_multi_socket_action( web->cm, sock, mask, &unused );
|
||||
while( rc == CURLM_CALL_MULTI_PERFORM );
|
||||
|
||||
if ( rc != CURLM_OK )
|
||||
do {
|
||||
rc = curl_multi_socket_action( web->cm, sock, mask, &unused );
|
||||
} while( rc == CURLM_CALL_MULTI_PERFORM );
|
||||
if ( rc == CURLM_OK )
|
||||
processCompletedTasks( web );
|
||||
else
|
||||
tr_err( "%s (%d)", curl_multi_strerror(rc), (int)sock );
|
||||
|
||||
processCompletedTasks( web );
|
||||
}
|
||||
|
||||
/* CURLMPOPT_SOCKETFUNCTION */
|
||||
|
@ -205,7 +218,7 @@ multi_sock_cb( CURL * easy UNUSED,
|
|||
kind = EV_PERSIST;
|
||||
if( action & CURL_POLL_IN ) kind |= EV_READ;
|
||||
if( action & CURL_POLL_OUT ) kind |= EV_WRITE;
|
||||
event_set( ev, sock, kind, event_callback, web );
|
||||
event_set( ev, sock, kind, ev_sock_cb, web );
|
||||
event_add( ev, NULL );
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +258,6 @@ pulse( int socket UNUSED, short action UNUSED, void * vweb )
|
|||
struct timeval tv = tr_timevalMsec( PULSE_MSEC );
|
||||
|
||||
pump( web );
|
||||
processCompletedTasks( web );
|
||||
|
||||
evtimer_del( &web->timer );
|
||||
evtimer_add( &web->timer, &tv );
|
||||
|
|
Loading…
Reference in a new issue