Changeset 12355


Ignore:
Timestamp:
Apr 13, 2011, 6:18:30 AM (11 years ago)
Author:
jordan
Message:

(trunk gtk) more heap pruning:

querying gconf2 each time the curl callack function is called is expensive, so query it once -- then again later, if the proxy settings change -- and remember the values in a local struct.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/main.c

    r12354 r12355  
    7777"2. Permission is granted to link the code in this release with the OpenSSL project's 'OpenSSL' library and to distribute the linked executables. Works derived from Transmission may, at their authors' discretion, keep or delete this exception.";
    7878
     79struct gtr_proxy_settings
     80{
     81    char * mode;
     82    char * autoconfig_url;
     83
     84    char * ftp_host;
     85    int ftp_port;
     86
     87    char * secure_host;
     88    int secure_port;
     89
     90    gboolean use_http_proxy;
     91    gboolean http_authenticate;
     92    char * http_host;
     93    int http_port;
     94    char * http_user;
     95    char * http_pass;
     96
     97    char * env_http_proxy;
     98};
     99
    79100struct cbdata
    80101{
    81     gboolean            is_iconified;
    82     guint               timer;
    83     guint               refresh_actions_tag;
    84     gpointer            icon;
    85     GtkWindow         * wind;
    86     TrCore            * core;
    87     GtkWidget         * msgwin;
    88     GtkWidget         * prefs;
    89     GSList            * error_list;
    90     GSList            * duplicates_list;
    91     GSList            * details;
    92     GtkTreeSelection  * sel;
    93     gpointer            quit_dialog;
     102    gboolean                    is_iconified;
     103    guint                       timer;
     104    guint                       refresh_actions_tag;
     105    gpointer                    icon;
     106    GtkWindow                 * wind;
     107    TrCore                    * core;
     108    GtkWidget                 * msgwin;
     109    GtkWidget                 * prefs;
     110    GSList                    * error_list;
     111    GSList                    * duplicates_list;
     112    GSList                    * details;
     113    GtkTreeSelection          * sel;
     114    gpointer                    quit_dialog;
     115    GObject                   * proxy_gconf_client;
     116    struct gtr_proxy_settings   proxy_settings;
    94117};
    95118
     
    609632}
    610633
     634/****
     635*****
     636*****  GNOME DESKTOP PROXY SETTINGS
     637*****
     638****/
     639
     640static void
     641proxy_settings_clear( struct gtr_proxy_settings * settings )
     642{
     643    g_free( settings->mode );
     644    g_free( settings->autoconfig_url );
     645    g_free( settings->ftp_host );
     646    g_free( settings->secure_host );
     647    g_free( settings->env_http_proxy );
     648    g_free( settings->http_host );
     649    g_free( settings->http_user );
     650    g_free( settings->http_pass );
     651    memset( settings, 0, sizeof( struct gtr_proxy_settings ) );
     652}
    611653
    612654#ifdef HAVE_GCONF2
    613 static void
    614 apply_desktop_proxy_settings( CURL * easy, GConfClient * client, const char * host_key, const char * port_key )
    615 {
    616     int port;
    617     GConfValue * value;
    618     static gboolean env_set;
    619     static gboolean env_checked = FALSE;
    620 
    621     /* Both libcurl and GNOME have hooks for proxy support.
    622      * If someone has set the http_proxy environment variable,
    623      * don't apply the GNOME settings here. That way libcurl can override GNOME. */
    624     if( !env_checked ) {
    625         const char * str = g_getenv( "http_proxy" );
    626         env_set = str && *str;
    627         env_checked = TRUE;
    628     }
    629     if( env_set )
     655
     656static char*
     657gtr_gconf_client_get_string( GConfClient * client, const char * key )
     658{
     659    GConfValue * value = gconf_client_get( client, key, NULL );
     660    char * ret = g_strdup( gconf_value_get_string( value ) );
     661    gconf_value_free( value );
     662    return ret;
     663}
     664static int
     665gtr_gconf_client_get_int( GConfClient * client, const char * key )
     666{
     667    GConfValue * value = gconf_client_get( client, key, NULL );
     668    int ret = gconf_value_get_int( value );
     669    gconf_value_free( value );
     670    return ret;
     671}
     672static gboolean
     673gtr_gconf_client_get_bool( GConfClient * client, const char * key )
     674{
     675    GConfValue * value = gconf_client_get( client, key, NULL );
     676    const gboolean ret = gconf_value_get_bool( value ) != 0;
     677    gconf_value_free( value );
     678    return ret;
     679}
     680static void
     681proxy_settings_populate( GConfClient * client, struct gtr_proxy_settings * settings )
     682{
     683    proxy_settings_clear( settings );
     684    settings->mode               = gtr_gconf_client_get_string ( client, "/system/proxy/mode" );
     685    settings->autoconfig_url     = gtr_gconf_client_get_string ( client, "/system/proxy/autoconfig_url" );
     686    settings->ftp_host           = gtr_gconf_client_get_string ( client, "/system/proxy/ftp_host" );
     687    settings->ftp_port           = gtr_gconf_client_get_int    ( client, "/system/proxy/ftp_port" );
     688    settings->secure_host        = gtr_gconf_client_get_string ( client, "/system/proxy/secure_host" );
     689    settings->secure_port        = gtr_gconf_client_get_int    ( client, "/system/proxy/secure_port" );
     690    settings->use_http_proxy     = gtr_gconf_client_get_bool   ( client, "/system/http_proxy/use_http_proxy" );
     691    settings->http_authenticate  = gtr_gconf_client_get_bool   ( client, "/system/http_proxy/use_authentication" );
     692    settings->http_host          = gtr_gconf_client_get_string ( client, "/system/http_proxy/host" );
     693    settings->http_port          = gtr_gconf_client_get_int    ( client, "/system/http_proxy/port" );
     694    settings->http_user          = gtr_gconf_client_get_string ( client, "/system/http_proxy/authentication_user" );
     695    settings->http_pass          = gtr_gconf_client_get_string ( client, "/system/http_proxy/authentication_password" );
     696    settings->env_http_proxy     = g_strdup( g_getenv( "http_proxy" ) );
     697}
     698
     699static void
     700gconf_proxy_settings_changed( GConfClient * client, guint cnxn_id UNUSED,
     701                              GConfEntry * entry UNUSED, gpointer gcbdata )
     702{
     703    struct cbdata * cbdata = gcbdata;
     704    struct gtr_proxy_settings * settings = &cbdata->proxy_settings;
     705    proxy_settings_populate( client, settings );
     706}
     707#endif
     708
     709static void
     710apply_desktop_proxy_settings( CURL * easy, const char * host, int port )
     711{
     712    if( host != NULL )
     713    {
     714        curl_easy_setopt( easy, CURLOPT_PROXY, host );
     715
     716        if( port )
     717            curl_easy_setopt( easy, CURLOPT_PROXYPORT, (long)port );
     718
     719        if( g_str_has_prefix( host, "socks4" ) )
     720            curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4 );
     721        else if( g_str_has_prefix( host, "socks5" ) )
     722            curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5 );
     723        else if( g_str_has_prefix( host, "http" ) )
     724            curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_HTTP );
     725    }
     726}
     727
     728static void
     729curl_config_func( tr_session * session UNUSED, void * vcurl UNUSED, const char * url, void * gproxy_settings )
     730{
     731    CURL *  easy = vcurl;
     732    const struct gtr_proxy_settings * settings = gproxy_settings;
     733
     734    /* The "http_proxy" environment variable is applied by libcurl.
     735     * Since it should take precedence over the GNOME session settings,
     736     * don't set anything here if "http_proxy" is set in the environment. */
     737    if( settings->env_http_proxy != NULL )
    630738        return;
    631739
    632     if(( value = gconf_client_get( client, host_key, NULL )))
    633     {
    634         const char * url = gconf_value_get_string( value );
    635 
    636         if( url && *url )
     740    if( !tr_strcmp0( settings->mode, "none" ) )
     741    {
     742        /* nooop */
     743    }
     744    else if( !tr_strcmp0( settings->mode, "auto" ) )
     745    {
     746        apply_desktop_proxy_settings( easy, settings->autoconfig_url, 0 );
     747    }
     748    else if( !tr_strcmp0( settings->mode, "manual" ))
     749    {
     750        gboolean authenticate = FALSE;
     751
     752        if( g_str_has_prefix( url, "ftp" ) )
    637753        {
    638             char * scheme = NULL;
    639             GConfValue * port_value;
    640 
    641             if( !tr_urlParse( url, strlen( url ), &scheme, NULL, NULL, NULL ) )
    642             {
    643                 if( !tr_strcmp0( scheme, "socks4" ) )
    644                     curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4 );
    645                 else if( !tr_strcmp0( scheme, "socks5" ) )
    646                     curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5 );
    647                 else if( !tr_strcmp0( scheme, "http" ) )
    648                     curl_easy_setopt( easy, CURLOPT_PROXYTYPE, (long)CURLPROXY_HTTP );
    649             }
    650 
    651             curl_easy_setopt( easy, CURLOPT_PROXY, url );
    652 
    653             if( port_key != NULL )
    654             {
    655                 if(( port_value = gconf_client_get( client, port_key, NULL )))
    656                 {
    657                     if(( port = gconf_value_get_int( value )))
    658                         curl_easy_setopt( easy, CURLOPT_PROXYPORT, (long)port );
    659 
    660                     gconf_value_free( port_value );
    661                 }
    662             }
    663 
    664             tr_free( scheme );
    665         }
    666 
    667         gconf_value_free( value );
    668     }
    669 }
     754            apply_desktop_proxy_settings( easy, settings->ftp_host, settings->ftp_port );
     755        }
     756        else if( g_str_has_prefix( url, "https" ) )
     757        {
     758            apply_desktop_proxy_settings( easy, settings->secure_host, settings->secure_port );
     759            authenticate = settings->http_authenticate;
     760        }
     761        else if( g_str_has_prefix( url, "http" ) )
     762        {
     763            apply_desktop_proxy_settings( easy, settings->http_host, settings->http_port );
     764            authenticate = settings->http_authenticate;
     765        }
     766
     767        if( authenticate && settings->http_user && settings->http_pass )
     768        {
     769            char * userpass = g_strdup_printf( "%s:%s", settings->http_user, settings->http_pass );
     770            curl_easy_setopt( easy, CURLOPT_PROXYUSERPWD, userpass );
     771            g_free( userpass );
     772        }
     773    }
     774    else
     775    {
     776        g_warning( "unhandled /system/proxy/mode: %s", settings->mode );
     777    }
     778}
     779
     780static void
     781proxy_setup( struct cbdata * cbdata )
     782{
     783    struct gtr_proxy_settings * settings = &cbdata->proxy_settings;
     784
     785#ifdef HAVE_GCONF2
     786    /* listen for gconf changes to /system/proxy and /system/http_proxy */
     787    GConfClient * client = gconf_client_get_default( );
     788    const char * key = "/system/proxy";
     789    gconf_client_add_dir( client, key, GCONF_CLIENT_PRELOAD_NONE, NULL );
     790    gconf_client_notify_add( client, key, gconf_proxy_settings_changed, cbdata, NULL, NULL );
     791    key = "/system/http_proxy";
     792    gconf_client_add_dir( client, key, GCONF_CLIENT_PRELOAD_NONE, NULL );
     793    gconf_client_notify_add( client, key, gconf_proxy_settings_changed, cbdata, NULL, NULL );
     794    cbdata->proxy_gconf_client = G_OBJECT( client );
     795    proxy_settings_populate( client, settings );
     796#else
     797    /* set up some default values for the proxy_settings struct */
     798    memset( settings, 0, sizeof( struct gtr_proxy_settings ) );
     799    settings->mode = g_strdup( "none" );
     800    settings->env_http_proxy = g_strdup( g_getenv( "http_proxy" ) );
    670801#endif
    671802
    672 static void
    673 curl_config_func( tr_session * session UNUSED, void * vcurl UNUSED, const char * destination )
    674 {
    675 #ifdef HAVE_GCONF2
    676     GConfValue * value;
    677     CURL * easy = vcurl;
    678     gboolean use_http_proxy = TRUE;
    679     GConfClient * client = gconf_client_get_default( );
    680 
    681     /* get GNOME's proxy mode */
    682     if(( value = gconf_client_get( client, "/system/proxy/mode", NULL )))
    683     {
    684         const char * mode = gconf_value_get_string( value );
    685 
    686         if( !tr_strcmp0( mode, "auto" ) )
    687         {
    688             apply_desktop_proxy_settings( easy, client, "/system/proxy/autoconfig_url", NULL );
    689             use_http_proxy = FALSE;
    690         }
    691         else if( !tr_strcmp0( mode, "manual" ))
    692         {
    693             char * scheme = NULL;
    694             if( !tr_urlParse( destination, strlen( destination ), &scheme, NULL, NULL, NULL ) )
    695             {
    696                 if( !tr_strcmp0( scheme, "ftp" ) )
    697                 {
    698                     apply_desktop_proxy_settings( easy, client, "/system/proxy/ftp_host", "/system/proxy/ftp_port" );
    699                     use_http_proxy = FALSE;
    700                 }
    701                 else if( !tr_strcmp0( scheme, "https" ) )
    702                 {
    703                     apply_desktop_proxy_settings( easy, client, "/system/proxy/secure_host", "/system/proxy/secure_port" );
    704                     use_http_proxy = FALSE;
    705                 }
    706             }
    707             tr_free( scheme );
    708         }
    709 
    710         gconf_value_free( value );
    711     }
    712 
    713     /* if this the proxy hasn't been handled yet and "use_http_proxy" is disabled, then don't use a proxy */
    714     if( use_http_proxy ) {
    715         if(( value = gconf_client_get( client, "/system/http_proxy/use_http_proxy", NULL ))) {
    716             use_http_proxy = gconf_value_get_bool( value ) != 0;
    717             gconf_value_free( value );
    718         }
    719     }
    720 
    721     if( use_http_proxy )
    722     {
    723         gboolean auth = FALSE;
    724         apply_desktop_proxy_settings( easy, client, "/system/http_proxy/host", "/system/http_proxy/port" );
    725 
    726         if(( value = gconf_client_get( client, "/system/http_proxy/use_authentication", NULL )))
    727         {
    728             auth = gconf_value_get_bool( value );
    729             gconf_value_free( value );
    730         }
    731 
    732         if( auth )
    733         {
    734             GConfValue * user_value = gconf_client_get( client, "/system/http_proxy/authentication_user", NULL );
    735             const char * user = ( user_value != NULL ) ? gconf_value_get_string( user_value ) : NULL;
    736             GConfValue * pass_value = gconf_client_get( client, "/system/http_proxy/authentication_password", NULL );
    737             const char * pass = ( pass_value != NULL ) ? gconf_value_get_string( pass_value ) : NULL;
    738 
    739             if( ( user != NULL ) && ( pass != NULL ) )
    740             {
    741                 char * userpass = g_strdup_printf( "%s:%s", user, pass );
    742                 curl_easy_setopt( easy, CURLOPT_PROXYUSERPWD, userpass );
    743                 g_free( userpass );
    744             }
    745 
    746             if( pass_value ) gconf_value_free( pass_value );
    747             if( user_value ) gconf_value_free( user_value );
    748         }
    749     }
    750 
    751     g_object_unref( G_OBJECT( client ) );
    752 #endif
    753 }
     803    /* set up the curl callback function */
     804    tr_sessionSetWebConfigFunc( gtr_core_session( cbdata->core ), curl_config_func, settings );
     805}
     806
     807
     808/****
     809*****
     810*****
     811****/
    754812
    755813int
     
    885943        /* initialize the libtransmission session */
    886944        session = tr_sessionInit( "gtk", configDir, TRUE, gtr_pref_get_all( ) );
    887         tr_sessionSetWebConfigFunc( session, curl_config_func );
    888945
    889946        gtr_pref_flag_set( TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( session ) );
    890947        gtr_pref_int_set( TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( session ) );
    891948        cbdata->core = gtr_core_new( session );
     949        proxy_setup( cbdata );
    892950
    893951        /* init the ui manager */
     
    11481206    }
    11491207
     1208    proxy_settings_clear( &cbdata->proxy_settings );
     1209    if( cbdata->proxy_gconf_client )
     1210        g_object_unref( cbdata->proxy_gconf_client );
    11501211    if( cbdata->prefs )
    11511212        gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) );
  • trunk/libtransmission/session.c

    r12303 r12355  
    25762576
    25772577void
    2578 tr_sessionSetWebConfigFunc( tr_session * session, void (*func)(tr_session*, void*, const char* ) )
     2578tr_sessionSetWebConfigFunc( tr_session * session, void (*func)(tr_session*, void*, const char*, void* ), void * user_data )
    25792579{
    25802580    session->curl_easy_config_func = func;
    2581 }
     2581    session->curl_easy_config_user_data = user_data;
     2582}
  • trunk/libtransmission/session.h

    r12303 r12355  
    5252struct tr_fdInfo;
    5353
    54 typedef void ( tr_web_config_func )( tr_session * session, void * curl_pointer, const char * url );
     54typedef void ( tr_web_config_func )( tr_session * session, void * curl_pointer, const char * url, void * user_data );
    5555
    5656struct tr_turtle_info
     
    208208
    209209    tr_web_config_func          * curl_easy_config_func;
     210    void                        * curl_easy_config_user_data;
    210211
    211212    uint8_t peer_id[PEER_ID_LEN+1];
  • trunk/libtransmission/web.c

    r12229 r12355  
    193193
    194194    if( s->curl_easy_config_func != NULL )
    195         s->curl_easy_config_func( s, e, task->url );
     195        s->curl_easy_config_func( s, e, task->url, s->curl_easy_config_user_data );
    196196
    197197    tr_free( cookie_filename );
  • trunk/libtransmission/web.h

    r12204 r12355  
    3838 * http://curl.haxx.se/libcurl/c/curl_easy_setopt.html()
    3939 */
    40 void tr_sessionSetWebConfigFunc( tr_session * session, void (*config)(tr_session * session, void * curl_pointer, const char * url ) );
     40void tr_sessionSetWebConfigFunc( tr_session * session, void (*config)(tr_session * session, void * curl_pointer, const char * url, void * user_data ), void * user_data );
    4141
    4242
Note: See TracChangeset for help on using the changeset viewer.