Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/proxy.c

    rdbca297 r71abe93  
    5151#endif
    5252
    53 static GHashTable *phb_hash = NULL;
    54 
    5553struct PHB {
    5654        b_event_handler func, proxy_func;
     
    6361};
    6462
    65 typedef int (*proxy_connect_func)(const char *host, unsigned short port_, struct PHB *phb);
    66 
    6763static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb);
    6864
    69 static 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         }
     65static gboolean phb_close(struct PHB *phb)
     66{
     67        close(phb->fd);
     68        phb->func(phb->data, -1, B_EV_IO_READ);
    8469        g_free(phb->host);
    8570        g_free(phb);
     
    10489                                dup2(new_fd, source);
    10590                                closesocket(new_fd);
    106                                 phb->fd = source;
    10791                                phb->inpa = b_input_add(source, B_EV_IO_WRITE, proxy_connected, phb);
    10892                                return FALSE;
     
    117101
    118102        freeaddrinfo(phb->gai);
    119         phb->gai = NULL;
    120 
    121103        b_event_remove(phb->inpa);
    122104        phb->inpa = 0;
    123 
    124105        if (phb->proxy_func) {
    125106                phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
    126107        } else {
    127108                phb->func(phb->data, source, B_EV_IO_READ);
    128                 phb_free(phb, TRUE);
     109                g_free(phb);
    129110        }
    130111
     
    190171
    191172        if (fd < 0 && host) {
    192                 phb_free(phb, TRUE);
     173                g_free(phb);
    193174        }
    194175
     
    223204            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    224205                phb->func(phb->data, source, B_EV_IO_READ);
    225                 return phb_free(phb, TRUE);
    226         }
    227 
    228         return phb_free(phb, FALSE);
     206                g_free(phb->host);
     207                g_free(phb);
     208                return FALSE;
     209        }
     210
     211        return phb_close(phb);
    229212}
    230213
     
    241224        len = sizeof(error);
    242225        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    243                 return phb_free(phb, FALSE);
     226                return phb_close(phb);
    244227        }
    245228        sock_make_blocking(source);
     
    248231                   phb->host, phb->port);
    249232        if (send(source, cmd, strlen(cmd), 0) < 0) {
    250                 return phb_free(phb, FALSE);
     233                return phb_close(phb);
    251234        }
    252235
     
    259242                g_free(t2);
    260243                if (send(source, cmd, strlen(cmd), 0) < 0) {
    261                         return phb_free(phb, FALSE);
     244                        return phb_close(phb);
    262245                }
    263246        }
     
    265248        g_snprintf(cmd, sizeof(cmd), "\r\n");
    266249        if (send(source, cmd, strlen(cmd), 0) < 0) {
    267                 return phb_free(phb, FALSE);
     250                return phb_close(phb);
    268251        }
    269252
     
    296279        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    297280                phb->func(phb->data, source, B_EV_IO_READ);
    298                 return phb_free(phb, TRUE);
    299         }
    300 
    301         return phb_free(phb, FALSE);
     281                g_free(phb->host);
     282                g_free(phb);
     283                return FALSE;
     284        }
     285
     286        return phb_close(phb);
    302287}
    303288
     
    309294        socklen_t len;
    310295        int error = ETIMEDOUT;
    311         gboolean is_socks4a = (proxytype == PROXY_SOCKS4A);
    312296
    313297        if (phb->inpa > 0) {
     
    316300        len = sizeof(error);
    317301        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    318                 return phb_free(phb, FALSE);
     302                return phb_close(phb);
    319303        }
    320304        sock_make_blocking(source);
    321305
    322         if (!is_socks4a && !(hp = gethostbyname(phb->host))) {
    323                 return phb_free(phb, FALSE);
     306        /* XXX does socks4 not support host name lookups by the proxy? */
     307        if (!(hp = gethostbyname(phb->host))) {
     308                return phb_close(phb);
    324309        }
    325310
     
    328313        packet[2] = phb->port >> 8;
    329314        packet[3] = phb->port & 0xff;
    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         }
     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];
    341319        packet[8] = 0;
    342320        if (write(source, packet, 9) != 9) {
    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                 }
     321                return phb_close(phb);
    352322        }
    353323
     
    378348
    379349        if (read(source, buf, 10) < 10) {
    380                 return phb_free(phb, FALSE);
     350                return phb_close(phb);
    381351        }
    382352        if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
    383                 return phb_free(phb, FALSE);
     353                return phb_close(phb);
    384354        }
    385355
    386356        phb->func(phb->data, source, B_EV_IO_READ);
    387         return phb_free(phb, TRUE);
     357        g_free(phb->host);
     358        g_free(phb);
     359
     360        return FALSE;
    388361}
    389362
     
    404377
    405378        if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
    406                 phb_free(phb, FALSE);
     379                phb_close(phb);
    407380                return;
    408381        }
     
    419392
    420393        if (read(source, buf, 2) < 2) {
    421                 return phb_free(phb, FALSE);
     394                return phb_close(phb);
    422395        }
    423396
    424397        if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
    425                 return phb_free(phb, FALSE);
     398                return phb_close(phb);
    426399        }
    427400
     
    439412
    440413        if (read(source, buf, 2) < 2) {
    441                 return phb_free(phb, FALSE);
     414                return phb_close(phb);
    442415        }
    443416
    444417        if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
    445                 return phb_free(phb, FALSE);
     418                return phb_close(phb);
    446419        }
    447420
     
    454427                memcpy(buf + 2 + i + 1, proxypass, j);
    455428                if (write(source, buf, 3 + i + j) < 3 + i + j) {
    456                         return phb_free(phb, FALSE);
     429                        return phb_close(phb);
    457430                }
    458431
     
    478451        len = sizeof(error);
    479452        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    480                 return phb_free(phb, FALSE);
     453                return phb_close(phb);
    481454        }
    482455        sock_make_blocking(source);
     
    496469
    497470        if (write(source, buf, i) < i) {
    498                 return phb_free(phb, FALSE);
     471                return phb_close(phb);
    499472        }
    500473
     
    514487}
    515488
    516 static 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 };
    523489
    524490/* Export functions */
     
    527493{
    528494        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         }
    535495
    536496        if (!host || port <= 0 || !func || strlen(host) > 128) {
     
    542502        phb->data = data;
    543503
    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 
    559 void 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 }
     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}
Note: See TracChangeset for help on using the changeset viewer.