Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/proxy.c

    r71abe93 rdbca297  
    5151#endif
    5252
     53static GHashTable *phb_hash = NULL;
     54
    5355struct PHB {
    5456        b_event_handler func, proxy_func;
     
    6163};
    6264
     65typedef int (*proxy_connect_func)(const char *host, unsigned short port_, struct PHB *phb);
     66
    6367static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb);
    6468
    65 static gboolean phb_close(struct PHB *phb)
    66 {
    67         close(phb->fd);
    68         phb->func(phb->data, -1, B_EV_IO_READ);
     69static gboolean phb_free(struct PHB *phb, gboolean success)
     70{
     71        g_hash_table_remove(phb_hash, &phb->fd);
     72
     73        if (!success) {
     74                if (phb->fd > 0) {
     75                        closesocket(phb->fd);
     76                }
     77                if (phb->func) {
     78                        phb->func(phb->data, -1, B_EV_IO_READ);
     79                }
     80        }
     81        if (phb->gai) {
     82                freeaddrinfo(phb->gai);
     83        }
    6984        g_free(phb->host);
    7085        g_free(phb);
     
    89104                                dup2(new_fd, source);
    90105                                closesocket(new_fd);
     106                                phb->fd = source;
    91107                                phb->inpa = b_input_add(source, B_EV_IO_WRITE, proxy_connected, phb);
    92108                                return FALSE;
     
    101117
    102118        freeaddrinfo(phb->gai);
     119        phb->gai = NULL;
     120
    103121        b_event_remove(phb->inpa);
    104122        phb->inpa = 0;
     123
    105124        if (phb->proxy_func) {
    106125                phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
    107126        } else {
    108127                phb->func(phb->data, source, B_EV_IO_READ);
    109                 g_free(phb);
     128                phb_free(phb, TRUE);
    110129        }
    111130
     
    171190
    172191        if (fd < 0 && host) {
    173                 g_free(phb);
     192                phb_free(phb, TRUE);
    174193        }
    175194
     
    204223            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    205224                phb->func(phb->data, source, B_EV_IO_READ);
    206                 g_free(phb->host);
    207                 g_free(phb);
    208                 return FALSE;
    209         }
    210 
    211         return phb_close(phb);
     225                return phb_free(phb, TRUE);
     226        }
     227
     228        return phb_free(phb, FALSE);
    212229}
    213230
     
    224241        len = sizeof(error);
    225242        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    226                 return phb_close(phb);
     243                return phb_free(phb, FALSE);
    227244        }
    228245        sock_make_blocking(source);
     
    231248                   phb->host, phb->port);
    232249        if (send(source, cmd, strlen(cmd), 0) < 0) {
    233                 return phb_close(phb);
     250                return phb_free(phb, FALSE);
    234251        }
    235252
     
    242259                g_free(t2);
    243260                if (send(source, cmd, strlen(cmd), 0) < 0) {
    244                         return phb_close(phb);
     261                        return phb_free(phb, FALSE);
    245262                }
    246263        }
     
    248265        g_snprintf(cmd, sizeof(cmd), "\r\n");
    249266        if (send(source, cmd, strlen(cmd), 0) < 0) {
    250                 return phb_close(phb);
     267                return phb_free(phb, FALSE);
    251268        }
    252269
     
    279296        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    280297                phb->func(phb->data, source, B_EV_IO_READ);
    281                 g_free(phb->host);
    282                 g_free(phb);
    283                 return FALSE;
    284         }
    285 
    286         return phb_close(phb);
     298                return phb_free(phb, TRUE);
     299        }
     300
     301        return phb_free(phb, FALSE);
    287302}
    288303
     
    294309        socklen_t len;
    295310        int error = ETIMEDOUT;
     311        gboolean is_socks4a = (proxytype == PROXY_SOCKS4A);
    296312
    297313        if (phb->inpa > 0) {
     
    300316        len = sizeof(error);
    301317        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    302                 return phb_close(phb);
     318                return phb_free(phb, FALSE);
    303319        }
    304320        sock_make_blocking(source);
    305321
    306         /* XXX does socks4 not support host name lookups by the proxy? */
    307         if (!(hp = gethostbyname(phb->host))) {
    308                 return phb_close(phb);
     322        if (!is_socks4a && !(hp = gethostbyname(phb->host))) {
     323                return phb_free(phb, FALSE);
    309324        }
    310325
     
    313328        packet[2] = phb->port >> 8;
    314329        packet[3] = phb->port & 0xff;
    315         packet[4] = (unsigned char) (hp->h_addr_list[0])[0];
    316         packet[5] = (unsigned char) (hp->h_addr_list[0])[1];
    317         packet[6] = (unsigned char) (hp->h_addr_list[0])[2];
    318         packet[7] = (unsigned char) (hp->h_addr_list[0])[3];
     330        if (is_socks4a) {
     331                packet[4] = 0;
     332                packet[5] = 0;
     333                packet[6] = 0;
     334                packet[7] = 1;
     335        } else {
     336                packet[4] = (unsigned char) (hp->h_addr_list[0])[0];
     337                packet[5] = (unsigned char) (hp->h_addr_list[0])[1];
     338                packet[6] = (unsigned char) (hp->h_addr_list[0])[2];
     339                packet[7] = (unsigned char) (hp->h_addr_list[0])[3];
     340        }
    319341        packet[8] = 0;
    320342        if (write(source, packet, 9) != 9) {
    321                 return phb_close(phb);
     343                return phb_free(phb, FALSE);
     344        }
     345
     346        if (is_socks4a) {
     347                size_t host_len = strlen(phb->host) + 1; /* include the \0 */
     348
     349                if (write(source, phb->host, host_len) != host_len) {
     350                        return phb_free(phb, FALSE);
     351                }
    322352        }
    323353
     
    348378
    349379        if (read(source, buf, 10) < 10) {
    350                 return phb_close(phb);
     380                return phb_free(phb, FALSE);
    351381        }
    352382        if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
    353                 return phb_close(phb);
     383                return phb_free(phb, FALSE);
    354384        }
    355385
    356386        phb->func(phb->data, source, B_EV_IO_READ);
    357         g_free(phb->host);
    358         g_free(phb);
    359 
    360         return FALSE;
     387        return phb_free(phb, TRUE);
    361388}
    362389
     
    377404
    378405        if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
    379                 phb_close(phb);
     406                phb_free(phb, FALSE);
    380407                return;
    381408        }
     
    392419
    393420        if (read(source, buf, 2) < 2) {
    394                 return phb_close(phb);
     421                return phb_free(phb, FALSE);
    395422        }
    396423
    397424        if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
    398                 return phb_close(phb);
     425                return phb_free(phb, FALSE);
    399426        }
    400427
     
    412439
    413440        if (read(source, buf, 2) < 2) {
    414                 return phb_close(phb);
     441                return phb_free(phb, FALSE);
    415442        }
    416443
    417444        if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
    418                 return phb_close(phb);
     445                return phb_free(phb, FALSE);
    419446        }
    420447
     
    427454                memcpy(buf + 2 + i + 1, proxypass, j);
    428455                if (write(source, buf, 3 + i + j) < 3 + i + j) {
    429                         return phb_close(phb);
     456                        return phb_free(phb, FALSE);
    430457                }
    431458
     
    451478        len = sizeof(error);
    452479        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    453                 return phb_close(phb);
     480                return phb_free(phb, FALSE);
    454481        }
    455482        sock_make_blocking(source);
     
    469496
    470497        if (write(source, buf, i) < i) {
    471                 return phb_close(phb);
     498                return phb_free(phb, FALSE);
    472499        }
    473500
     
    487514}
    488515
     516static const proxy_connect_func proxy_connect_funcs_array[] = {
     517        proxy_connect_none,   /* PROXY_NONE */
     518        proxy_connect_http,   /* PROXY_HTTP */
     519        proxy_connect_socks4, /* PROXY_SOCKS4 */
     520        proxy_connect_socks5, /* PROXY_SOCKS5 */
     521        proxy_connect_socks4, /* PROXY_SOCKS4A */
     522};
    489523
    490524/* Export functions */
     
    493527{
    494528        struct PHB *phb;
     529        proxy_connect_func fun;
     530        int fd;
     531
     532        if (!phb_hash) {
     533                phb_hash = g_hash_table_new(g_int_hash, g_int_equal);
     534        }
    495535
    496536        if (!host || port <= 0 || !func || strlen(host) > 128) {
     
    502542        phb->data = data;
    503543
    504         if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) {
    505                 return proxy_connect_none(host, port, phb);
    506         } else if (proxytype == PROXY_HTTP) {
    507                 return proxy_connect_http(host, port, phb);
    508         } else if (proxytype == PROXY_SOCKS4) {
    509                 return proxy_connect_socks4(host, port, phb);
    510         } else if (proxytype == PROXY_SOCKS5) {
    511                 return proxy_connect_socks5(host, port, phb);
    512         }
    513 
    514         g_free(phb);
    515         return -1;
    516 }
     544        if (proxyhost[0] && proxyport > 0 && proxytype >= 0 && proxytype < G_N_ELEMENTS(proxy_connect_funcs_array)) {
     545                fun = proxy_connect_funcs_array[proxytype];
     546        } else {
     547                fun = proxy_connect_none;
     548        }
     549
     550        fd = fun(host, port, phb);
     551
     552        if (fd != -1) {
     553                g_hash_table_insert(phb_hash, &phb->fd, phb);
     554        }
     555
     556        return fd;
     557}
     558
     559void proxy_disconnect(int fd)
     560{
     561        struct PHB *phb = g_hash_table_lookup(phb_hash, &fd);
     562
     563        if (!phb) {
     564                /* not in the early part of the connection - just close the fd */
     565                closesocket(fd);
     566                return;
     567        }
     568
     569        if (phb->inpa) {
     570                b_event_remove(phb->inpa);
     571                phb->inpa = 0;
     572        }
     573
     574        /* avoid calling the callback, which might result in double-free */
     575        phb->func = NULL;
     576
     577        /* close and free */
     578        phb_free(phb, FALSE);
     579}
Note: See TracChangeset for help on using the changeset viewer.