9
9
#include <unistd.h>
10
10
#include "lib/asyncaddrinfo/asyncaddrinfo.h"
11
11
#include "log.h"
12
+ #include "poll.h"
13
+ #include "proxy_server.h"
12
14
#include "states/epoll_cb.h"
13
15
#include "util.h"
14
16
15
17
#define CONNECT_BACKLOG 512
16
- #define EPOLL_MAX_EVENTS 64
17
18
#define DEFAULT_THREAD_COUNT 8
18
19
#define MAX_BLACKLIST_LEN 100
19
20
@@ -39,75 +40,37 @@ int create_bind_listen(unsigned short port) {
39
40
return listening_socket ;
40
41
}
41
42
42
- struct event_loop_args {
43
+ struct connection_thread_args {
43
44
unsigned short thread_id ;
44
- bool telemetry_enabled ;
45
- int listening_socket ;
46
- char * * blacklist ;
47
- int blacklist_len ;
45
+ struct proxy_server * config ;
48
46
};
49
47
50
- void handle_connections_in_event_loop (struct event_loop_args * args ) {
51
- int epoll_fd = epoll_create1 ( 0 );
52
- if (epoll_fd < 0 ) {
53
- die (hsprintf ("failed to create epoll instance: %s" , errno2s (errno )));
48
+ void handle_connections (struct proxy_server * server ) {
49
+ struct poll * p = poll_create ( );
50
+ if (p == NULL ) {
51
+ die (hsprintf ("failed to create poll instance: %s" , errno2s (errno )));
54
52
}
55
53
56
- struct epoll_event event , events [EPOLL_MAX_EVENTS ];
57
-
58
- // Configure `event.data.ptr` to be NULL when there are events on listening socket
59
- event .data .ptr = NULL ;
60
54
// Since we will call `accept4` until there are no more incoming connections,
61
- // and edge-triggered is more efficient than level-triggered,
62
- // we can register edge -triggered notification for read events on the listening socket
63
- event . events = EPOLLIN | EPOLLET ;
64
- if ( epoll_ctl ( epoll_fd , EPOLL_CTL_ADD , args -> listening_socket , & event ) < 0 ) {
65
- die (hsprintf ("failed to add listening socket %d into epoll : %s" , args -> listening_socket , errno2s (errno )));
55
+ // we can register edge-triggered notification for read events on the listening socket.
56
+ // Edge -triggered is more efficient than level-triggered.
57
+ if ( poll_wait_for_readability (
58
+ p , server -> listening_socket , server , false, true, ( poll_callback ) accept_incoming_connections ) < 0 ) {
59
+ die (hsprintf ("failed to register readability notification for listening socket : %s" , errno2s (errno )));
66
60
}
67
61
68
- // event loop
69
- while (1 ) {
70
- int num_events = epoll_wait (epoll_fd , events , EPOLL_MAX_EVENTS , -1 );
71
- DEBUG_LOG ("epoll_wait returned %d" , num_events );
72
- if (num_events < 0 ) {
73
- die (hsprintf ("epoll_wait error: %s" , errno2s (errno )));
74
- }
75
-
76
- for (int i = 0 ; i < num_events ; i ++ ) {
77
- if (events [i ].data .ptr == NULL ) {
78
- // events on listening socket
79
- if (events [i ].events & EPOLLERR ) {
80
- DEBUG_LOG ("epoll reported error on listening socket" );
81
- }
82
- if (!(events [i ].events & EPOLLIN )) {
83
- DEBUG_LOG ("listening socket is not readable but epoll woke us up anyway" );
84
- continue ;
85
- }
86
- accept_incoming_connections (
87
- epoll_fd , args -> listening_socket , args -> telemetry_enabled , args -> blacklist , args -> blacklist_len );
88
- } else {
89
- // events on existing connection
90
- struct epoll_cb * cb = events [i ].data .ptr ;
91
- if (cb -> type == cb_type_accepted ) {
92
- handle_accepted_cb (epoll_fd , (struct epoll_accepted_cb * )cb , events [i ].events );
93
- } else if (cb -> type == cb_type_connecting ) {
94
- handle_connecting_cb (epoll_fd , (struct epoll_connecting_cb * )cb , events [i ].events );
95
- } else if (cb -> type == cb_type_tunneling ) {
96
- handle_tunneling_cb (epoll_fd , (struct epoll_tunneling_cb * )cb , events [i ].events );
97
- }
98
- }
99
- }
62
+ // start the event loop and run until termination
63
+ if (poll_run (p ) < 0 ) {
64
+ die (hsprintf ("poll_run returned error: %s" , errno2s (errno )));
100
65
}
101
66
102
- if (close (epoll_fd ) < 0 ) {
103
- die (hsprintf ("failed to close epoll instance: %s" , errno2s (errno )));
104
- }
67
+ poll_destroy (p );
105
68
}
106
69
107
- void * handle_connections_in_event_loop_pthread_wrapper (void * raw_args ) {
108
- struct event_loop_args * args = raw_args ;
70
+ void * handle_connections_pthread_wrapper (void * raw_args ) {
71
+ struct connection_thread_args * args = raw_args ;
109
72
thread_id__ = args -> thread_id ; // for logging purpose
110
- handle_connections_in_event_loop (args );
73
+ handle_connections (args -> config );
111
74
return NULL ;
112
75
}
113
76
@@ -200,33 +163,37 @@ int main(int argc, char** argv) {
200
163
printf ("- number of connection threads: %hu\n" , connection_threads );
201
164
printf ("- number of async addrinfo (DNS) threads: %hu\n" , asyncaddrinfo_threads );
202
165
203
- int listening_socket = create_bind_listen (listening_port );
204
-
205
166
// start the addr info lookup threads
206
167
asyncaddrinfo_init (asyncaddrinfo_threads );
207
168
208
169
// start the connection threads
209
- struct event_loop_args args_list [connection_threads ];
170
+ // TODO: should this struct be server or config?
171
+ int listening_socket = create_bind_listen (listening_port );
172
+ struct proxy_server server = {
173
+ .listening_socket = listening_socket ,
174
+ .telemetry_enabled = telemetry_enabled ,
175
+ .blacklist = blacklist ,
176
+ .blacklist_len = blacklist_len ,
177
+ };
178
+
179
+ struct connection_thread_args args_list [connection_threads ];
210
180
for (int i = 0 ; i < connection_threads ; i ++ ) {
211
- args_list [i ].listening_socket = listening_socket ;
212
- args_list [i ].telemetry_enabled = telemetry_enabled ;
213
181
args_list [i ].thread_id = i ;
214
- args_list [i ].blacklist = blacklist ;
215
- args_list [i ].blacklist_len = blacklist_len ;
182
+ args_list [i ].config = & server ;
216
183
}
217
184
218
185
pthread_t workers [connection_threads - 1 ];
219
186
for (int i = 0 ; i < connection_threads - 1 ; i ++ ) {
220
187
// child threads will have id from 1 onwards
221
188
// the main thread will be thread 0
222
- if (0 != pthread_create (& workers [i ], NULL , handle_connections_in_event_loop_pthread_wrapper , & args_list [i + 1 ])) {
189
+ if (0 != pthread_create (& workers [i ], NULL , handle_connections_pthread_wrapper , & args_list [i + 1 ])) {
223
190
die (hsprintf ("error creating thread %d: %s" , i + 1 , errno2s (errno )));
224
191
}
225
192
}
226
193
227
194
printf ("Accepting requests\n" );
228
195
// run another event loop on the main thread
229
- handle_connections_in_event_loop_pthread_wrapper (& args_list [0 ]);
196
+ handle_connections_pthread_wrapper (& args_list [0 ]);
230
197
231
198
// We will never reach here, the cleanup code below is just for completeness' sake
232
199
0 commit comments