source: trunk/gtk/favicon.c @ 11896

Last change on this file since 11896 was 11896, checked in by jordan, 11 years ago

(trunk) #4032 "Better error detection / reporting in http announces" -- added to trunk.

This patch adds two new flags to the callback function -- did_connect and did_timeout -- that are calculated inside of web.c using information from libcurl. This allows the announcer to detect timeouts more accurately and also to distinguish between unresponsive peers (which get the preexisting "Tracker did not respond" error message) and unconnectable peers (which get a new error message, "Could not connect to tracker").

  • Property svn:keywords set to Date Rev Author Id
File size: 4.8 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: favicon.c 11896 2011-02-17 02:26:24Z jordan $
11 */
12
13#include <glib/gstdio.h> /* g_remove() */
14#include <gtk/gtk.h>
15
16#include <libtransmission/transmission.h>
17#include <libtransmission/web.h> /* tr_webRun() */
18
19#include "favicon.h"
20#include "util.h" /* gtr_mkdir_with_parents(), gtr_idle_add() */
21
22#define IMAGE_TYPES 4
23static const char * image_types[IMAGE_TYPES] = { "ico", "png", "gif", "jpg" };
24
25struct favicon_data
26{
27    tr_session * session;
28    GFunc func;
29    gpointer data;
30    char * host;
31    char * contents;
32    size_t len;
33    int type;
34};
35
36static char*
37get_url( const char * host, int image_type )
38{
39    return g_strdup_printf( "http://%s/favicon.%s", host, image_types[image_type] );
40}
41
42static char*
43favicon_get_cache_dir( void )
44{
45    static char * dir = NULL;
46
47    if( dir == NULL )
48    {
49        dir = g_build_filename( g_get_user_cache_dir(),
50                                "transmission",
51                                "favicons",
52                                NULL );
53        gtr_mkdir_with_parents( dir, 0777 );
54    }
55
56    return dir;
57}
58
59static char*
60favicon_get_cache_filename( const char * host )
61{
62    return g_build_filename( favicon_get_cache_dir(), host, NULL );
63}
64
65static void
66favicon_save_to_cache( const char * host, const void * data, size_t len )
67{
68    char * filename = favicon_get_cache_filename( host );
69    g_file_set_contents( filename, data, len, NULL );
70    g_free( filename );
71}
72
73static GdkPixbuf*
74favicon_load_from_cache( const char * host )
75{
76    char * filename = favicon_get_cache_filename( host );
77    GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file_at_size( filename, 16, 16, NULL );
78    if( pixbuf == NULL ) /* bad file */
79        g_remove( filename );
80    g_free( filename );
81    return pixbuf;
82}
83
84static void favicon_web_done_cb( tr_session*, tr_bool, tr_bool, long, const void*, size_t, void* );
85
86static gboolean
87favicon_web_done_idle_cb( gpointer vfav )
88{
89    GdkPixbuf * pixbuf = NULL;
90    gboolean finished = FALSE;
91    struct favicon_data * fav = vfav;
92
93    if( fav->len > 0 ) /* we got something... try to make a pixbuf from it */
94    {
95        favicon_save_to_cache( fav->host, fav->contents, fav->len );
96        pixbuf = favicon_load_from_cache( fav->host );
97        finished = pixbuf != NULL;
98    }
99
100    if( !finished ) /* no pixbuf yet... */
101    {
102        if( ++fav->type == IMAGE_TYPES ) /* failure */
103        {
104            finished = TRUE;
105        }
106        else /* keep trying */
107        {
108            char * url = get_url( fav->host, fav->type );
109
110            g_free( fav->contents );
111            fav->contents = NULL;
112            fav->len = 0;
113
114            tr_webRun( fav->session, url, NULL, favicon_web_done_cb, fav );
115            g_free( url );
116        }
117    }
118
119    if( finished )
120    {
121        fav->func( pixbuf, fav->data );
122        g_free( fav->host );
123        g_free( fav->contents );
124        g_free( fav );
125    }
126
127    return FALSE;
128}
129
130static void
131favicon_web_done_cb( tr_session    * session UNUSED,
132                     tr_bool         did_connect UNUSED,
133                     tr_bool         did_timeout UNUSED,
134                     long            code UNUSED,
135                     const void    * data,
136                     size_t          len,
137                     void          * vfav )
138{
139    struct favicon_data * fav = vfav;
140    fav->contents = g_memdup( data, len );
141    fav->len = len;
142
143    gtr_idle_add( favicon_web_done_idle_cb, fav );
144}
145
146void
147gtr_get_favicon( tr_session  * session,
148                 const char  * host,
149                 GFunc         pixbuf_ready_func,
150                 gpointer      pixbuf_ready_func_data )
151{
152    GdkPixbuf * pixbuf = favicon_load_from_cache( host );
153
154    if( pixbuf != NULL )
155    {
156        pixbuf_ready_func( pixbuf, pixbuf_ready_func_data );
157    }
158    else
159    {
160        struct favicon_data * data;
161        char * url = get_url( host, 0 );
162
163        data = g_new( struct favicon_data, 1 );
164        data->session = session;
165        data->func = pixbuf_ready_func;
166        data->data = pixbuf_ready_func_data;
167        data->host = g_strdup( host );
168        data->type = 0;
169
170        tr_webRun( session, url, NULL, favicon_web_done_cb, data );
171        g_free( url );
172    }
173}
174
175void
176gtr_get_favicon_from_url( tr_session  * session,
177                          const char  * url,
178                          GFunc         pixbuf_ready_func,
179                          gpointer      pixbuf_ready_func_data )
180{
181    char * host = gtr_get_host_from_url( url );
182    gtr_get_favicon( session, host, pixbuf_ready_func, pixbuf_ready_func_data );
183    g_free( host );
184}
Note: See TracBrowser for help on using the repository browser.