static void auto_event_error(struct bufferevent *buffev, short what, void *_arg) { redsocks_client *client = _arg; int saved_errno = errno; assert(buffev == client->relay || buffev == client->client); redsocks_touch_client(client); redsocks_log_errno(client, LOG_DEBUG, "Errno: %d, State: %d, what: %x", saved_errno, client->state, what); if (buffev == client->relay) { if ( client->state == socks5_pre_detect && what == (EVBUFFER_WRITE|EVBUFFER_TIMEOUT)) { /* In case timeout occurs for connecting relay, we try to connect to target with SOCKS5 proxy. It is possible that the connection to target can be set up a bit longer than the timeout value we set. However, it is still better to make connection via proxy. */ auto_retry(client, 1); return; } if (client->state == socks5_pre_detect && saved_errno == ECONNRESET) if (!auto_retry_or_drop(client)) return; if (client->state == socks5_direct && what == (EVBUFFER_READ|EVBUFFER_ERROR) && saved_errno == ECONNRESET ) { if (!auto_retry_or_drop(client)) return; } } if (what == (EVBUFFER_READ|EVBUFFER_EOF)) { struct bufferevent *antiev; if (buffev == client->relay) antiev = client->client; else antiev = client->relay; redsocks_shutdown(client, buffev, SHUT_RD); if (antiev != NULL && EVBUFFER_LENGTH(antiev->output) == 0) redsocks_shutdown(client, antiev, SHUT_WR); } else { /* myerrno = red_socket_geterrno(buffev); redsocks_log_errno(client, LOG_NOTICE, "%s error, code " event_fmt_str, buffev == client->relay ? "relay" : "client", event_fmt(what)); */ redsocks_drop_client(client); } }
static void auto_event_error(struct bufferevent *buffev, short what, void *_arg) { redsocks_client *client = _arg; autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len; int saved_errno = errno; assert(buffev == client->relay || buffev == client->client); redsocks_touch_client(client); redsocks_log_errno(client, LOG_DEBUG, "%s errno(%d), State: %d, what: " event_fmt_str, buffev == client->client?"client":"relay", saved_errno, aclient->state, event_fmt(what)); if (buffev == client->relay) { if ( aclient->state == AUTOPROXY_NEW && what == (EVBUFFER_WRITE|EVBUFFER_TIMEOUT)) { on_connection_blocked(client); /* In case timeout occurs while connecting relay, we try to connect to target via SOCKS5 proxy. It is possible that the connection to target can be set up a bit longer than the timeout value we set. However, it is still better to make connection via proxy. */ auto_retry(client, 1); return; } if (aclient->state == AUTOPROXY_NEW && saved_errno == ECONNRESET) if (!auto_retry_or_drop(client)) return; if (aclient->state == AUTOPROXY_CONNECTED && what == (EVBUFFER_READ|EVBUFFER_ERROR) && saved_errno == ECONNRESET ) { if (!auto_retry_or_drop(client)) return; } } if (what == (EVBUFFER_READ|EVBUFFER_EOF)) { struct bufferevent *antiev; if (buffev == client->relay) antiev = client->client; else antiev = client->relay; redsocks_shutdown(client, buffev, SHUT_RD); if (antiev != NULL && EVBUFFER_LENGTH(antiev->output) == 0) redsocks_shutdown(client, antiev, SHUT_WR); } else { redsocks_drop_client(client); } }
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 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); }