static void auto_relay_connected(struct bufferevent *buffev, void *_arg) { redsocks_client *client = _arg; assert(buffev == client->relay); redsocks_touch_client(client); if (!red_is_socket_connected_ok(buffev)) { if (client->state == socks5_pre_detect && !auto_retry_or_drop(client)) return; redsocks_log_error(client, LOG_DEBUG, "failed to connect to proxy"); goto fail; } /* We do not need to detect timeouts any more. The two peers will handle it. */ bufferevent_set_timeouts(client->relay, NULL, NULL); client->relay->readcb = client->instance->relay_ss->readcb; client->relay->writecb = client->instance->relay_ss->writecb; client->relay->writecb(buffev, _arg); return; fail: redsocks_drop_client(client); }
static void ss_relay_connected(struct bufferevent *buffev, void *_arg) { redsocks_client *client = _arg; ss_header_ipv4 header; size_t len = 0; assert(buffev == client->relay); assert(client->state == ss_new); redsocks_touch_client(client); if (!red_is_socket_connected_ok(buffev)) { redsocks_log_error(client, LOG_DEBUG, "failed to connect to destination"); redsocks_drop_client(client); return; } client->relay_connected = 1; /* We do not need to detect timeouts any more. The two peers will handle it. */ bufferevent_set_timeouts(client->relay, NULL, NULL); if (!redsocks_start_relay(client)) { /* overwrite theread callback to my function */ bufferevent_setcb(client->client, ss_client_readcb, ss_client_writecb, redsocks_event_error, client); bufferevent_setcb(client->relay, ss_relay_readcb, ss_relay_writecb, redsocks_event_error, client); } else { redsocks_log_error(client, LOG_DEBUG, "failed to start relay"); redsocks_drop_client(client); return; } /* build and send header */ // TODO: Better implementation and IPv6 Support header.addr_type = ss_addrtype_ipv4; header.addr = client->destaddr.sin_addr.s_addr; header.port = client->destaddr.sin_port; len += sizeof(header); encrypt_mem(client, (char *)&header, len, client->relay, 0); client->state = ss_connected; // Write any data received from client side to relay. if (evbuffer_get_length(bufferevent_get_input(client->client))) ss_relay_writecb(client->relay, client); return; }
static void auto_relay_connected(struct bufferevent *buffev, void *_arg) { redsocks_client *client = _arg; autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len; assert(buffev == client->relay); redsocks_touch_client(client); if (!red_is_socket_connected_ok(buffev)) { if (aclient->state == AUTOPROXY_NEW && !auto_retry_or_drop(client)) return; redsocks_log_error(client, LOG_DEBUG, "failed to connect to proxy"); goto fail; } /* update client state */ aclient->state = AUTOPROXY_CONNECTED; /* We do not need to detect timeouts any more. The two peers will handle it. */ bufferevent_set_timeouts(client->relay, NULL, NULL); if (!redsocks_start_relay(client)) { /* overwrite theread callback to my function */ client->client->readcb = direct_relay_clientreadcb; client->client->writecb = direct_relay_clientwritecb; client->relay->readcb = direct_relay_relayreadcb; client->relay->writecb = direct_relay_relaywritecb; } else { redsocks_log_error(client, LOG_DEBUG, "failed to start relay"); goto fail; } client->relay->writecb(buffev, _arg); return; fail: redsocks_drop_client(client); }