static void auto_connect_relay(redsocks_client *client) { autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len; struct timeval tv; tv.tv_sec = client->instance->config.timeout; tv.tv_usec = 0; time_t * acc_time = NULL; time_t now = redsocks_time(NULL); /* use default timeout if timeout is not configured */ if (tv.tv_sec == 0) tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS; if (aclient->state == AUTOPROXY_NEW) { acc_time = get_addr_time_in_cache(&client->destaddr); if (acc_time) { if (now - *acc_time < CACHE_ITEM_STALE_SECONDS ) { redsocks_log_error(client, LOG_DEBUG, "Found dest IP in cache"); auto_retry(client, 0); return ; } else { /* stale this address in cache */ del_addr_from_cache(&client->destaddr); /* update timeout value for quick detection */ tv.tv_sec = QUICK_CONNECT_TIMEOUT_SECONDS; } } /* connect to target directly without going through proxy */ client->relay = red_connect_relay2(&client->destaddr, auto_relay_connected, auto_event_error, client, &tv); aclient->time_connect_relay = redsocks_time(NULL); if (!client->relay) { redsocks_log_errno(client, LOG_ERR, "auto_connect_relay"); redsocks_drop_client(client); } } else { redsocks_log_errno(client, LOG_ERR, "invalid state: %d", aclient->state); } }
/* return 1 for drop, 0 for retry. */ static int auto_retry_or_drop(redsocks_client * client) { time_t now = redsocks_time(NULL); autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len; if (aclient->state == AUTOPROXY_NEW) { if (now - aclient->time_connect_relay <= CIRCUIT_RESET_SECONDS) { on_connection_blocked(client); auto_retry(client, 0); return 0; } } else if ( aclient->state == AUTOPROXY_CONNECTED) { // if (now - aclient->time_connect_relay <= CIRCUIT_RESET_SECONDS) { on_connection_blocked(client); auto_retry(client, 0); return 0; } } /* drop */ return 1; }
static void auto_connect_relay(redsocks_client *client) { socks5_client *socks5 = (void*)(client + 1); struct timeval tv; tv.tv_sec = CONNECT_TIMEOUT_SECONDS; tv.tv_usec = 0; if (client->state == socks5_pre_detect) { if (is_addr_in_cache(&client->destaddr)) { client->state = socks5_new; /* Connect SOCKS5 */ redsocks_log_error(client, LOG_DEBUG, "Found in cache"); } } client->relay = red_connect_relay2( client->state == socks5_pre_detect ? &client->destaddr : &client->instance->config.relayaddr, auto_relay_connected, auto_event_error, client, client->state == socks5_pre_detect ? &tv: NULL); socks5->time_connect_relay = redsocks_time(NULL); if (!client->relay) { redsocks_log_errno(client, LOG_ERR, "auto_connect_relay"); redsocks_drop_client(client); } }
/* return 1 for drop, 0 for retry. */ static int auto_retry_or_drop(redsocks_client * client) { time_t now = redsocks_time(NULL); socks5_client *socks5 = (void*)(client + 1); if (client->state == socks5_pre_detect) { if (now - socks5->time_connect_relay <= CIRCUIT_RESET_SECONDS) { auto_retry(client, 1); return 0; } } if ( client->state == socks5_direct) { // if (now - socks5->time_connect_relay <= CIRCUIT_RESET_SECONDS) { auto_retry(client, 0); return 0; } } /* drop */ return 1; }
static void add_addr_to_cache(const struct sockaddr_in * addr) { int block = block_from_sockaddr_in(addr); int count = addr_cache_counters[block]; /* use 'first' to index item in cache block when count is equal or greater than block size */ int first = addr_cache_pointers[block]; if (count < ADDR_CACHE_BLOCK_SIZE) { memcpy((void *)&addr_cache[block][count].addr, (void *) addr, sizeof(struct sockaddr_in)); addr_cache[block][count].access_time = redsocks_time(NULL); addr_cache_counters[block]++; } else { memcpy((void *)&addr_cache[block][first].addr, (void *) addr, sizeof(struct sockaddr_in)); addr_cache[block][first].access_time = redsocks_time(NULL); addr_cache_pointers[block]++; addr_cache_pointers[block]%=ADDR_CACHE_BLOCK_SIZE; } }