diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-05-20 13:00:26 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-05-20 13:00:26 +0000 |
commit | 9bf22db9cf42ff29f51e9ea1474b8a1915c4f339 (patch) | |
tree | 224570e6466a40fac3a1bb7a54c56af89a9a9676 | |
parent | 52cab305fc73c75fedcbf877f0ef6bb03151970b (diff) | |
download | gnunet-9bf22db9cf42ff29f51e9ea1474b8a1915c4f339.tar.gz gnunet-9bf22db9cf42ff29f51e9ea1474b8a1915c4f339.zip |
- make mhd and curl play nice thread wise
-rw-r--r-- | src/gns/gnocksy/gnocksy.c | 186 | ||||
-rw-r--r-- | src/gns/gnocksy/protocol.h | 21 |
2 files changed, 173 insertions, 34 deletions
diff --git a/src/gns/gnocksy/gnocksy.c b/src/gns/gnocksy/gnocksy.c index 2f2699955..3f2254778 100644 --- a/src/gns/gnocksy/gnocksy.c +++ b/src/gns/gnocksy/gnocksy.c | |||
@@ -30,7 +30,8 @@ | |||
30 | 30 | ||
31 | #define DEBUG 1 | 31 | #define DEBUG 1 |
32 | 32 | ||
33 | CURL *curl = NULL; | 33 | #define HTML_HDR_CONTENT "Content-Type: text/html\r\n" |
34 | |||
34 | struct MHD_Daemon *mhd_daemon; | 35 | struct MHD_Daemon *mhd_daemon; |
35 | 36 | ||
36 | static size_t | 37 | static size_t |
@@ -38,21 +39,56 @@ curl_write_data (void *buffer, size_t size, size_t nmemb, void* cls) | |||
38 | { | 39 | { |
39 | const char* page = buffer; | 40 | const char* page = buffer; |
40 | size_t bytes = size * nmemb; | 41 | size_t bytes = size * nmemb; |
41 | struct MHD_Response *response; | 42 | struct socks5_bridge* br = cls; |
42 | struct MHD_Connection *con = cls; | ||
43 | int ret; | 43 | int ret; |
44 | 44 | ||
45 | response = MHD_create_response_from_data (strlen(page), | 45 | pthread_mutex_lock ( &br->m_buf ); |
46 | (void*) page, | 46 | if (br->MHD_CURL_BUF_STATUS == BUF_WAIT_FOR_MHD) |
47 | MHD_NO, | 47 | { |
48 | MHD_NO); | 48 | pthread_mutex_unlock ( &br->m_buf ); |
49 | printf( "waiting for mhd to process data... pausing curl\n"); | ||
50 | return CURL_WRITEFUNC_PAUSE; | ||
51 | } | ||
52 | |||
53 | /* do regex magic */ | ||
54 | if ( br->res_is_html ) | ||
55 | { | ||
56 | printf ("result is html text\n"); | ||
57 | //void | ||
58 | } | ||
59 | |||
60 | memcpy (br->MHD_CURL_BUF, buffer, bytes); | ||
61 | br->MHD_CURL_BUF_SIZE = bytes; | ||
62 | |||
63 | br->MHD_CURL_BUF_STATUS = BUF_WAIT_FOR_MHD; | ||
64 | |||
65 | pthread_mutex_unlock ( &br->m_buf ); | ||
66 | |||
67 | |||
68 | //MHD_destroy_response (response); | ||
69 | printf( "buffer: %s\n", (char*)buffer ); | ||
70 | return bytes; | ||
71 | } | ||
72 | |||
73 | static size_t | ||
74 | curl_check_hdr (void *buffer, size_t size, size_t nmemb, void* cls) | ||
75 | { | ||
76 | size_t bytes = size * nmemb; | ||
77 | struct socks5_bridge* br = cls; | ||
78 | char hdr[bytes+1]; | ||
79 | |||
80 | memcpy(hdr, buffer, bytes); | ||
81 | hdr[bytes] = '\0'; | ||
82 | |||
83 | printf ("got hdr: %s\n", hdr); | ||
84 | |||
85 | if (0 == strcmp(hdr, HTML_HDR_CONTENT)) | ||
86 | br->res_is_html = 1; | ||
49 | 87 | ||
50 | ret = MHD_queue_response (con, MHD_HTTP_OK, response); | ||
51 | MHD_destroy_response (response); | ||
52 | printf( "buffer %s\n", (char*)buffer ); | ||
53 | return bytes; | 88 | return bytes; |
54 | } | 89 | } |
55 | 90 | ||
91 | |||
56 | /* | 92 | /* |
57 | * Create an ipv4/6 tcp socket for a given port | 93 | * Create an ipv4/6 tcp socket for a given port |
58 | * | 94 | * |
@@ -203,6 +239,87 @@ access_cb (void* cls, | |||
203 | return MHD_YES; | 239 | return MHD_YES; |
204 | } | 240 | } |
205 | 241 | ||
242 | static void | ||
243 | fetch_url (struct socks5_bridge* br) | ||
244 | { | ||
245 | |||
246 | CURLcode ret; | ||
247 | |||
248 | br->curl = curl_easy_init(); | ||
249 | |||
250 | /* TODO optionally do LEHO stuff here */ | ||
251 | |||
252 | if (br->curl) | ||
253 | { | ||
254 | curl_easy_setopt (br->curl, CURLOPT_URL, br->full_url); | ||
255 | curl_easy_setopt (br->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); | ||
256 | curl_easy_setopt (br->curl, CURLOPT_HEADERDATA, br); | ||
257 | curl_easy_setopt (br->curl, CURLOPT_WRITEFUNCTION, &curl_write_data); | ||
258 | curl_easy_setopt (br->curl, CURLOPT_WRITEDATA, br); | ||
259 | ret = curl_easy_perform (br->curl); | ||
260 | free (br->full_url); | ||
261 | pthread_mutex_lock ( &br->m_done ); | ||
262 | br->is_done = 1; | ||
263 | pthread_mutex_unlock ( &br->m_done ); | ||
264 | |||
265 | curl_easy_cleanup (br->curl); | ||
266 | |||
267 | if (ret == CURLE_OK) | ||
268 | { | ||
269 | printf("all good on the curl end\n"); | ||
270 | return; | ||
271 | } | ||
272 | printf("error on the curl end %s\n", curl_easy_strerror(ret)); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static ssize_t | ||
277 | mhd_content_cb (void* cls, | ||
278 | uint64_t pos, | ||
279 | char* buf, | ||
280 | size_t max) | ||
281 | { | ||
282 | struct socks5_bridge* br = cls; | ||
283 | |||
284 | pthread_mutex_lock ( &br->m_done ); | ||
285 | /* if done and buf empty */ | ||
286 | if ( (br->is_done == 1) && | ||
287 | (br->MHD_CURL_BUF_STATUS == BUF_WAIT_FOR_CURL) ) | ||
288 | { | ||
289 | printf("done. sending response...\n"); | ||
290 | br->is_done = 0; | ||
291 | pthread_mutex_unlock ( &br->m_done ); | ||
292 | return MHD_CONTENT_READER_END_OF_STREAM; | ||
293 | } | ||
294 | pthread_mutex_unlock ( &br->m_done ); | ||
295 | |||
296 | pthread_mutex_lock ( &br->m_buf ); | ||
297 | if ( br->MHD_CURL_BUF_STATUS == BUF_WAIT_FOR_CURL ) | ||
298 | { | ||
299 | printf("waiting for curl...\n"); | ||
300 | pthread_mutex_unlock ( &br->m_buf ); | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | if ( br->MHD_CURL_BUF_SIZE > max ) | ||
305 | { | ||
306 | printf("buffer in mhd response too small!\n"); | ||
307 | pthread_mutex_unlock ( &br->m_buf ); | ||
308 | return MHD_CONTENT_READER_END_WITH_ERROR; | ||
309 | } | ||
310 | |||
311 | if (0 != br->MHD_CURL_BUF_SIZE) | ||
312 | { | ||
313 | printf("copying %d bytes to mhd response at offset %d\n", | ||
314 | br->MHD_CURL_BUF_SIZE, pos); | ||
315 | memcpy ( buf, br->MHD_CURL_BUF, br->MHD_CURL_BUF_SIZE ); | ||
316 | } | ||
317 | br->MHD_CURL_BUF_STATUS = BUF_WAIT_FOR_CURL; | ||
318 | pthread_mutex_unlock ( &br->m_buf ); | ||
319 | |||
320 | return br->MHD_CURL_BUF_SIZE; | ||
321 | } | ||
322 | |||
206 | static int | 323 | static int |
207 | accept_cb (void *cls, | 324 | accept_cb (void *cls, |
208 | struct MHD_Connection *con, | 325 | struct MHD_Connection *con, |
@@ -218,7 +335,7 @@ accept_cb (void *cls, | |||
218 | "</head><body>gnoxy demo</body></html>"; | 335 | "</head><body>gnoxy demo</body></html>"; |
219 | struct MHD_Response *response; | 336 | struct MHD_Response *response; |
220 | struct socks5_bridge *br = cls; | 337 | struct socks5_bridge *br = cls; |
221 | CURLcode ret; | 338 | int ret; |
222 | char* full_url; | 339 | char* full_url; |
223 | 340 | ||
224 | if (0 != strcmp (meth, "GET")) | 341 | if (0 != strcmp (meth, "GET")) |
@@ -233,28 +350,31 @@ accept_cb (void *cls, | |||
233 | return MHD_NO; | 350 | return MHD_NO; |
234 | 351 | ||
235 | *con_cls = NULL; | 352 | *con_cls = NULL; |
236 | 353 | ||
237 | if (curl) | 354 | if (-1 == asprintf (&br->full_url, "%s%s", br->host, url)) |
238 | { | 355 | { |
239 | if (-1 == asprintf (&full_url, "%s%s", br->host, url)) | 356 | printf ("error building url!\n"); |
240 | { | 357 | return MHD_NO; |
241 | printf ("error building url!\n"); | ||
242 | return MHD_NO; | ||
243 | } | ||
244 | printf ("url %s\n", full_url); | ||
245 | curl_easy_setopt (curl, CURLOPT_URL, full_url); | ||
246 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, &curl_write_data); | ||
247 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, con); | ||
248 | ret = curl_easy_perform (curl); | ||
249 | free (full_url); | ||
250 | if (ret == CURLE_OK) | ||
251 | { | ||
252 | printf("all good on the curl end\n"); | ||
253 | return MHD_YES; | ||
254 | } | ||
255 | printf("error on the curl end %s\n", curl_easy_strerror(ret)); | ||
256 | } | 358 | } |
257 | return MHD_NO; | 359 | printf ("url %s\n", br->full_url); |
360 | |||
361 | pthread_mutex_lock ( &br->m_done ); | ||
362 | br->is_done = 0; | ||
363 | pthread_mutex_unlock ( &br->m_done ); | ||
364 | |||
365 | br->MHD_CURL_BUF_STATUS = BUF_WAIT_FOR_CURL; | ||
366 | br->res_is_html = 0; | ||
367 | |||
368 | response = MHD_create_response_from_callback (-1, -1, | ||
369 | &mhd_content_cb, | ||
370 | br, | ||
371 | NULL); //TODO destroy resp here | ||
372 | |||
373 | ret = MHD_queue_response (con, MHD_HTTP_OK, response); | ||
374 | pthread_create ( &br->thread, NULL, &fetch_url, br ); | ||
375 | |||
376 | return MHD_YES; | ||
377 | |||
258 | 378 | ||
259 | } | 379 | } |
260 | 380 | ||
@@ -281,14 +401,13 @@ int main ( int argc, char *argv[] ) | |||
281 | struct socks5_client_request *req; | 401 | struct socks5_client_request *req; |
282 | struct socks5_bridge* new_br; | 402 | struct socks5_bridge* new_br; |
283 | char domain[256]; | 403 | char domain[256]; |
284 | uint8_t msg[16]; | ||
285 | uint8_t dom_len; | 404 | uint8_t dom_len; |
286 | uint16_t req_port; | 405 | uint16_t req_port; |
287 | int conn_fd; | 406 | int conn_fd; |
288 | struct hostent *phost; | 407 | struct hostent *phost; |
289 | 408 | ||
290 | mhd_daemon = NULL; | 409 | mhd_daemon = NULL; |
291 | curl = curl_easy_init(); | 410 | curl_global_init(CURL_GLOBAL_ALL); |
292 | 411 | ||
293 | for (j = 0; j < MAXEVENTS; j++) | 412 | for (j = 0; j < MAXEVENTS; j++) |
294 | ev_states[j] = SOCKS5_INIT; | 413 | ev_states[j] = SOCKS5_INIT; |
@@ -565,7 +684,6 @@ int main ( int argc, char *argv[] ) | |||
565 | 684 | ||
566 | free (events); | 685 | free (events); |
567 | MHD_stop_daemon (mhd_daemon); | 686 | MHD_stop_daemon (mhd_daemon); |
568 | curl_easy_cleanup (curl); | ||
569 | close (sfd); | 687 | close (sfd); |
570 | 688 | ||
571 | return EXIT_SUCCESS; | 689 | return EXIT_SUCCESS; |
diff --git a/src/gns/gnocksy/protocol.h b/src/gns/gnocksy/protocol.h index 8b3b218d6..4f7e23675 100644 --- a/src/gns/gnocksy/protocol.h +++ b/src/gns/gnocksy/protocol.h | |||
@@ -36,6 +36,9 @@ struct socks5_server_hello | |||
36 | uint8_t auth_method; | 36 | uint8_t auth_method; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | #define BUF_WAIT_FOR_CURL 0 | ||
40 | #define BUF_WAIT_FOR_MHD 1 | ||
41 | |||
39 | /* Struct used to store connection | 42 | /* Struct used to store connection |
40 | * information | 43 | * information |
41 | */ | 44 | */ |
@@ -47,6 +50,24 @@ struct socks5_bridge | |||
47 | socklen_t addr_len; | 50 | socklen_t addr_len; |
48 | char host[256]; | 51 | char host[256]; |
49 | int status; | 52 | int status; |
53 | |||
54 | /* http url + host */ | ||
55 | char* full_url; | ||
56 | |||
57 | /* handle to curl */ | ||
58 | CURL* curl; | ||
59 | |||
60 | /* is response html? */ | ||
61 | int res_is_html; | ||
62 | |||
63 | /* buffer structures */ | ||
64 | pthread_t thread; | ||
65 | pthread_mutex_t m_done; | ||
66 | int is_done; | ||
67 | pthread_mutex_t m_buf; | ||
68 | char MHD_CURL_BUF[CURL_MAX_WRITE_SIZE]; | ||
69 | size_t MHD_CURL_BUF_SIZE; | ||
70 | int MHD_CURL_BUF_STATUS; | ||
50 | }; | 71 | }; |
51 | 72 | ||
52 | /* Server response to client requests */ | 73 | /* Server response to client requests */ |