2019-04-24 14:23:41 +00:00
# include "proxy.h"
int main_on_tcp_co ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
int conn_sock1 , conn_sock2 ;
struct sockaddr_in addr ;
socklen_t in_len ;
char url [ 1024 ] , port [ 6 ] ;
struct evt_core_cat local_cat = { 0 } ;
struct evt_core_fdinfo to_fdinfo = { 0 } ;
to_fdinfo . cat = & local_cat ;
to_fdinfo . url = url ;
in_len = sizeof ( addr ) ;
conn_sock1 = accept ( fdinfo - > fd , ( struct sockaddr * ) & addr , & in_len ) ;
if ( conn_sock1 = = - 1 & & errno = = EAGAIN ) return 1 ;
if ( conn_sock1 = = - 1 ) goto co_error ;
conn_sock2 = dup ( conn_sock1 ) ;
if ( conn_sock2 = = - 1 ) goto co_error ;
//printf("fd=%d accepts, creating fds=%d,%d\n", fd, conn_sock1, conn_sock2);
url_get_port ( port , fdinfo - > url ) ;
to_fdinfo . fd = conn_sock1 ;
to_fdinfo . cat - > name = " tcp-read " ;
sprintf ( to_fdinfo . url , " tcp:read:127.0.0.1:%s " , port ) ;
evt_core_add_fd ( ctx , & to_fdinfo ) ;
to_fdinfo . fd = conn_sock2 ;
to_fdinfo . cat - > name = " tcp-write " ;
sprintf ( to_fdinfo . url , " tcp:write:127.0.0.1:%s " , port ) ;
evt_core_add_fd ( ctx , & to_fdinfo ) ;
2020-01-23 16:08:04 +00:00
printf ( " [%s][proxy] Accepted a new connection on port=%s: read_fd=%d, write_fd=%d \n " , current_human_datetime ( ) , port , conn_sock1 , conn_sock2 ) ;
2019-04-24 14:23:41 +00:00
return 0 ;
co_error :
perror ( " Failed to handle new connection " ) ;
exit ( EXIT_FAILURE ) ;
}
int main_on_tcp_read ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
struct buffer_packet * bp ;
struct algo_ctx * app_ctx = fdinfo - > cat - > app_ctx ;
int read_res = FDS_READY ;
2019-05-24 09:04:37 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Get current read buffer OR a new read buffer OR subscribe to be notified later \n " ) ;
2019-05-27 15:32:00 +00:00
if ( ( bp = get_read_buffer ( & app_ctx - > br , fdinfo ) ) = = NULL ) return 1 ;
2019-04-24 14:23:41 +00:00
2019-05-24 09:04:37 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Try to read a whole packet in the buffer \n " ) ;
2019-04-24 14:23:41 +00:00
while ( bp - > mode = = BP_READING ) {
2019-08-09 15:01:28 +00:00
read_res = read_packet_from_tcp ( fdinfo , bp ) ;
2019-04-24 14:23:41 +00:00
if ( read_res = = FDS_ERR ) goto co_error ;
if ( read_res = = FDS_AGAIN ) return 1 ;
}
2019-09-06 09:20:17 +00:00
app_ctx - > cell_rcv + + ;
2019-05-24 09:04:37 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Call logic on packet \n " ) ;
2019-04-24 14:23:41 +00:00
return app_ctx - > desc - > on_stream ( ctx , fdinfo , bp ) ;
co_error :
perror ( " Failed to TCP read " ) ;
2020-01-29 09:53:37 +00:00
mv_buffer_rtof ( & app_ctx - > br , fdinfo ) ;
2019-05-24 15:15:35 +00:00
evt_core_rm_fd ( ctx , fdinfo - > fd ) ;
return 1 ;
2019-04-24 14:23:41 +00:00
}
int main_on_udp_read ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
struct buffer_packet * bp ;
struct algo_ctx * app_ctx = fdinfo - > cat - > app_ctx ;
int read_res = FDS_READY ;
char url [ 255 ] ;
// 1. Get current read buffer OR a new read buffer OR subscribe to be notified later
2019-05-27 15:32:00 +00:00
if ( ( bp = get_read_buffer ( & app_ctx - > br , fdinfo ) ) = = NULL ) return 1 ;
2019-04-24 14:23:41 +00:00
// 2. Read packet from socket
2019-08-09 15:01:28 +00:00
read_res = read_packet_from_udp ( fdinfo , bp , fdinfo - > other ) ;
2019-04-24 14:23:41 +00:00
if ( read_res = = FDS_ERR ) goto co_error ;
if ( read_res = = FDS_AGAIN ) return 1 ;
2019-05-28 09:45:20 +00:00
// 3. Notify helpers
2019-09-06 09:20:17 +00:00
app_ctx - > udp_rcv + + ;
2019-05-28 09:45:20 +00:00
traffic_capture_notify ( & app_ctx - > cap , bp , " in " ) ;
// 4. Apply logic
2019-04-24 14:23:41 +00:00
return app_ctx - > desc - > on_datagram ( ctx , fdinfo , bp ) ;
co_error :
perror ( " Failed to UDP read " ) ;
2020-01-29 09:53:37 +00:00
mv_buffer_rtof ( & app_ctx - > br , fdinfo ) ;
2019-05-24 15:15:35 +00:00
return 0 ;
2019-04-24 14:23:41 +00:00
}
int main_on_tcp_write ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
struct buffer_packet * bp ;
struct algo_ctx * app_ctx = fdinfo - > cat - > app_ctx ;
struct rr_ctx * rr = app_ctx - > misc ;
int write_res = FDS_READY ;
// 0. Show some information about circuits
uint8_t is_rdy = fdinfo - > cat - > socklist - > len > = app_ctx - > link_count ? 1 : 0 ;
if ( ! app_ctx - > is_rdy & & is_rdy ) printf ( " === Our %d requested circuits are now up === \n " , app_ctx - > link_count ) ;
else if ( app_ctx - > is_rdy & & ! is_rdy ) printf ( " === Only %d/%d circuits are available, results could be biased === \n " , fdinfo - > cat - > socklist - > len , app_ctx - > link_count ) ;
2020-02-04 10:44:20 +00:00
app_ctx - > is_rdy = app_ctx - > is_rdy | | is_rdy ; // @FIXME we don't want deactivation finally
2019-04-24 14:23:41 +00:00
// 1. Get current write buffer OR a buffer from the waiting queue OR leave
2019-05-27 15:32:00 +00:00
if ( ( bp = get_write_buffer ( & app_ctx - > br , fdinfo ) ) = = NULL ) return 1 ;
2019-04-24 14:23:41 +00:00
2019-09-04 09:06:47 +00:00
// 1.5. Prevent buffer sending if we are still bootstrapping...
if ( app_ctx - > ap . is_waiting_bootstrap & & ! app_ctx - > is_rdy ) goto free_buffer ;
2019-04-24 14:23:41 +00:00
// 2. Write data from the buffer to the socket
while ( bp - > mode = = BP_WRITING ) {
2019-08-09 15:01:28 +00:00
write_res = write_packet_to_tcp ( fdinfo , bp ) ;
2019-04-24 14:23:41 +00:00
if ( write_res = = FDS_ERR ) goto co_error ;
if ( write_res = = FDS_AGAIN ) return 1 ;
}
2020-02-04 10:44:20 +00:00
2019-09-06 09:20:17 +00:00
app_ctx - > cell_sent + + ;
2019-04-24 14:23:41 +00:00
2019-09-04 09:06:47 +00:00
free_buffer :
2019-04-24 14:23:41 +00:00
// 3. A whole packet has been written
// Release the buffer and notify
2019-05-27 15:32:00 +00:00
mv_buffer_wtof ( & app_ctx - > br , fdinfo ) ;
notify_read ( ctx , & app_ctx - > br ) ;
2019-04-24 14:23:41 +00:00
return 0 ;
co_error :
perror ( " Failed to TCP write " ) ;
2020-01-29 09:53:37 +00:00
mv_buffer_wtof ( & app_ctx - > br , fdinfo ) ;
2019-05-24 15:15:35 +00:00
evt_core_rm_fd ( ctx , fdinfo - > fd ) ;
return 1 ;
2019-04-24 14:23:41 +00:00
}
int main_on_udp_write ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
struct buffer_packet * bp ;
struct algo_ctx * app_ctx = fdinfo - > cat - > app_ctx ;
int write_res = FDS_READY ;
// 1. Get current write buffer OR a buffer from the waiting queue OR leave
2019-08-12 14:38:19 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Find write buffer \n " ) ;
2019-05-27 15:32:00 +00:00
if ( ( bp = get_write_buffer ( & app_ctx - > br , fdinfo ) ) = = NULL ) return 1 ;
2019-04-24 14:23:41 +00:00
// 2. Write buffer
2019-08-12 14:38:19 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Write UDP packet \n " ) ;
2019-08-09 15:01:28 +00:00
write_res = write_packet_to_udp ( fdinfo , bp , fdinfo - > other ) ;
2019-04-24 14:23:41 +00:00
if ( write_res = = FDS_ERR ) goto co_error ;
if ( write_res = = FDS_AGAIN ) return 1 ;
2019-05-28 09:45:20 +00:00
// 3. Notify helpers
2019-08-12 14:38:19 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Notify traffic capture \n " ) ;
2019-09-06 09:20:17 +00:00
app_ctx - > udp_sent + + ;
2019-05-28 09:45:20 +00:00
traffic_capture_notify ( & app_ctx - > cap , bp , " out " ) ;
// 4. A whole packet has been written
2019-04-24 14:23:41 +00:00
// Release the buffer and notify
2019-08-12 14:38:19 +00:00
if ( ctx - > verbose > 1 ) fprintf ( stderr , " [proxy] Release buffer and notify \n " ) ;
2019-05-27 15:32:00 +00:00
mv_buffer_wtof ( & app_ctx - > br , fdinfo ) ;
notify_read ( ctx , & app_ctx - > br ) ;
2019-04-24 14:23:41 +00:00
return 0 ;
co_error :
perror ( " Failed to UDP write " ) ;
2020-01-29 09:53:37 +00:00
mv_buffer_wtof ( & app_ctx - > br , fdinfo ) ;
2019-05-24 15:15:35 +00:00
return 0 ;
2019-04-24 14:23:41 +00:00
}
int main_on_err ( struct evt_core_ctx * ctx , struct evt_core_fdinfo * fdinfo ) {
struct algo_ctx * app_ctx = fdinfo - > cat - > app_ctx ;
struct buffer_packet * bp ;
// 1. If has a "used" buffer, remove it
2019-05-27 15:32:00 +00:00
mv_buffer_rtof ( & app_ctx - > br , fdinfo ) ;
2019-04-24 14:23:41 +00:00
// 2. If appears in the write waiting queue, remove it
2019-05-27 15:32:00 +00:00
while ( get_write_buffer ( & app_ctx - > br , fdinfo ) ! = NULL ) {
mv_buffer_wtof ( & app_ctx - > br , fdinfo ) ;
2019-04-24 14:23:41 +00:00
}
// 3. If appears in the read waiting queue, remove it
2019-05-27 15:32:00 +00:00
g_queue_remove_all ( app_ctx - > br . read_waiting , & ( fdinfo - > fd ) ) ;
2019-04-24 14:23:41 +00:00
return app_ctx - > desc - > on_err ( ctx , fdinfo ) ;
}
2019-05-27 15:32:00 +00:00
void algo_main_destroy ( void * app_ctx ) {
struct algo_ctx * ctx = ( struct algo_ctx * ) app_ctx ;
2019-09-06 09:20:17 +00:00
2019-05-27 15:32:00 +00:00
ctx - > ref_count - - ;
if ( ctx - > ref_count > 0 ) return ;
2019-09-06 09:20:17 +00:00
printf ( " udp_sent: %ld, udp_rcv: %ld, cells_sent: %ld, cells_rcv: %ld \n " , ctx - > udp_sent , ctx - > udp_rcv , ctx - > cell_sent , ctx - > cell_rcv ) ;
2019-05-27 16:14:21 +00:00
traffic_capture_stop ( & ctx - > cap ) ;
2019-05-27 15:32:00 +00:00
destroy_buffer_management ( & ctx - > br ) ;
if ( ctx - > free_misc ) ctx - > free_misc ( ctx - > misc ) ;
free ( ctx ) ;
}
2019-04-24 14:23:41 +00:00
void algo_main_init ( struct evt_core_ctx * evt , struct algo_params * ap ) {
struct algo_ctx * ctx = malloc ( sizeof ( struct algo_ctx ) ) ;
if ( ctx = = NULL ) goto init_err ;
memset ( ctx , 0 , sizeof ( struct algo_ctx ) ) ;
2019-09-17 14:44:49 +00:00
ctx - > link_count = ap - > links ;
2019-04-24 14:23:41 +00:00
ctx - > is_rdy = 0 ;
ctx - > ap = * ap ;
struct evt_core_cat tcp_listen = {
. name = " tcp-listen " ,
. flags = EPOLLIN ,
. app_ctx = ctx ,
2019-05-27 15:32:00 +00:00
. free_app_ctx = algo_main_destroy ,
2019-04-24 14:23:41 +00:00
. cb = main_on_tcp_co ,
. err_cb = NULL
} ;
2019-05-09 09:24:05 +00:00
ctx - > ref_count + + ;
2019-04-24 14:23:41 +00:00
evt_core_add_cat ( evt , & tcp_listen ) ;
struct evt_core_cat tcp_read = {
. name = " tcp-read " ,
2020-02-04 10:44:20 +00:00
. flags = EPOLLIN | EPOLLET | EPOLLHUP | EPOLLRDHUP ,
2019-04-24 14:23:41 +00:00
. app_ctx = ctx ,
2019-05-27 15:32:00 +00:00
. free_app_ctx = algo_main_destroy ,
2019-04-24 14:23:41 +00:00
. cb = main_on_tcp_read ,
. err_cb = main_on_err
} ;
ctx - > ref_count + + ;
evt_core_add_cat ( evt , & tcp_read ) ;
struct evt_core_cat udp_read = {
. name = " udp-read " ,
2020-01-23 16:38:08 +00:00
. flags = EPOLLIN | EPOLLET ,
2019-04-24 14:23:41 +00:00
. app_ctx = ctx ,
2019-05-27 15:32:00 +00:00
. free_app_ctx = algo_main_destroy ,
2019-04-24 14:23:41 +00:00
. cb = main_on_udp_read ,
. err_cb = main_on_err
} ;
ctx - > ref_count + + ;
evt_core_add_cat ( evt , & udp_read ) ;
struct evt_core_cat tcp_write = {
. name = " tcp-write " ,
2020-02-04 10:44:20 +00:00
. flags = EPOLLOUT | EPOLLET | EPOLLHUP | EPOLLRDHUP ,
2019-04-24 14:23:41 +00:00
. app_ctx = ctx ,
2019-05-27 15:32:00 +00:00
. free_app_ctx = algo_main_destroy ,
2019-04-24 14:23:41 +00:00
. cb = main_on_tcp_write ,
. err_cb = main_on_err
} ;
ctx - > ref_count + + ;
evt_core_add_cat ( evt , & tcp_write ) ;
struct evt_core_cat udp_write = {
. name = " udp-write " ,
. flags = EPOLLOUT | EPOLLET ,
. app_ctx = ctx ,
2019-05-27 15:32:00 +00:00
. free_app_ctx = algo_main_destroy ,
2019-04-24 14:23:41 +00:00
. cb = main_on_udp_write ,
. err_cb = main_on_err
} ;
ctx - > ref_count + + ;
evt_core_add_cat ( evt , & udp_write ) ;
2019-05-27 15:32:00 +00:00
init_buffer_management ( & ctx - > br ) ;
2019-05-27 16:14:21 +00:00
traffic_capture_init ( & ctx - > cap , ap - > capture_file ) ;
2019-05-27 15:32:00 +00:00
2019-04-24 14:23:41 +00:00
for ( int i = 0 ; i < sizeof ( available_algo ) / sizeof ( available_algo [ 0 ] ) ; i + + ) {
if ( strcmp ( available_algo [ i ] . name , ap - > algo_name ) = = 0 ) {
ctx - > desc = & ( available_algo [ i ] ) ;
ctx - > desc - > init ( evt , ctx , ap ) ;
return ;
}
}
fprintf ( stderr , " Algorithm %s has not been found \n " , ap - > algo_name ) ;
exit ( EXIT_FAILURE ) ;
init_err :
fprintf ( stderr , " Failed to init proxy \n " ) ;
exit ( EXIT_FAILURE ) ;
}