diff options
Diffstat (limited to 'src/transport')
-rw-r--r-- | src/transport/plugin_transport_http_server.c | 1728 | ||||
-rw-r--r-- | src/transport/test_transport_api_http_reverse_peer1.conf | 2 | ||||
-rw-r--r-- | src/transport/test_transport_api_http_reverse_peer2.conf | 2 | ||||
-rw-r--r-- | src/transport/transport-testing.c | 4 | ||||
-rw-r--r-- | src/transport/transport.conf.in | 12 |
5 files changed, 888 insertions, 860 deletions
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c index aba4b5ed0..0db5e31c5 100644 --- a/src/transport/plugin_transport_http_server.c +++ b/src/transport/plugin_transport_http_server.c | |||
@@ -54,242 +54,247 @@ | |||
54 | 54 | ||
55 | 55 | ||
56 | /** | 56 | /** |
57 | * Session handle for connections. | 57 | * Information we keep with MHD for an HTTP request. |
58 | */ | 58 | */ |
59 | struct Session | 59 | struct ServerConnection |
60 | { | 60 | { |
61 | /** | 61 | /** |
62 | * Stored in a linked list. | 62 | * The session this server connection belongs to |
63 | */ | 63 | */ |
64 | struct Session *next; | 64 | struct Session *session; |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * Stored in a linked list. | 67 | * The MHD connection |
68 | */ | 68 | */ |
69 | struct Session *prev; | 69 | struct MHD_Connection *mhd_conn; |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * To whom are we talking to (set to our identity | 72 | * The MHD daemon |
73 | * if we are still waiting for the welcome message) | ||
74 | */ | 73 | */ |
75 | struct GNUNET_PeerIdentity target; | 74 | struct MHD_Daemon *mhd_daemon; |
76 | 75 | ||
77 | /** | 76 | /** |
78 | * Pointer to the global plugin struct. | 77 | * Options requested by peer |
79 | */ | 78 | */ |
80 | struct HTTP_Server_Plugin *plugin; | 79 | uint32_t options; |
80 | #define OPTION_LONG_POLL 1 /* GET request wants long-poll semantics */ | ||
81 | 81 | ||
82 | /** | 82 | /** |
83 | * next pointer for double linked list | 83 | * _RECV or _SEND |
84 | */ | 84 | */ |
85 | struct HTTP_Message *msg_head; | 85 | int direction; |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * previous pointer for double linked list | 88 | * For PUT connections: Is this the first or last callback with size 0 |
89 | * For GET connections: Have we sent a message | ||
89 | */ | 90 | */ |
90 | struct HTTP_Message *msg_tail; | 91 | int connected; |
92 | |||
93 | }; | ||
91 | 94 | ||
95 | |||
96 | /** | ||
97 | * Wrapper to manage addresses | ||
98 | */ | ||
99 | struct HttpAddressWrapper | ||
100 | { | ||
92 | /** | 101 | /** |
93 | * Message stream tokenizer for incoming data | 102 | * Linked list next |
94 | */ | 103 | */ |
95 | struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk; | 104 | struct HttpAddressWrapper *next; |
96 | 105 | ||
97 | /** | 106 | /** |
98 | * Client recv handle | 107 | * Linked list previous |
99 | */ | 108 | */ |
100 | struct ServerConnection *server_recv; | 109 | struct HttpAddressWrapper *prev; |
101 | 110 | ||
102 | /** | 111 | /** |
103 | * Client send handle | 112 | * An address we are using. |
104 | */ | 113 | */ |
105 | struct ServerConnection *server_send; | 114 | struct HttpAddress *address; |
106 | 115 | ||
107 | /** | 116 | /** |
108 | * Address | 117 | * Length of the address. |
109 | */ | 118 | */ |
110 | struct GNUNET_HELLO_Address *address; | 119 | size_t addrlen; |
120 | }; | ||
121 | |||
111 | 122 | ||
123 | /** | ||
124 | * Message to send using http | ||
125 | */ | ||
126 | struct HTTP_Message | ||
127 | { | ||
112 | /** | 128 | /** |
113 | * Unique HTTP/S connection tag for this connection | 129 | * next pointer for double linked list |
114 | */ | 130 | */ |
115 | uint32_t tag; | 131 | struct HTTP_Message *next; |
116 | 132 | ||
117 | /** | 133 | /** |
118 | * ATS network type in NBO | 134 | * previous pointer for double linked list |
119 | */ | 135 | */ |
120 | uint32_t ats_address_network_type; | 136 | struct HTTP_Message *prev; |
121 | 137 | ||
122 | /** | 138 | /** |
123 | * Was session given to transport service? | 139 | * buffer containing data to send |
124 | */ | 140 | */ |
125 | int session_passed; | 141 | char *buf; |
126 | 142 | ||
127 | /** | 143 | /** |
128 | * Did we immediately end the session in disconnect_cb | 144 | * amount of data already sent |
129 | */ | 145 | */ |
130 | int session_ended; | 146 | size_t pos; |
131 | 147 | ||
132 | /** | 148 | /** |
133 | * Absolute time when to receive data again | 149 | * buffer length |
134 | * Used for receive throttling | ||
135 | */ | 150 | */ |
136 | struct GNUNET_TIME_Absolute next_receive; | 151 | size_t size; |
137 | 152 | ||
138 | /** | 153 | /** |
139 | * Session timeout task | 154 | * HTTP/S specific overhead |
140 | */ | 155 | */ |
141 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | 156 | size_t overhead; |
142 | 157 | ||
143 | /** | 158 | /** |
144 | * Should this session get disconnected? GNUNET_YES/NO | 159 | * Continuation function to call once the transmission buffer |
160 | * has again space available. NULL if there is no | ||
161 | * continuation to call. | ||
162 | */ | ||
163 | GNUNET_TRANSPORT_TransmitContinuation transmit_cont; | ||
164 | |||
165 | /** | ||
166 | * Closure for transmit_cont. | ||
145 | */ | 167 | */ |
146 | int disconnect; | 168 | void *transmit_cont_cls; |
147 | }; | 169 | }; |
148 | 170 | ||
149 | 171 | ||
150 | struct ServerConnection | 172 | /** |
173 | * Session handle for connections. | ||
174 | */ | ||
175 | struct Session | ||
151 | { | 176 | { |
152 | /** | ||
153 | * _RECV or _SEND | ||
154 | */ | ||
155 | int direction; | ||
156 | 177 | ||
157 | /** | 178 | /** |
158 | * For PUT connections: Is this the first or last callback with size 0 | 179 | * To whom are we talking to (set to our identity |
159 | * For GET connections: Have we sent a message | 180 | * if we are still waiting for the welcome message) |
160 | */ | 181 | */ |
161 | int connected; | 182 | struct GNUNET_PeerIdentity target; |
162 | 183 | ||
163 | /** | 184 | /** |
164 | * The session this server connection belongs to | 185 | * Pointer to the global plugin struct. |
165 | */ | 186 | */ |
166 | struct Session *session; | 187 | struct HTTP_Server_Plugin *plugin; |
167 | 188 | ||
168 | /** | 189 | /** |
169 | * The MHD connection | 190 | * next pointer for double linked list |
170 | */ | 191 | */ |
171 | struct MHD_Connection *mhd_conn; | 192 | struct HTTP_Message *msg_head; |
172 | 193 | ||
173 | /** | 194 | /** |
174 | * The MHD daemon | 195 | * previous pointer for double linked list |
175 | */ | 196 | */ |
176 | struct MHD_Daemon *mhd_daemon; | 197 | struct HTTP_Message *msg_tail; |
177 | 198 | ||
178 | /** | 199 | /** |
179 | * Options requested by peer | 200 | * Message stream tokenizer for incoming data |
180 | */ | 201 | */ |
181 | uint32_t options; | 202 | struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk; |
182 | #define OPTION_LONG_POLL 1 /* GET request wants long-poll semantics */ | ||
183 | }; | ||
184 | |||
185 | 203 | ||
186 | /** | ||
187 | * Encapsulation of all of the state of the plugin. | ||
188 | */ | ||
189 | struct HTTP_Server_Plugin | ||
190 | { | ||
191 | /** | 204 | /** |
192 | * Our environment. | 205 | * Client recv handle |
193 | */ | 206 | */ |
194 | struct GNUNET_TRANSPORT_PluginEnvironment *env; | 207 | struct ServerConnection *server_recv; |
195 | 208 | ||
196 | /** | 209 | /** |
197 | * Linked list head of open sessions. | 210 | * Client send handle |
198 | */ | 211 | */ |
199 | struct Session *head; | 212 | struct ServerConnection *server_send; |
200 | 213 | ||
201 | /** | 214 | /** |
202 | * Linked list tail of open sessions. | 215 | * Address |
203 | */ | 216 | */ |
204 | struct Session *tail; | 217 | struct GNUNET_HELLO_Address *address; |
205 | 218 | ||
206 | /** | 219 | /** |
207 | * Plugin name | 220 | * Absolute time when to receive data again |
221 | * Used for receive throttling | ||
208 | */ | 222 | */ |
209 | char *name; | 223 | struct GNUNET_TIME_Absolute next_receive; |
210 | 224 | ||
211 | /** | 225 | /** |
212 | * Protocol | 226 | * Session timeout task |
213 | */ | 227 | */ |
214 | char *protocol; | 228 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; |
215 | 229 | ||
216 | /** | 230 | /** |
217 | * My options to be included in the address | 231 | * Unique HTTP/S connection tag for this connection |
218 | */ | 232 | */ |
219 | uint32_t options; | 233 | uint32_t tag; |
220 | 234 | ||
221 | /** | 235 | /** |
222 | * External address | 236 | * ATS network type in NBO |
223 | */ | 237 | */ |
224 | char *external_hostname; | 238 | uint32_t ats_address_network_type; |
225 | 239 | ||
226 | /** | 240 | /** |
227 | * Verify external address | 241 | * #GNUNET_YES if this session is known to the service. |
228 | */ | 242 | */ |
229 | int verify_external_hostname; | 243 | int known_to_service; |
230 | 244 | ||
231 | /** | 245 | }; |
232 | * Maximum number of sockets the plugin can use | ||
233 | * Each http inbound /outbound connections are two connections | ||
234 | */ | ||
235 | unsigned int max_connections; | ||
236 | 246 | ||
237 | /** | ||
238 | * Current number of sockets the plugin can use | ||
239 | * Each http inbound /outbound connections are two connections | ||
240 | */ | ||
241 | unsigned int cur_connections; | ||
242 | 247 | ||
248 | /** | ||
249 | * Encapsulation of all of the state of the plugin. | ||
250 | */ | ||
251 | struct HTTP_Server_Plugin | ||
252 | { | ||
243 | /** | 253 | /** |
244 | * Did we immediately end the session in disconnect_cb | 254 | * Our environment. |
245 | */ | 255 | */ |
246 | int in_shutdown; | 256 | struct GNUNET_TRANSPORT_PluginEnvironment *env; |
247 | 257 | ||
248 | /** | 258 | /** |
249 | * Length of peer id | 259 | * Hash map of open sessions. |
250 | */ | 260 | */ |
251 | int peer_id_length; | 261 | struct GNUNET_CONTAINER_MultiPeerMap *sessions; |
252 | 262 | ||
253 | /** | 263 | /** |
254 | * External hostname the plugin can be connected to, can be different to | 264 | * Function to call about session status changes. |
255 | * the host's FQDN, used e.g. for reverse proxying | ||
256 | */ | 265 | */ |
257 | struct GNUNET_HELLO_Address *ext_addr; | 266 | GNUNET_TRANSPORT_SessionInfoCallback sic; |
258 | 267 | ||
259 | /** | 268 | /** |
260 | * Notify transport only about external address | 269 | * Closure for @e sic. |
261 | */ | 270 | */ |
262 | unsigned int external_only; | 271 | void *sic_cls; |
263 | 272 | ||
264 | /** | 273 | /** |
265 | * use IPv6 | 274 | * Plugin name |
266 | */ | 275 | */ |
267 | uint16_t use_ipv6; | 276 | char *name; |
268 | 277 | ||
269 | /** | 278 | /** |
270 | * use IPv4 | 279 | * Protocol |
271 | */ | 280 | */ |
272 | uint16_t use_ipv4; | 281 | char *protocol; |
273 | 282 | ||
274 | /** | 283 | /** |
275 | * Port used | 284 | * External address |
276 | */ | 285 | */ |
277 | uint16_t port; | 286 | char *external_hostname; |
278 | 287 | ||
279 | /** | 288 | /** |
280 | * Task calling transport service about external address | 289 | * External hostname the plugin can be connected to, can be different to |
290 | * the host's FQDN, used e.g. for reverse proxying | ||
281 | */ | 291 | */ |
282 | GNUNET_SCHEDULER_TaskIdentifier notify_ext_task; | 292 | struct GNUNET_HELLO_Address *ext_addr; |
283 | 293 | ||
284 | /** | 294 | /** |
285 | * NAT handle & address management | 295 | * NAT handle & address management |
286 | */ | 296 | */ |
287 | struct GNUNET_NAT_Handle *nat; | 297 | struct GNUNET_NAT_Handle *nat; |
288 | |||
289 | /** | ||
290 | * List of own addresses | ||
291 | */ | ||
292 | |||
293 | /** | 298 | /** |
294 | * IPv4 addresses DLL head | 299 | * IPv4 addresses DLL head |
295 | */ | 300 | */ |
@@ -311,26 +316,6 @@ struct HTTP_Server_Plugin | |||
311 | struct sockaddr_in6 *server_addr_v6; | 316 | struct sockaddr_in6 *server_addr_v6; |
312 | 317 | ||
313 | /** | 318 | /** |
314 | * MHD IPv4 task | ||
315 | */ | ||
316 | GNUNET_SCHEDULER_TaskIdentifier server_v4_task; | ||
317 | |||
318 | /** | ||
319 | * MHD IPv6 task | ||
320 | */ | ||
321 | GNUNET_SCHEDULER_TaskIdentifier server_v6_task; | ||
322 | |||
323 | /** | ||
324 | * The IPv4 server is scheduled to run asap | ||
325 | */ | ||
326 | int server_v4_immediately; | ||
327 | |||
328 | /** | ||
329 | * The IPv6 server is scheduled to run asap | ||
330 | */ | ||
331 | int server_v6_immediately; | ||
332 | |||
333 | /** | ||
334 | * MHD IPv4 daemon | 319 | * MHD IPv4 daemon |
335 | */ | 320 | */ |
336 | struct MHD_Daemon *server_v4; | 321 | struct MHD_Daemon *server_v4; |
@@ -340,11 +325,6 @@ struct HTTP_Server_Plugin | |||
340 | */ | 325 | */ |
341 | struct MHD_Daemon *server_v6; | 326 | struct MHD_Daemon *server_v6; |
342 | 327 | ||
343 | /** | ||
344 | * Regex for parsing URLs | ||
345 | */ | ||
346 | regex_t url_regex; | ||
347 | |||
348 | #if BUILD_HTTPS | 328 | #if BUILD_HTTPS |
349 | /** | 329 | /** |
350 | * Crypto related | 330 | * Crypto related |
@@ -368,105 +348,224 @@ struct HTTP_Server_Plugin | |||
368 | char *cert; | 348 | char *cert; |
369 | #endif | 349 | #endif |
370 | 350 | ||
371 | }; | 351 | /** |
352 | * MHD IPv4 task | ||
353 | */ | ||
354 | GNUNET_SCHEDULER_TaskIdentifier server_v4_task; | ||
372 | 355 | ||
356 | /** | ||
357 | * MHD IPv6 task | ||
358 | */ | ||
359 | GNUNET_SCHEDULER_TaskIdentifier server_v6_task; | ||
373 | 360 | ||
374 | /** | ||
375 | * Wrapper to manage addresses | ||
376 | */ | ||
377 | struct HttpAddressWrapper | ||
378 | { | ||
379 | /** | 361 | /** |
380 | * Linked list next | 362 | * Task calling transport service about external address |
381 | */ | 363 | */ |
382 | struct HttpAddressWrapper *next; | 364 | GNUNET_SCHEDULER_TaskIdentifier notify_ext_task; |
383 | 365 | ||
384 | /** | 366 | /** |
385 | * Linked list previous | 367 | * Notify transport only about external address |
386 | */ | 368 | */ |
387 | struct HttpAddressWrapper *prev; | 369 | unsigned int external_only; |
388 | 370 | ||
389 | struct HttpAddress *address; | 371 | /** |
372 | * The IPv4 server is scheduled to run asap | ||
373 | */ | ||
374 | int server_v4_immediately; | ||
390 | 375 | ||
391 | size_t addrlen; | 376 | /** |
392 | }; | 377 | * The IPv6 server is scheduled to run asap |
378 | */ | ||
379 | int server_v6_immediately; | ||
393 | 380 | ||
381 | /** | ||
382 | * Verify external address | ||
383 | */ | ||
384 | int verify_external_hostname; | ||
394 | 385 | ||
395 | /** | ||
396 | * Message to send using http | ||
397 | */ | ||
398 | struct HTTP_Message | ||
399 | { | ||
400 | /** | 386 | /** |
401 | * next pointer for double linked list | 387 | * Maximum number of sockets the plugin can use |
388 | * Each http inbound /outbound connections are two connections | ||
402 | */ | 389 | */ |
403 | struct HTTP_Message *next; | 390 | unsigned int max_connections; |
404 | 391 | ||
405 | /** | 392 | /** |
406 | * previous pointer for double linked list | 393 | * Current number of sockets the plugin can use |
394 | * Each http inbound /outbound connections are two connections | ||
407 | */ | 395 | */ |
408 | struct HTTP_Message *prev; | 396 | unsigned int cur_connections; |
409 | 397 | ||
410 | /** | 398 | /** |
411 | * buffer containing data to send | 399 | * Did we immediately end the session in disconnect_cb |
412 | */ | 400 | */ |
413 | char *buf; | 401 | int in_shutdown; |
414 | 402 | ||
415 | /** | 403 | /** |
416 | * amount of data already sent | 404 | * Length of peer id |
417 | */ | 405 | */ |
418 | size_t pos; | 406 | int peer_id_length; |
419 | 407 | ||
420 | /** | 408 | /** |
421 | * buffer length | 409 | * My options to be included in the address |
422 | */ | 410 | */ |
423 | size_t size; | 411 | uint32_t options; |
424 | 412 | ||
425 | /** | 413 | /** |
426 | * HTTP/S specific overhead | 414 | * use IPv6 |
427 | */ | 415 | */ |
428 | size_t overhead; | 416 | uint16_t use_ipv6; |
429 | 417 | ||
430 | /** | 418 | /** |
431 | * Continuation function to call once the transmission buffer | 419 | * use IPv4 |
432 | * has again space available. NULL if there is no | ||
433 | * continuation to call. | ||
434 | */ | 420 | */ |
435 | GNUNET_TRANSPORT_TransmitContinuation transmit_cont; | 421 | uint16_t use_ipv4; |
436 | 422 | ||
437 | /** | 423 | /** |
438 | * Closure for transmit_cont. | 424 | * Port used |
439 | */ | 425 | */ |
440 | void *transmit_cont_cls; | 426 | uint16_t port; |
427 | |||
428 | /** | ||
429 | * Regex for parsing URLs. FIXME: this seems overkill. | ||
430 | */ | ||
431 | regex_t url_regex; | ||
432 | |||
441 | }; | 433 | }; |
442 | 434 | ||
443 | 435 | ||
444 | /** | 436 | /** |
445 | * Start session timeout for session s | 437 | * If a session monitor is attached, notify it about the new |
446 | * @param s the session | 438 | * session state. |
439 | * | ||
440 | * @param plugin our plugin | ||
441 | * @param session session that changed state | ||
442 | * @param state new state of the session | ||
447 | */ | 443 | */ |
448 | static void | 444 | static void |
449 | server_start_session_timeout (struct Session *s); | 445 | notify_session_monitor (struct HTTP_Server_Plugin *plugin, |
446 | struct Session *session, | ||
447 | enum GNUNET_TRANSPORT_SessionState state) | ||
448 | { | ||
449 | struct GNUNET_TRANSPORT_SessionInfo info; | ||
450 | |||
451 | if (NULL == plugin->sic) | ||
452 | return; | ||
453 | memset (&info, 0, sizeof (info)); | ||
454 | info.state = state; | ||
455 | info.is_inbound = GNUNET_YES; | ||
456 | // info.num_msg_pending = session->msgs_in_queue; // FIXME | ||
457 | // info.num_bytes_pending = session->bytes_in_queue; // FIXME | ||
458 | // info.receive_delay = session->next_receive; // FIXME | ||
459 | // info.session_timeout = session->timeout; // FIXME | ||
460 | info.address = session->address; | ||
461 | plugin->sic (plugin->sic_cls, | ||
462 | session, | ||
463 | &info); | ||
464 | } | ||
450 | 465 | ||
451 | 466 | ||
452 | /** | 467 | /** |
453 | * Increment session timeout due to activity for session s | 468 | * Reschedule the execution of both IPv4 and IPv6 server. |
454 | * @param s the session | 469 | * |
470 | * @param plugin the plugin | ||
471 | * @param server which server to schedule v4 or v6? | ||
472 | * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait | ||
473 | * until timeout | ||
455 | */ | 474 | */ |
456 | static void | 475 | static void |
457 | server_reschedule_session_timeout (struct Session *s); | 476 | server_reschedule (struct HTTP_Server_Plugin *plugin, |
477 | struct MHD_Daemon *server, | ||
478 | int now); | ||
458 | 479 | ||
459 | 480 | ||
460 | /** | 481 | /** |
461 | * Cancel timeout for session s | 482 | * Deletes the session. Must not be used afterwards. |
462 | * @param s the session | 483 | * |
484 | * @param s the session to delete | ||
463 | */ | 485 | */ |
464 | static void | 486 | static void |
465 | server_stop_session_timeout (struct Session *s); | 487 | server_delete_session (struct Session *s) |
488 | { | ||
489 | struct HTTP_Server_Plugin *plugin = s->plugin; | ||
490 | struct HTTP_Message *msg; | ||
491 | struct HTTP_Message *tmp; | ||
492 | struct ServerConnection *send; | ||
493 | struct ServerConnection *recv; | ||
494 | |||
495 | if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) | ||
496 | { | ||
497 | GNUNET_SCHEDULER_cancel (s->timeout_task); | ||
498 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
499 | } | ||
500 | GNUNET_assert (GNUNET_OK == | ||
501 | GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, | ||
502 | &s->target, | ||
503 | s)); | ||
504 | msg = s->msg_head; | ||
505 | while (NULL != msg) | ||
506 | { | ||
507 | tmp = msg->next; | ||
508 | GNUNET_CONTAINER_DLL_remove (s->msg_head, | ||
509 | s->msg_tail, | ||
510 | msg); | ||
511 | if (NULL != msg->transmit_cont) | ||
512 | msg->transmit_cont (msg->transmit_cont_cls, | ||
513 | &s->target, | ||
514 | GNUNET_SYSERR, | ||
515 | msg->size, | ||
516 | msg->pos + msg->overhead); | ||
517 | GNUNET_free (msg); | ||
518 | msg = tmp; | ||
519 | } | ||
520 | send = s->server_send; | ||
521 | if (NULL != send) | ||
522 | { | ||
523 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
524 | "Server: %p / %p Terminating inbound PUT session to peer `%s'\n", | ||
525 | s, send, | ||
526 | GNUNET_i2s (&s->target)); | ||
527 | send->session = NULL; | ||
528 | MHD_set_connection_option (send->mhd_conn, | ||
529 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
530 | 1 /* 0 = no timeout, so this is MIN */); | ||
531 | server_reschedule (plugin, | ||
532 | send->mhd_daemon, | ||
533 | GNUNET_YES); | ||
534 | } | ||
535 | recv = s->server_recv; | ||
536 | if (NULL != recv) | ||
537 | { | ||
538 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Server: %p / %p Terminating inbound GET session to peer `%s'\n", | ||
540 | s, recv, GNUNET_i2s (&s->target)); | ||
541 | recv->session = NULL; | ||
542 | MHD_set_connection_option (recv->mhd_conn, | ||
543 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
544 | 1 /* 0 = no timeout, so this is MIN */); | ||
545 | server_reschedule (plugin, | ||
546 | recv->mhd_daemon, | ||
547 | GNUNET_YES); | ||
548 | } | ||
549 | if (GNUNET_YES == s->known_to_service) | ||
550 | plugin->env->session_end (plugin->env->cls, | ||
551 | s->address, | ||
552 | s); | ||
553 | if (NULL != s->msg_tk) | ||
554 | { | ||
555 | GNUNET_SERVER_mst_destroy (s->msg_tk); | ||
556 | s->msg_tk = NULL; | ||
557 | } | ||
558 | GNUNET_HELLO_address_free (s->address); | ||
559 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
560 | "Session %p destroyed\n", | ||
561 | s); | ||
562 | GNUNET_free (s); | ||
563 | } | ||
466 | 564 | ||
467 | 565 | ||
468 | /** | 566 | /** |
469 | * Disconnect session @a s | 567 | * Disconnect session @a s by telling MHD to close the |
568 | * connections (reducing timeout, etc.). | ||
470 | * | 569 | * |
471 | * @param cls closure with the `struct HTTP_Server_Plugin` | 570 | * @param cls closure with the `struct HTTP_Server_Plugin` |
472 | * @param s the session | 571 | * @param s the session |
@@ -474,31 +573,54 @@ server_stop_session_timeout (struct Session *s); | |||
474 | */ | 573 | */ |
475 | static int | 574 | static int |
476 | http_server_plugin_disconnect_session (void *cls, | 575 | http_server_plugin_disconnect_session (void *cls, |
477 | struct Session *s); | 576 | struct Session *s) |
577 | { | ||
578 | server_delete_session (s); | ||
579 | return GNUNET_OK; | ||
580 | } | ||
478 | 581 | ||
479 | 582 | ||
480 | /** | 583 | /** |
481 | * Does session s exist? | 584 | * Session was idle, so disconnect it |
482 | * | 585 | * |
483 | * @param plugin the plugin handle | 586 | * @param cls the session |
484 | * @param s the session | 587 | * @param tc task context |
485 | * @return #GNUNET_YES on success, #GNUNET_NO on error | ||
486 | */ | 588 | */ |
487 | static int | 589 | static void |
488 | server_exist_session (struct HTTP_Server_Plugin *plugin, struct Session *s); | 590 | server_session_timeout (void *cls, |
591 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
592 | { | ||
593 | struct Session *s = cls; | ||
594 | |||
595 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
596 | GNUNET_log (TIMEOUT_LOG, | ||
597 | "Session %p was idle for %s, disconnecting\n", | ||
598 | s, | ||
599 | GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, | ||
600 | GNUNET_YES)); | ||
601 | server_delete_session (s); | ||
602 | } | ||
489 | 603 | ||
490 | 604 | ||
491 | /** | 605 | /** |
492 | * Reschedule the execution of both IPv4 and IPv6 server | 606 | * Increment session timeout due to activity session @a s |
493 | * @param plugin the plugin | 607 | * |
494 | * @param server which server to schedule v4 or v6? | 608 | * @param s the session |
495 | * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait | ||
496 | * until timeout | ||
497 | */ | 609 | */ |
498 | static void | 610 | static void |
499 | server_reschedule (struct HTTP_Server_Plugin *plugin, | 611 | server_reschedule_session_timeout (struct Session *s) |
500 | struct MHD_Daemon *server, | 612 | { |
501 | int now); | 613 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); |
614 | GNUNET_SCHEDULER_cancel (s->timeout_task); | ||
615 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, | ||
616 | &server_session_timeout, | ||
617 | s); | ||
618 | GNUNET_log (TIMEOUT_LOG, | ||
619 | "Timeout rescheduled for session %p set to %s\n", | ||
620 | s, | ||
621 | GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, | ||
622 | GNUNET_YES)); | ||
623 | } | ||
502 | 624 | ||
503 | 625 | ||
504 | /** | 626 | /** |
@@ -530,29 +652,19 @@ server_reschedule (struct HTTP_Server_Plugin *plugin, | |||
530 | */ | 652 | */ |
531 | static ssize_t | 653 | static ssize_t |
532 | http_server_plugin_send (void *cls, | 654 | http_server_plugin_send (void *cls, |
533 | struct Session *session, | 655 | struct Session *session, |
534 | const char *msgbuf, size_t msgbuf_size, | 656 | const char *msgbuf, |
535 | unsigned int priority, | 657 | size_t msgbuf_size, |
536 | struct GNUNET_TIME_Relative to, | 658 | unsigned int priority, |
537 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | 659 | struct GNUNET_TIME_Relative to, |
660 | GNUNET_TRANSPORT_TransmitContinuation cont, | ||
661 | void *cont_cls) | ||
538 | { | 662 | { |
539 | struct HTTP_Server_Plugin *plugin = cls; | 663 | struct HTTP_Server_Plugin *plugin = cls; |
540 | struct HTTP_Message *msg; | 664 | struct HTTP_Message *msg; |
541 | int bytes_sent = 0; | 665 | ssize_t bytes_sent = 0; |
542 | char *stat_txt; | 666 | char *stat_txt; |
543 | 667 | ||
544 | GNUNET_assert (plugin != NULL); | ||
545 | GNUNET_assert (session != NULL); | ||
546 | |||
547 | if (GNUNET_NO == server_exist_session (plugin, session)) | ||
548 | { | ||
549 | GNUNET_break (0); | ||
550 | return GNUNET_SYSERR; | ||
551 | } | ||
552 | if (session->disconnect) | ||
553 | return GNUNET_SYSERR; | ||
554 | |||
555 | |||
556 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 668 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
557 | "Session %p/connection %p: Sending message with %u to peer `%s'\n", | 669 | "Session %p/connection %p: Sending message with %u to peer `%s'\n", |
558 | session, | 670 | session, |
@@ -570,25 +682,45 @@ http_server_plugin_send (void *cls, | |||
570 | msg->transmit_cont = cont; | 682 | msg->transmit_cont = cont; |
571 | msg->transmit_cont_cls = cont_cls; | 683 | msg->transmit_cont_cls = cont_cls; |
572 | memcpy (msg->buf, msgbuf, msgbuf_size); | 684 | memcpy (msg->buf, msgbuf, msgbuf_size); |
573 | 685 | GNUNET_CONTAINER_DLL_insert_tail (session->msg_head, | |
574 | GNUNET_CONTAINER_DLL_insert_tail (session->msg_head, session->msg_tail, msg); | 686 | session->msg_tail, |
575 | 687 | msg); | |
576 | GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers", plugin->protocol); | 688 | GNUNET_asprintf (&stat_txt, |
689 | "# bytes currently in %s_server buffers", | ||
690 | plugin->protocol); | ||
577 | GNUNET_STATISTICS_update (plugin->env->stats, | 691 | GNUNET_STATISTICS_update (plugin->env->stats, |
578 | stat_txt, msgbuf_size, GNUNET_NO); | 692 | stat_txt, msgbuf_size, GNUNET_NO); |
579 | GNUNET_free (stat_txt); | 693 | GNUNET_free (stat_txt); |
580 | 694 | ||
581 | if (NULL != session->server_send) | 695 | if (NULL != session->server_send) |
582 | { | ||
583 | server_reschedule (session->plugin, | 696 | server_reschedule (session->plugin, |
584 | session->server_send->mhd_daemon, | 697 | session->server_send->mhd_daemon, |
585 | GNUNET_YES); | 698 | GNUNET_YES); |
586 | } | ||
587 | return bytes_sent; | 699 | return bytes_sent; |
588 | } | 700 | } |
589 | 701 | ||
590 | 702 | ||
591 | /** | 703 | /** |
704 | * Terminate session. | ||
705 | * | ||
706 | * @param cls the `struct HTTP_Server_Plugin *` | ||
707 | * @param peer for which this is a session | ||
708 | * @param value the `struct Session` to clean up | ||
709 | * @return #GNUNET_OK (continue to iterate) | ||
710 | */ | ||
711 | static int | ||
712 | destroy_session_cb (void *cls, | ||
713 | const struct GNUNET_PeerIdentity *peer, | ||
714 | void *value) | ||
715 | { | ||
716 | struct Session *s = value; | ||
717 | |||
718 | server_delete_session (s); | ||
719 | return GNUNET_OK; | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
592 | * Function that can be used to force the plugin to disconnect | 724 | * Function that can be used to force the plugin to disconnect |
593 | * from the given peer and cancel all previous transmissions | 725 | * from the given peer and cancel all previous transmissions |
594 | * (and their continuationc). | 726 | * (and their continuationc). |
@@ -601,24 +733,14 @@ http_server_plugin_disconnect_peer (void *cls, | |||
601 | const struct GNUNET_PeerIdentity *target) | 733 | const struct GNUNET_PeerIdentity *target) |
602 | { | 734 | { |
603 | struct HTTP_Server_Plugin *plugin = cls; | 735 | struct HTTP_Server_Plugin *plugin = cls; |
604 | struct Session *next; | ||
605 | struct Session *pos; | ||
606 | 736 | ||
607 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 737 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
608 | "Transport tells me to disconnect `%s'\n", | 738 | "Transport tells me to disconnect `%s'\n", |
609 | GNUNET_i2s (target)); | 739 | GNUNET_i2s (target)); |
610 | next = plugin->head; | 740 | GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, |
611 | while (NULL != (pos = next)) | 741 | target, |
612 | { | 742 | &destroy_session_cb, |
613 | next = pos->next; | 743 | plugin); |
614 | if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) | ||
615 | { | ||
616 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
617 | "Disconnecting session %p to `%s'\n", | ||
618 | pos, GNUNET_i2s (target)); | ||
619 | http_server_plugin_disconnect_session (plugin, pos); | ||
620 | } | ||
621 | } | ||
622 | } | 744 | } |
623 | 745 | ||
624 | 746 | ||
@@ -671,9 +793,9 @@ http_server_plugin_address_suggested (void *cls, | |||
671 | 793 | ||
672 | /** | 794 | /** |
673 | * Creates a new outbound session the transport | 795 | * Creates a new outbound session the transport |
674 | * service will use to send data to the peer | 796 | * service will use to send data to the peer. |
675 | * | 797 | * |
676 | * Since HTTP/S server cannot create sessions, always return NULL | 798 | * Since HTTP/S server cannot create sessions, always returns NULL. |
677 | * | 799 | * |
678 | * @param cls the plugin | 800 | * @param cls the plugin |
679 | * @param address the address | 801 | * @param address the address |
@@ -688,85 +810,155 @@ http_server_plugin_get_session (void *cls, | |||
688 | 810 | ||
689 | 811 | ||
690 | /** | 812 | /** |
691 | * Deleting the session | 813 | * Call MHD IPv4 to process pending requests and then go back |
692 | * Must not be used afterwards | 814 | * and schedule the next run. |
693 | * | 815 | * |
694 | * @param cls closure with the `struct HTTP_ServerPlugin` | 816 | * @param cls plugin as closure |
695 | * @param s the session to delete | 817 | * @param tc task context |
696 | * @return #GNUNET_OK on success | ||
697 | */ | 818 | */ |
698 | static int | 819 | static void |
699 | server_delete_session (void *cls, | 820 | server_v4_run (void *cls, |
700 | struct Session *s) | 821 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
701 | { | 822 | { |
702 | struct HTTP_Server_Plugin *plugin = cls; | 823 | struct HTTP_Server_Plugin *plugin = cls; |
703 | struct HTTP_Message *msg; | ||
704 | struct HTTP_Message *tmp; | ||
705 | 824 | ||
706 | server_stop_session_timeout(s); | 825 | plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; |
707 | GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); | 826 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
708 | msg = s->msg_head; | 827 | return; |
709 | while (NULL != msg) | 828 | plugin->server_v4_immediately = GNUNET_NO; |
710 | { | 829 | GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4)); |
711 | tmp = msg->next; | 830 | server_reschedule (plugin, plugin->server_v4, GNUNET_NO); |
712 | GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); | ||
713 | if (NULL != msg->transmit_cont) | ||
714 | msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR, | ||
715 | msg->size, msg->pos + msg->overhead); | ||
716 | GNUNET_free (msg); | ||
717 | msg = tmp; | ||
718 | } | ||
719 | if (NULL != s->msg_tk) | ||
720 | { | ||
721 | GNUNET_SERVER_mst_destroy (s->msg_tk); | ||
722 | s->msg_tk = NULL; | ||
723 | } | ||
724 | GNUNET_HELLO_address_free (s->address); | ||
725 | GNUNET_free_non_null (s->server_recv); | ||
726 | GNUNET_free_non_null (s->server_send); | ||
727 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
728 | "Session %p destroyed\n", | ||
729 | s); | ||
730 | GNUNET_free (s); | ||
731 | return GNUNET_OK; | ||
732 | } | 831 | } |
733 | 832 | ||
734 | 833 | ||
735 | /** | 834 | /** |
736 | * Cancel timeout for session s | 835 | * Call MHD IPv6 to process pending requests and then go back |
737 | * | 836 | * and schedule the next run. |
738 | * @param s the session | 837 | * |
739 | */ | 838 | * @param cls plugin as closure |
839 | * @param tc task context | ||
840 | */ | ||
740 | static void | 841 | static void |
741 | server_stop_session_timeout (struct Session *s) | 842 | server_v6_run (void *cls, |
843 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
742 | { | 844 | { |
743 | GNUNET_assert (NULL != s); | 845 | struct HTTP_Server_Plugin *plugin = cls; |
744 | 846 | ||
745 | if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) | 847 | plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; |
746 | { | 848 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
747 | GNUNET_SCHEDULER_cancel (s->timeout_task); | 849 | return; |
748 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 850 | plugin->server_v6_immediately = GNUNET_NO; |
749 | GNUNET_log (TIMEOUT_LOG, "Timeout stopped for session %p\n", s); | 851 | GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6)); |
750 | } | 852 | server_reschedule (plugin, plugin->server_v6, GNUNET_NO); |
751 | } | 853 | } |
752 | 854 | ||
753 | 855 | ||
754 | /** | 856 | /** |
755 | * Function that queries MHD's select sets and | 857 | * Function that queries MHD's select sets and |
756 | * starts the task waiting for them. | 858 | * starts the task waiting for them. |
859 | * | ||
757 | * @param plugin plugin | 860 | * @param plugin plugin |
758 | * @param daemon_handle the MHD daemon handle | 861 | * @param daemon_handle the MHD daemon handle |
759 | * @param now schedule immediately | 862 | * @return gnunet task identifier |
760 | * @return task identifier | ||
761 | */ | 863 | */ |
762 | static GNUNET_SCHEDULER_TaskIdentifier | 864 | static GNUNET_SCHEDULER_TaskIdentifier |
763 | server_schedule (struct HTTP_Server_Plugin *plugin, | 865 | server_schedule (struct HTTP_Server_Plugin *plugin, |
764 | struct MHD_Daemon *daemon_handle, | 866 | struct MHD_Daemon *daemon_handle, |
765 | int now); | 867 | int now) |
868 | { | ||
869 | GNUNET_SCHEDULER_TaskIdentifier ret; | ||
870 | fd_set rs; | ||
871 | fd_set ws; | ||
872 | fd_set es; | ||
873 | struct GNUNET_NETWORK_FDSet *wrs; | ||
874 | struct GNUNET_NETWORK_FDSet *wws; | ||
875 | int max; | ||
876 | MHD_UNSIGNED_LONG_LONG timeout; | ||
877 | static unsigned long long last_timeout = 0; | ||
878 | int haveto; | ||
879 | struct GNUNET_TIME_Relative tv; | ||
880 | |||
881 | if (GNUNET_YES == plugin->in_shutdown) | ||
882 | return GNUNET_SCHEDULER_NO_TASK; | ||
883 | |||
884 | ret = GNUNET_SCHEDULER_NO_TASK; | ||
885 | FD_ZERO (&rs); | ||
886 | FD_ZERO (&ws); | ||
887 | FD_ZERO (&es); | ||
888 | wrs = GNUNET_NETWORK_fdset_create (); | ||
889 | wws = GNUNET_NETWORK_fdset_create (); | ||
890 | max = -1; | ||
891 | GNUNET_assert (MHD_YES == | ||
892 | MHD_get_fdset (daemon_handle, | ||
893 | &rs, | ||
894 | &ws, | ||
895 | &es, | ||
896 | &max)); | ||
897 | haveto = MHD_get_timeout (daemon_handle, &timeout); | ||
898 | if (haveto == MHD_YES) | ||
899 | { | ||
900 | if (timeout != last_timeout) | ||
901 | { | ||
902 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
903 | "SELECT Timeout changed from %llu to %llu (ms)\n", | ||
904 | last_timeout, timeout); | ||
905 | last_timeout = timeout; | ||
906 | } | ||
907 | if (timeout <= GNUNET_TIME_UNIT_SECONDS.rel_value_us / 1000LL) | ||
908 | tv.rel_value_us = (uint64_t) timeout * 1000LL; | ||
909 | else | ||
910 | tv = GNUNET_TIME_UNIT_SECONDS; | ||
911 | } | ||
912 | else | ||
913 | tv = GNUNET_TIME_UNIT_SECONDS; | ||
914 | /* Force immediate run, since we have outbound data to send */ | ||
915 | if (now == GNUNET_YES) | ||
916 | tv = GNUNET_TIME_UNIT_MILLISECONDS; | ||
917 | GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); | ||
918 | GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); | ||
919 | |||
920 | if (daemon_handle == plugin->server_v4) | ||
921 | { | ||
922 | if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK) | ||
923 | { | ||
924 | GNUNET_SCHEDULER_cancel (plugin->server_v4_task); | ||
925 | plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; | ||
926 | } | ||
927 | #if 0 | ||
928 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
929 | "Scheduling IPv4 server task in %llu ms\n", | ||
930 | tv); | ||
931 | #endif | ||
932 | ret = | ||
933 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
934 | tv, wrs, wws, | ||
935 | &server_v4_run, plugin); | ||
936 | } | ||
937 | if (daemon_handle == plugin->server_v6) | ||
938 | { | ||
939 | if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK) | ||
940 | { | ||
941 | GNUNET_SCHEDULER_cancel (plugin->server_v6_task); | ||
942 | plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; | ||
943 | } | ||
944 | #if 0 | ||
945 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
946 | "Scheduling IPv6 server task in %llu ms\n", tv); | ||
947 | #endif | ||
948 | ret = | ||
949 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
950 | tv, wrs, wws, | ||
951 | &server_v6_run, plugin); | ||
952 | } | ||
953 | GNUNET_NETWORK_fdset_destroy (wrs); | ||
954 | GNUNET_NETWORK_fdset_destroy (wws); | ||
955 | return ret; | ||
956 | } | ||
766 | 957 | ||
767 | 958 | ||
768 | /** | 959 | /** |
769 | * Reschedule the execution of both IPv4 and IPv6 server | 960 | * Reschedule the execution of both IPv4 and IPv6 server |
961 | * | ||
770 | * @param plugin the plugin | 962 | * @param plugin the plugin |
771 | * @param server which server to schedule v4 or v6? | 963 | * @param server which server to schedule v4 or v6? |
772 | * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait | 964 | * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait |
@@ -812,55 +1004,6 @@ server_reschedule (struct HTTP_Server_Plugin *plugin, | |||
812 | 1004 | ||
813 | 1005 | ||
814 | /** | 1006 | /** |
815 | * Disconnect session @a s | ||
816 | * | ||
817 | * @param cls closure with the `struct HTTP_Server_Plugin` | ||
818 | * @param s the session | ||
819 | * @return #GNUNET_OK on success | ||
820 | */ | ||
821 | static int | ||
822 | http_server_plugin_disconnect_session (void *cls, | ||
823 | struct Session *s) | ||
824 | { | ||
825 | struct HTTP_Server_Plugin *plugin = cls; | ||
826 | struct ServerConnection * send; | ||
827 | struct ServerConnection * recv; | ||
828 | |||
829 | if (GNUNET_NO == server_exist_session (plugin, s)) | ||
830 | { | ||
831 | GNUNET_break (0); | ||
832 | return GNUNET_SYSERR; | ||
833 | } | ||
834 | s->disconnect = GNUNET_YES; | ||
835 | send = (struct ServerConnection *) s->server_send; | ||
836 | if (send != NULL) | ||
837 | { | ||
838 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
839 | "Server: %p / %p Terminating inbound PUT session to peer `%s'\n", | ||
840 | s, send, GNUNET_i2s (&s->target)); | ||
841 | |||
842 | MHD_set_connection_option (send->mhd_conn, | ||
843 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
844 | 1); | ||
845 | server_reschedule (s->plugin, send->mhd_daemon, GNUNET_YES); | ||
846 | } | ||
847 | |||
848 | recv = (struct ServerConnection *) s->server_recv; | ||
849 | if (recv != NULL) | ||
850 | { | ||
851 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
852 | "Server: %p / %p Terminating inbound GET session to peer `%s'\n", | ||
853 | s, recv, GNUNET_i2s (&s->target)); | ||
854 | MHD_set_connection_option (recv->mhd_conn, | ||
855 | MHD_CONNECTION_OPTION_TIMEOUT, | ||
856 | 1); | ||
857 | server_reschedule (s->plugin, recv->mhd_daemon, GNUNET_YES); | ||
858 | } | ||
859 | return GNUNET_OK; | ||
860 | } | ||
861 | |||
862 | |||
863 | /** | ||
864 | * Function that is called to get the keepalive factor. | 1007 | * Function that is called to get the keepalive factor. |
865 | * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to | 1008 | * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to |
866 | * calculate the interval between keepalive packets. | 1009 | * calculate the interval between keepalive packets. |
@@ -874,16 +1017,12 @@ http_server_query_keepalive_factor (void *cls) | |||
874 | return 3; | 1017 | return 3; |
875 | } | 1018 | } |
876 | 1019 | ||
1020 | |||
877 | static void | 1021 | static void |
878 | http_server_plugin_update_session_timeout (void *cls, | 1022 | http_server_plugin_update_session_timeout (void *cls, |
879 | const struct GNUNET_PeerIdentity *peer, | 1023 | const struct GNUNET_PeerIdentity *peer, |
880 | struct Session *session) | 1024 | struct Session *session) |
881 | { | 1025 | { |
882 | struct HTTP_Server_Plugin *plugin = cls; | ||
883 | |||
884 | if (GNUNET_NO == server_exist_session (plugin, session)) | ||
885 | return; | ||
886 | |||
887 | server_reschedule_session_timeout (session); | 1026 | server_reschedule_session_timeout (session); |
888 | } | 1027 | } |
889 | 1028 | ||
@@ -900,7 +1039,7 @@ server_mhd_connection_timeout (struct HTTP_Server_Plugin *plugin, | |||
900 | struct Session *s, | 1039 | struct Session *s, |
901 | unsigned int to) | 1040 | unsigned int to) |
902 | { | 1041 | { |
903 | /* Setting timeouts for other connections */ | 1042 | /* Setting timeouts for other connections */ |
904 | if (NULL != s->server_recv) | 1043 | if (NULL != s->server_recv) |
905 | { | 1044 | { |
906 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1045 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1054,6 +1193,48 @@ server_parse_url (struct HTTP_Server_Plugin *plugin, | |||
1054 | 1193 | ||
1055 | 1194 | ||
1056 | /** | 1195 | /** |
1196 | * Closure for #session_tag_it(). | ||
1197 | */ | ||
1198 | struct SessionTagContext | ||
1199 | { | ||
1200 | /** | ||
1201 | * Set to session matching the tag. | ||
1202 | */ | ||
1203 | struct Session *res; | ||
1204 | |||
1205 | /** | ||
1206 | * Tag we are looking for. | ||
1207 | */ | ||
1208 | uint32_t tag; | ||
1209 | }; | ||
1210 | |||
1211 | |||
1212 | /** | ||
1213 | * Find a session with a matching tag. | ||
1214 | * | ||
1215 | * @param cls the `struct SessionTagContext *` | ||
1216 | * @param key peer identity (unused) | ||
1217 | * @param value the `struct Session *` | ||
1218 | * @return #GNUNET_NO if we found the session, #GNUNET_OK if not | ||
1219 | */ | ||
1220 | static int | ||
1221 | session_tag_it (void *cls, | ||
1222 | const struct GNUNET_PeerIdentity *key, | ||
1223 | void *value) | ||
1224 | { | ||
1225 | struct SessionTagContext *stc = cls; | ||
1226 | struct Session *s = value; | ||
1227 | |||
1228 | if (s->tag == stc->tag) | ||
1229 | { | ||
1230 | stc->res = s; | ||
1231 | return GNUNET_NO; | ||
1232 | } | ||
1233 | return GNUNET_YES; | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | /** | ||
1057 | * Lookup a mhd connection and create one if none is found | 1238 | * Lookup a mhd connection and create one if none is found |
1058 | * | 1239 | * |
1059 | * @param plugin the plugin handle | 1240 | * @param plugin the plugin handle |
@@ -1064,18 +1245,18 @@ server_parse_url (struct HTTP_Server_Plugin *plugin, | |||
1064 | */ | 1245 | */ |
1065 | static struct ServerConnection * | 1246 | static struct ServerConnection * |
1066 | server_lookup_connection (struct HTTP_Server_Plugin *plugin, | 1247 | server_lookup_connection (struct HTTP_Server_Plugin *plugin, |
1067 | struct MHD_Connection *mhd_connection, const char *url, | 1248 | struct MHD_Connection *mhd_connection, |
1068 | const char *method) | 1249 | const char *url, |
1250 | const char *method) | ||
1069 | { | 1251 | { |
1070 | struct Session *s = NULL; | 1252 | struct Session *s = NULL; |
1071 | struct ServerConnection *sc = NULL; | 1253 | struct ServerConnection *sc = NULL; |
1072 | const union MHD_ConnectionInfo *conn_info; | 1254 | const union MHD_ConnectionInfo *conn_info; |
1073 | struct HttpAddress *addr; | 1255 | struct HttpAddress *addr; |
1074 | |||
1075 | struct GNUNET_ATS_Information ats; | 1256 | struct GNUNET_ATS_Information ats; |
1076 | struct GNUNET_PeerIdentity target; | 1257 | struct GNUNET_PeerIdentity target; |
1077 | size_t addr_len; | 1258 | size_t addr_len; |
1078 | uint32_t tag = 0; | 1259 | struct SessionTagContext stc; |
1079 | uint32_t options; | 1260 | uint32_t options; |
1080 | int direction = GNUNET_SYSERR; | 1261 | int direction = GNUNET_SYSERR; |
1081 | unsigned int to; | 1262 | unsigned int to; |
@@ -1089,8 +1270,9 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1089 | "New %s connection from %s\n", | 1270 | "New %s connection from %s\n", |
1090 | method, | 1271 | method, |
1091 | url); | 1272 | url); |
1092 | 1273 | stc.tag = 0; | |
1093 | if (GNUNET_SYSERR == server_parse_url (plugin, url, &target, &tag, &options)) | 1274 | if (GNUNET_SYSERR == |
1275 | server_parse_url (plugin, url, &target, &stc.tag, &options)) | ||
1094 | { | 1276 | { |
1095 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1277 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1096 | "Invalid url %s\n", url); | 1278 | "Invalid url %s\n", url); |
@@ -1112,51 +1294,38 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1112 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1294 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1113 | "New %s connection from %s with tag %u (%u of %u)\n", | 1295 | "New %s connection from %s with tag %u (%u of %u)\n", |
1114 | method, | 1296 | method, |
1115 | GNUNET_i2s (&target), tag, | 1297 | GNUNET_i2s (&target), |
1298 | stc.tag, | ||
1116 | plugin->cur_connections, plugin->max_connections); | 1299 | plugin->cur_connections, plugin->max_connections); |
1117 | /* find duplicate session */ | 1300 | /* find existing session */ |
1118 | s = plugin->head; | 1301 | stc.res = NULL; |
1119 | while (s != NULL) | 1302 | GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, |
1120 | { | 1303 | &target, |
1121 | if ((0 == memcmp (&s->target, &target, sizeof (struct GNUNET_PeerIdentity))) && | 1304 | &session_tag_it, |
1122 | (s->tag == tag)) | 1305 | &stc); |
1123 | break; | 1306 | if (NULL == (s = stc.res)) |
1124 | s = s->next; | ||
1125 | } | ||
1126 | if (s != NULL) | ||
1127 | { | ||
1128 | if ((_RECEIVE == direction) && (NULL != s->server_recv)) | ||
1129 | { | ||
1130 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1131 | "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", | ||
1132 | GNUNET_i2s (&target), | ||
1133 | tag); | ||
1134 | return NULL; | ||
1135 | } | ||
1136 | if ((_SEND == direction) && (NULL != s->server_send)) | ||
1137 | { | ||
1138 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1139 | "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", | ||
1140 | GNUNET_i2s (&target), | ||
1141 | tag); | ||
1142 | return NULL; | ||
1143 | } | ||
1144 | } | ||
1145 | else | ||
1146 | { | 1307 | { |
1147 | /* create new session */ | 1308 | /* create new session */ |
1148 | addr = NULL; | 1309 | addr = NULL; |
1149 | switch (conn_info->client_addr->sa_family) | 1310 | switch (conn_info->client_addr->sa_family) |
1150 | { | 1311 | { |
1151 | case (AF_INET): | 1312 | case (AF_INET): |
1152 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in)); | 1313 | addr = http_common_address_from_socket (plugin->protocol, |
1314 | conn_info->client_addr, | ||
1315 | sizeof (struct sockaddr_in)); | ||
1153 | addr_len = http_common_address_get_size (addr); | 1316 | addr_len = http_common_address_get_size (addr); |
1154 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in)); | 1317 | ats = plugin->env->get_address_type (plugin->env->cls, |
1318 | conn_info->client_addr, | ||
1319 | sizeof (struct sockaddr_in)); | ||
1155 | break; | 1320 | break; |
1156 | case (AF_INET6): | 1321 | case (AF_INET6): |
1157 | addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in6)); | 1322 | addr = http_common_address_from_socket (plugin->protocol, |
1323 | conn_info->client_addr, | ||
1324 | sizeof (struct sockaddr_in6)); | ||
1158 | addr_len = http_common_address_get_size (addr); | 1325 | addr_len = http_common_address_get_size (addr); |
1159 | ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in6)); | 1326 | ats = plugin->env->get_address_type (plugin->env->cls, |
1327 | conn_info->client_addr, | ||
1328 | sizeof (struct sockaddr_in6)); | ||
1160 | break; | 1329 | break; |
1161 | default: | 1330 | default: |
1162 | /* external host name */ | 1331 | /* external host name */ |
@@ -1164,21 +1333,24 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1164 | ats.type = htonl (GNUNET_ATS_NET_WAN); | 1333 | ats.type = htonl (GNUNET_ATS_NET_WAN); |
1165 | return NULL; | 1334 | return NULL; |
1166 | } | 1335 | } |
1167 | |||
1168 | s = GNUNET_new (struct Session); | 1336 | s = GNUNET_new (struct Session); |
1169 | memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity)); | 1337 | s->target = target; |
1170 | s->plugin = plugin; | 1338 | s->plugin = plugin; |
1171 | s->address = GNUNET_HELLO_address_allocate (&s->target, PLUGIN_NAME, | 1339 | s->address = GNUNET_HELLO_address_allocate (&s->target, |
1172 | addr, addr_len, GNUNET_HELLO_ADDRESS_INFO_INBOUND); | 1340 | PLUGIN_NAME, |
1341 | addr, | ||
1342 | addr_len, | ||
1343 | GNUNET_HELLO_ADDRESS_INFO_INBOUND); | ||
1173 | s->ats_address_network_type = ats.value; | 1344 | s->ats_address_network_type = ats.value; |
1174 | s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS; | 1345 | s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS; |
1175 | s->tag = tag; | 1346 | s->tag = stc.tag; |
1176 | s->server_recv = NULL; | 1347 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, |
1177 | s->server_send = NULL; | 1348 | &server_session_timeout, |
1178 | s->session_passed = GNUNET_NO; | 1349 | s); |
1179 | s->session_ended = GNUNET_NO; | 1350 | (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessions, |
1180 | server_start_session_timeout(s); | 1351 | &s->target, |
1181 | GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); | 1352 | s, |
1353 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1182 | 1354 | ||
1183 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1355 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1184 | "Creating new session %p for peer `%s' connecting from `%s'\n", | 1356 | "Creating new session %p for peer `%s' connecting from `%s'\n", |
@@ -1188,6 +1360,23 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1188 | addr_len)); | 1360 | addr_len)); |
1189 | GNUNET_free_non_null (addr); | 1361 | GNUNET_free_non_null (addr); |
1190 | } | 1362 | } |
1363 | |||
1364 | if ( (_RECEIVE == direction) && (NULL != s->server_recv) ) | ||
1365 | { | ||
1366 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1367 | "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", | ||
1368 | GNUNET_i2s (&target), | ||
1369 | stc.tag); | ||
1370 | return NULL; | ||
1371 | } | ||
1372 | if ((_SEND == direction) && (NULL != s->server_send)) | ||
1373 | { | ||
1374 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1375 | "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", | ||
1376 | GNUNET_i2s (&target), | ||
1377 | stc.tag); | ||
1378 | return NULL; | ||
1379 | } | ||
1191 | sc = GNUNET_new (struct ServerConnection); | 1380 | sc = GNUNET_new (struct ServerConnection); |
1192 | if (conn_info->client_addr->sa_family == AF_INET) | 1381 | if (conn_info->client_addr->sa_family == AF_INET) |
1193 | sc->mhd_daemon = plugin->server_v4; | 1382 | sc->mhd_daemon = plugin->server_v4; |
@@ -1205,6 +1394,7 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1205 | 1394 | ||
1206 | if ((NULL != s->server_send) && (NULL != s->server_recv)) | 1395 | if ((NULL != s->server_send) && (NULL != s->server_recv)) |
1207 | { | 1396 | { |
1397 | s->known_to_service = GNUNET_YES; | ||
1208 | plugin->env->session_start (NULL, s->address ,s, NULL, 0); | 1398 | plugin->env->session_start (NULL, s->address ,s, NULL, 0); |
1209 | } | 1399 | } |
1210 | 1400 | ||
@@ -1223,7 +1413,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1223 | to = (HTTP_SERVER_SESSION_TIMEOUT.rel_value_us / 1000LL / 1000LL); | 1413 | to = (HTTP_SERVER_SESSION_TIMEOUT.rel_value_us / 1000LL / 1000LL); |
1224 | server_mhd_connection_timeout (plugin, s, to); | 1414 | server_mhd_connection_timeout (plugin, s, to); |
1225 | } | 1415 | } |
1226 | |||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1416 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1228 | "Setting timeout for %p to %u sec.\n", sc, to); | 1417 | "Setting timeout for %p to %u sec.\n", sc, to); |
1229 | return sc; | 1418 | return sc; |
@@ -1231,39 +1420,6 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin, | |||
1231 | 1420 | ||
1232 | 1421 | ||
1233 | /** | 1422 | /** |
1234 | * Lookup a session for a server connection | ||
1235 | * | ||
1236 | * @param plugin the plugin | ||
1237 | * @param sc the server connection | ||
1238 | * @return the session found or NULL | ||
1239 | */ | ||
1240 | static struct Session * | ||
1241 | server_lookup_session (struct HTTP_Server_Plugin *plugin, | ||
1242 | struct ServerConnection * sc) | ||
1243 | { | ||
1244 | struct Session *s; | ||
1245 | |||
1246 | for (s = plugin->head; NULL != s; s = s->next) | ||
1247 | if ((s->server_recv == sc) || (s->server_send == sc)) | ||
1248 | return s; | ||
1249 | return NULL; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | static int | ||
1254 | server_exist_session (struct HTTP_Server_Plugin *plugin, | ||
1255 | struct Session *s) | ||
1256 | { | ||
1257 | struct Session * head; | ||
1258 | |||
1259 | for (head = plugin->head; head != NULL; head = head->next) | ||
1260 | if (head == s) | ||
1261 | return GNUNET_YES; | ||
1262 | return GNUNET_NO; | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | /** | ||
1267 | * Callback called by MHD when it needs data to send | 1423 | * Callback called by MHD when it needs data to send |
1268 | * | 1424 | * |
1269 | * @param cls current session | 1425 | * @param cls current session |
@@ -1273,7 +1429,10 @@ server_exist_session (struct HTTP_Server_Plugin *plugin, | |||
1273 | * @return bytes written to buffer | 1429 | * @return bytes written to buffer |
1274 | */ | 1430 | */ |
1275 | static ssize_t | 1431 | static ssize_t |
1276 | server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) | 1432 | server_send_callback (void *cls, |
1433 | uint64_t pos, | ||
1434 | char *buf, | ||
1435 | size_t max) | ||
1277 | { | 1436 | { |
1278 | struct Session *s = cls; | 1437 | struct Session *s = cls; |
1279 | struct ServerConnection *sc; | 1438 | struct ServerConnection *sc; |
@@ -1281,8 +1440,6 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) | |||
1281 | struct HTTP_Message *msg; | 1440 | struct HTTP_Message *msg; |
1282 | char *stat_txt; | 1441 | char *stat_txt; |
1283 | 1442 | ||
1284 | if (GNUNET_NO == server_exist_session (s->plugin, s)) | ||
1285 | return 0; | ||
1286 | sc = s->server_send; | 1443 | sc = s->server_send; |
1287 | if (NULL == sc) | 1444 | if (NULL == sc) |
1288 | return 0; | 1445 | return 0; |
@@ -1298,7 +1455,9 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) | |||
1298 | /* removing message */ | 1455 | /* removing message */ |
1299 | if (msg->pos == msg->size) | 1456 | if (msg->pos == msg->size) |
1300 | { | 1457 | { |
1301 | GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); | 1458 | GNUNET_CONTAINER_DLL_remove (s->msg_head, |
1459 | s->msg_tail, | ||
1460 | msg); | ||
1302 | if (NULL != msg->transmit_cont) | 1461 | if (NULL != msg->transmit_cont) |
1303 | msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK, | 1462 | msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK, |
1304 | msg->size, msg->size + msg->overhead); | 1463 | msg->size, msg->size + msg->overhead); |
@@ -1342,7 +1501,8 @@ server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) | |||
1342 | * @return #GNUNET_OK | 1501 | * @return #GNUNET_OK |
1343 | */ | 1502 | */ |
1344 | static int | 1503 | static int |
1345 | server_receive_mst_cb (void *cls, void *client, | 1504 | server_receive_mst_cb (void *cls, |
1505 | void *client, | ||
1346 | const struct GNUNET_MessageHeader *message) | 1506 | const struct GNUNET_MessageHeader *message) |
1347 | { | 1507 | { |
1348 | struct Session *s = cls; | 1508 | struct Session *s = cls; |
@@ -1351,24 +1511,30 @@ server_receive_mst_cb (void *cls, void *client, | |||
1351 | struct GNUNET_TIME_Relative delay; | 1511 | struct GNUNET_TIME_Relative delay; |
1352 | char *stat_txt; | 1512 | char *stat_txt; |
1353 | 1513 | ||
1354 | if (GNUNET_NO == server_exist_session (s->plugin, s)) | ||
1355 | return GNUNET_OK; | ||
1356 | |||
1357 | |||
1358 | atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); | 1514 | atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); |
1359 | atsi.value = s->ats_address_network_type; | 1515 | atsi.value = s->ats_address_network_type; |
1360 | GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED)); | 1516 | GNUNET_break (s->ats_address_network_type != |
1361 | 1517 | ntohl (GNUNET_ATS_NET_UNSPECIFIED)); | |
1362 | delay = plugin->env->receive (plugin->env->cls, s->address, s, message); | 1518 | |
1363 | plugin->env->update_address_metrics (plugin->env->cls, s->address, s, &atsi, 1); | 1519 | if (GNUNET_NO == s->known_to_service) |
1364 | 1520 | { | |
1365 | GNUNET_asprintf (&stat_txt, "# bytes received via %s_server", plugin->protocol); | 1521 | s->known_to_service = GNUNET_YES; |
1522 | plugin->env->session_start (NULL, s->address, s, NULL, 0); | ||
1523 | } | ||
1524 | delay = plugin->env->receive (plugin->env->cls, | ||
1525 | s->address, | ||
1526 | s, | ||
1527 | message); | ||
1528 | plugin->env->update_address_metrics (plugin->env->cls, | ||
1529 | s->address, s, | ||
1530 | &atsi, 1); | ||
1531 | GNUNET_asprintf (&stat_txt, | ||
1532 | "# bytes received via %s_server", | ||
1533 | plugin->protocol); | ||
1366 | GNUNET_STATISTICS_update (plugin->env->stats, | 1534 | GNUNET_STATISTICS_update (plugin->env->stats, |
1367 | stat_txt, ntohs (message->size), GNUNET_NO); | 1535 | stat_txt, ntohs (message->size), GNUNET_NO); |
1368 | GNUNET_free (stat_txt); | 1536 | GNUNET_free (stat_txt); |
1369 | 1537 | s->next_receive = GNUNET_TIME_relative_to_absolute (delay); | |
1370 | s->session_passed = GNUNET_YES; | ||
1371 | s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); | ||
1372 | if (delay.rel_value_us > 0) | 1538 | if (delay.rel_value_us > 0) |
1373 | { | 1539 | { |
1374 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1540 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1384,6 +1550,7 @@ server_receive_mst_cb (void *cls, void *client, | |||
1384 | return GNUNET_OK; | 1550 | return GNUNET_OK; |
1385 | } | 1551 | } |
1386 | 1552 | ||
1553 | |||
1387 | /** | 1554 | /** |
1388 | * Add headers to a request indicating that we allow Cross-Origin Resource | 1555 | * Add headers to a request indicating that we allow Cross-Origin Resource |
1389 | * Sharing. | 1556 | * Sharing. |
@@ -1402,6 +1569,7 @@ add_cors_headers(struct MHD_Response *response) | |||
1402 | "86400"); | 1569 | "86400"); |
1403 | } | 1570 | } |
1404 | 1571 | ||
1572 | |||
1405 | /** | 1573 | /** |
1406 | * MHD callback for a new incoming connection | 1574 | * MHD callback for a new incoming connection |
1407 | * | 1575 | * |
@@ -1416,26 +1584,31 @@ add_cors_headers(struct MHD_Response *response) | |||
1416 | * @return MHD_YES if connection is accepted, MHD_NO on reject | 1584 | * @return MHD_YES if connection is accepted, MHD_NO on reject |
1417 | */ | 1585 | */ |
1418 | static int | 1586 | static int |
1419 | server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | 1587 | server_access_cb (void *cls, |
1420 | const char *url, const char *method, const char *version, | 1588 | struct MHD_Connection *mhd_connection, |
1421 | const char *upload_data, size_t * upload_data_size, | 1589 | const char *url, |
1590 | const char *method, | ||
1591 | const char *version, | ||
1592 | const char *upload_data, | ||
1593 | size_t *upload_data_size, | ||
1422 | void **httpSessionCache) | 1594 | void **httpSessionCache) |
1423 | { | 1595 | { |
1424 | struct HTTP_Server_Plugin *plugin = cls; | 1596 | struct HTTP_Server_Plugin *plugin = cls; |
1425 | int res = MHD_YES; | ||
1426 | |||
1427 | struct ServerConnection *sc = *httpSessionCache; | 1597 | struct ServerConnection *sc = *httpSessionCache; |
1428 | struct Session *s; | 1598 | struct Session *s; |
1429 | struct MHD_Response *response; | 1599 | struct MHD_Response *response; |
1600 | int res = MHD_YES; | ||
1430 | 1601 | ||
1431 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1602 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1432 | _("Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data size %u\n"), | 1603 | _("Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data size %u\n"), |
1433 | sc, | 1604 | sc, |
1434 | plugin->cur_connections, plugin->max_connections, | 1605 | plugin->cur_connections, |
1435 | method, version, url, (*upload_data_size)); | 1606 | plugin->max_connections, |
1436 | 1607 | method, | |
1437 | GNUNET_assert (cls != NULL); | 1608 | version, |
1438 | if (sc == NULL) | 1609 | url, |
1610 | (*upload_data_size)); | ||
1611 | if (NULL == sc) | ||
1439 | { | 1612 | { |
1440 | /* CORS pre-flight request */ | 1613 | /* CORS pre-flight request */ |
1441 | if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method)) | 1614 | if (0 == strcmp (MHD_HTTP_METHOD_OPTIONS, method)) |
@@ -1449,13 +1622,18 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | |||
1449 | } | 1622 | } |
1450 | /* new connection */ | 1623 | /* new connection */ |
1451 | sc = server_lookup_connection (plugin, mhd_connection, url, method); | 1624 | sc = server_lookup_connection (plugin, mhd_connection, url, method); |
1452 | if (sc != NULL) | 1625 | if (NULL != sc) |
1453 | { | 1626 | { |
1627 | /* attach to new / existing session */ | ||
1454 | (*httpSessionCache) = sc; | 1628 | (*httpSessionCache) = sc; |
1455 | } | 1629 | } |
1456 | else | 1630 | else |
1457 | { | 1631 | { |
1458 | response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE), HTTP_ERROR_RESPONSE, MHD_NO, MHD_NO); | 1632 | /* existing session already has matching connection, refuse */ |
1633 | response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE), | ||
1634 | HTTP_ERROR_RESPONSE, | ||
1635 | MHD_NO, | ||
1636 | MHD_NO); | ||
1459 | MHD_add_response_header (response, | 1637 | MHD_add_response_header (response, |
1460 | MHD_HTTP_HEADER_CONTENT_TYPE, | 1638 | MHD_HTTP_HEADER_CONTENT_TYPE, |
1461 | "text/html"); | 1639 | "text/html"); |
@@ -1465,33 +1643,19 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | |||
1465 | return res; | 1643 | return res; |
1466 | } | 1644 | } |
1467 | } | 1645 | } |
1468 | else | 1646 | /* 'old' connection */ |
1647 | if (NULL == (s = sc->session)) | ||
1469 | { | 1648 | { |
1470 | /* 'old' connection */ | 1649 | /* Session was already disconnected; |
1471 | if (NULL == server_lookup_session (plugin, sc)) | 1650 | sent HTTP/1.1: 200 OK as response */ |
1472 | { | ||
1473 | /* Session was already disconnected */ | ||
1474 | return MHD_NO; | ||
1475 | } | ||
1476 | } | ||
1477 | |||
1478 | /* existing connection */ | ||
1479 | sc = (*httpSessionCache); | ||
1480 | s = sc->session; | ||
1481 | GNUNET_assert (NULL != s); | ||
1482 | /* connection is to be disconnected */ | ||
1483 | if (s->disconnect == GNUNET_YES) | ||
1484 | { | ||
1485 | /* Sent HTTP/1.1: 200 OK as response */ | ||
1486 | response = MHD_create_response_from_data (strlen ("Thank you!"), | 1651 | response = MHD_create_response_from_data (strlen ("Thank you!"), |
1487 | "Thank you!", | 1652 | "Thank you!", |
1488 | MHD_NO, MHD_NO); | 1653 | MHD_NO, MHD_NO); |
1489 | add_cors_headers(response); | 1654 | add_cors_headers(response); |
1490 | MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); | 1655 | MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); |
1491 | MHD_destroy_response (response); | 1656 | MHD_destroy_response (response); |
1492 | return MHD_YES; | 1657 | return MHD_YES; |
1493 | } | 1658 | } |
1494 | GNUNET_assert (s != NULL); | ||
1495 | 1659 | ||
1496 | if (sc->direction == _SEND) | 1660 | if (sc->direction == _SEND) |
1497 | { | 1661 | { |
@@ -1595,68 +1759,61 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection, | |||
1595 | * @param httpSessionCache the pointer to distinguish | 1759 | * @param httpSessionCache the pointer to distinguish |
1596 | */ | 1760 | */ |
1597 | static void | 1761 | static void |
1598 | server_disconnect_cb (void *cls, struct MHD_Connection *connection, | 1762 | server_disconnect_cb (void *cls, |
1763 | struct MHD_Connection *connection, | ||
1599 | void **httpSessionCache) | 1764 | void **httpSessionCache) |
1600 | { | 1765 | { |
1601 | struct HTTP_Server_Plugin *plugin = cls; | 1766 | struct HTTP_Server_Plugin *plugin = cls; |
1602 | struct ServerConnection *sc = *httpSessionCache; | 1767 | struct ServerConnection *sc = *httpSessionCache; |
1603 | struct Session *s; | 1768 | struct Session *s; |
1604 | struct Session *t; | ||
1605 | 1769 | ||
1606 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1770 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1607 | "Disconnect for connection %p\n", | 1771 | "Disconnect for connection %p\n", |
1608 | sc); | 1772 | sc); |
1609 | if (sc == NULL) | 1773 | if (NULL == sc) |
1610 | return; | 1774 | return; /* never really got setup */ |
1611 | 1775 | if (NULL == (s = sc->session)) | |
1612 | if (NULL == (s = server_lookup_session (plugin, sc))) | 1776 | return; /* session already dead */ |
1613 | return; | ||
1614 | for (t = plugin->head; t != NULL; t = t->next) | ||
1615 | if (t == s) | ||
1616 | break; | ||
1617 | if (NULL == t) | ||
1618 | return; | ||
1619 | |||
1620 | if (sc->direction == _SEND) | 1777 | if (sc->direction == _SEND) |
1621 | { | 1778 | { |
1622 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1779 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1623 | "Peer `%s' connection %p, GET on address `%s' disconnected\n", | 1780 | "Peer `%s' connection %p, GET on address `%s' disconnected\n", |
1624 | GNUNET_i2s (&s->target), s->server_send, | 1781 | GNUNET_i2s (&s->target), |
1782 | s->server_send, | ||
1625 | http_common_plugin_address_to_string (plugin->protocol, | 1783 | http_common_plugin_address_to_string (plugin->protocol, |
1626 | s->address->address, | 1784 | s->address->address, |
1627 | s->address->address_length)); | 1785 | s->address->address_length)); |
1628 | s->server_send = NULL; | 1786 | s->server_send = NULL; |
1629 | if (!(sc->options & OPTION_LONG_POLL) && NULL != (s->server_recv)) | 1787 | if (! ( (0 != (sc->options & OPTION_LONG_POLL)) && |
1788 | (NULL != s->server_recv) ) ) | ||
1630 | { | 1789 | { |
1631 | s->disconnect = GNUNET_YES; | 1790 | server_delete_session (s); |
1632 | GNUNET_assert (NULL != s->server_recv->mhd_conn); | 1791 | GNUNET_free (sc); |
1633 | #if MHD_VERSION >= 0x00090E00 | 1792 | plugin->cur_connections--; |
1634 | MHD_set_connection_option (s->server_recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, | 1793 | return; |
1635 | 1); | ||
1636 | #endif | ||
1637 | server_reschedule (plugin, s->server_recv->mhd_daemon, GNUNET_NO); | ||
1638 | } | 1794 | } |
1639 | } | 1795 | } |
1640 | if (sc->direction == _RECEIVE) | 1796 | if (sc->direction == _RECEIVE) |
1641 | { | 1797 | { |
1642 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1798 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1643 | "Peer `%s' connection %p PUT on address `%s' disconnected\n", | 1799 | "Peer `%s' connection %p PUT on address `%s' disconnected\n", |
1644 | GNUNET_i2s (&s->target), s->server_recv, | 1800 | GNUNET_i2s (&s->target), |
1801 | s->server_recv, | ||
1645 | http_common_plugin_address_to_string (plugin->protocol, | 1802 | http_common_plugin_address_to_string (plugin->protocol, |
1646 | s->address->address, | 1803 | s->address->address, |
1647 | s->address->address_length)); | 1804 | s->address->address_length)); |
1648 | s->server_recv = NULL; | 1805 | s->server_recv = NULL; |
1649 | if (s->msg_tk != NULL) | 1806 | if (NULL != s->msg_tk) |
1650 | { | 1807 | { |
1651 | GNUNET_SERVER_mst_destroy (s->msg_tk); | 1808 | GNUNET_SERVER_mst_destroy (s->msg_tk); |
1652 | s->msg_tk = NULL; | 1809 | s->msg_tk = NULL; |
1653 | } | 1810 | } |
1654 | } | 1811 | } |
1655 | |||
1656 | GNUNET_free (sc); | 1812 | GNUNET_free (sc); |
1657 | plugin->cur_connections--; | 1813 | plugin->cur_connections--; |
1658 | 1814 | ||
1659 | if (s->disconnect && (s->server_send == NULL) && (s->server_recv == NULL)) | 1815 | if ( (NULL == s->server_send) && |
1816 | (NULL == s->server_recv) ) | ||
1660 | { | 1817 | { |
1661 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1818 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1662 | "Peer `%s' on address `%s' disconnected\n", | 1819 | "Peer `%s' on address `%s' disconnected\n", |
@@ -1665,13 +1822,7 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection, | |||
1665 | s->address->address, | 1822 | s->address->address, |
1666 | s->address->address_length)); | 1823 | s->address->address_length)); |
1667 | 1824 | ||
1668 | if ((GNUNET_YES == s->session_passed) && (GNUNET_NO == s->session_ended)) | 1825 | server_delete_session (s); |
1669 | { | ||
1670 | /* Notify transport immediately that this session is invalid */ | ||
1671 | s->session_ended = GNUNET_YES; | ||
1672 | plugin->env->session_end (plugin->env->cls, s->address, s); | ||
1673 | } | ||
1674 | server_delete_session (plugin, s); | ||
1675 | } | 1826 | } |
1676 | } | 1827 | } |
1677 | 1828 | ||
@@ -1685,7 +1836,9 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection, | |||
1685 | * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected | 1836 | * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected |
1686 | */ | 1837 | */ |
1687 | static int | 1838 | static int |
1688 | server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len) | 1839 | server_accept_cb (void *cls, |
1840 | const struct sockaddr *addr, | ||
1841 | socklen_t addr_len) | ||
1689 | { | 1842 | { |
1690 | struct HTTP_Server_Plugin *plugin = cls; | 1843 | struct HTTP_Server_Plugin *plugin = cls; |
1691 | 1844 | ||
@@ -1708,167 +1861,17 @@ server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len) | |||
1708 | 1861 | ||
1709 | 1862 | ||
1710 | static void | 1863 | static void |
1711 | server_log (void *arg, const char *fmt, va_list ap) | 1864 | server_log (void *arg, |
1865 | const char *fmt, | ||
1866 | va_list ap) | ||
1712 | { | 1867 | { |
1713 | char text[1024]; | 1868 | char text[1024]; |
1714 | 1869 | ||
1715 | vsnprintf (text, sizeof (text), fmt, ap); | 1870 | vsnprintf (text, sizeof (text), fmt, ap); |
1716 | va_end (ap); | 1871 | va_end (ap); |
1717 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server: %s\n", text); | 1872 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1718 | } | 1873 | "Server: %s\n", |
1719 | 1874 | text); | |
1720 | |||
1721 | /** | ||
1722 | * Call MHD IPv4 to process pending requests and then go back | ||
1723 | * and schedule the next run. | ||
1724 | * @param cls plugin as closure | ||
1725 | * @param tc task context | ||
1726 | */ | ||
1727 | static void | ||
1728 | server_v4_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1729 | { | ||
1730 | struct HTTP_Server_Plugin *plugin = cls; | ||
1731 | |||
1732 | GNUNET_assert (cls != NULL); | ||
1733 | |||
1734 | plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; | ||
1735 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1736 | return; | ||
1737 | #if 0 | ||
1738 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1739 | "Running IPv4 server\n"); | ||
1740 | #endif | ||
1741 | plugin->server_v4_immediately = GNUNET_NO; | ||
1742 | GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4)); | ||
1743 | server_reschedule (plugin, plugin->server_v4, GNUNET_NO); | ||
1744 | } | ||
1745 | |||
1746 | |||
1747 | /** | ||
1748 | * Call MHD IPv6 to process pending requests and then go back | ||
1749 | * and schedule the next run. | ||
1750 | * @param cls plugin as closure | ||
1751 | * @param tc task context | ||
1752 | */ | ||
1753 | static void | ||
1754 | server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1755 | { | ||
1756 | struct HTTP_Server_Plugin *plugin = cls; | ||
1757 | |||
1758 | GNUNET_assert (cls != NULL); | ||
1759 | plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; | ||
1760 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1761 | return; | ||
1762 | #if 0 | ||
1763 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1764 | "Running IPv6 server\n"); | ||
1765 | #endif | ||
1766 | plugin->server_v6_immediately = GNUNET_NO; | ||
1767 | GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6)); | ||
1768 | server_reschedule (plugin, plugin->server_v6, GNUNET_NO); | ||
1769 | } | ||
1770 | |||
1771 | |||
1772 | /** | ||
1773 | * Function that queries MHD's select sets and | ||
1774 | * starts the task waiting for them. | ||
1775 | * | ||
1776 | * @param plugin plugin | ||
1777 | * @param daemon_handle the MHD daemon handle | ||
1778 | * @return gnunet task identifier | ||
1779 | */ | ||
1780 | static GNUNET_SCHEDULER_TaskIdentifier | ||
1781 | server_schedule (struct HTTP_Server_Plugin *plugin, | ||
1782 | struct MHD_Daemon *daemon_handle, | ||
1783 | int now) | ||
1784 | { | ||
1785 | GNUNET_SCHEDULER_TaskIdentifier ret; | ||
1786 | fd_set rs; | ||
1787 | fd_set ws; | ||
1788 | fd_set es; | ||
1789 | struct GNUNET_NETWORK_FDSet *wrs; | ||
1790 | struct GNUNET_NETWORK_FDSet *wws; | ||
1791 | struct GNUNET_NETWORK_FDSet *wes; | ||
1792 | int max; | ||
1793 | MHD_UNSIGNED_LONG_LONG timeout; | ||
1794 | static unsigned long long last_timeout = 0; | ||
1795 | int haveto; | ||
1796 | |||
1797 | struct GNUNET_TIME_Relative tv; | ||
1798 | |||
1799 | if (GNUNET_YES == plugin->in_shutdown) | ||
1800 | return GNUNET_SCHEDULER_NO_TASK; | ||
1801 | |||
1802 | ret = GNUNET_SCHEDULER_NO_TASK; | ||
1803 | FD_ZERO (&rs); | ||
1804 | FD_ZERO (&ws); | ||
1805 | FD_ZERO (&es); | ||
1806 | wrs = GNUNET_NETWORK_fdset_create (); | ||
1807 | wes = GNUNET_NETWORK_fdset_create (); | ||
1808 | wws = GNUNET_NETWORK_fdset_create (); | ||
1809 | max = -1; | ||
1810 | GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); | ||
1811 | haveto = MHD_get_timeout (daemon_handle, &timeout); | ||
1812 | if (haveto == MHD_YES) | ||
1813 | { | ||
1814 | if (timeout != last_timeout) | ||
1815 | { | ||
1816 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1817 | "SELECT Timeout changed from %llu to %llu (ms)\n", | ||
1818 | last_timeout, timeout); | ||
1819 | last_timeout = timeout; | ||
1820 | } | ||
1821 | if (timeout <= GNUNET_TIME_UNIT_SECONDS.rel_value_us / 1000LL) | ||
1822 | tv.rel_value_us = (uint64_t) timeout * 1000LL; | ||
1823 | else | ||
1824 | tv = GNUNET_TIME_UNIT_SECONDS; | ||
1825 | } | ||
1826 | else | ||
1827 | tv = GNUNET_TIME_UNIT_SECONDS; | ||
1828 | /* Force immediate run, since we have outbound data to send */ | ||
1829 | if (now == GNUNET_YES) | ||
1830 | tv = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1831 | GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); | ||
1832 | GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); | ||
1833 | GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); | ||
1834 | |||
1835 | if (daemon_handle == plugin->server_v4) | ||
1836 | { | ||
1837 | if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK) | ||
1838 | { | ||
1839 | GNUNET_SCHEDULER_cancel (plugin->server_v4_task); | ||
1840 | plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; | ||
1841 | } | ||
1842 | #if 0 | ||
1843 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1844 | "Scheduling IPv4 server task in %llu ms\n", | ||
1845 | tv); | ||
1846 | #endif | ||
1847 | ret = | ||
1848 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
1849 | tv, wrs, wws, | ||
1850 | &server_v4_run, plugin); | ||
1851 | } | ||
1852 | if (daemon_handle == plugin->server_v6) | ||
1853 | { | ||
1854 | if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK) | ||
1855 | { | ||
1856 | GNUNET_SCHEDULER_cancel (plugin->server_v6_task); | ||
1857 | plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; | ||
1858 | } | ||
1859 | #if 0 | ||
1860 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1861 | "Scheduling IPv6 server task in %llu ms\n", tv); | ||
1862 | #endif | ||
1863 | ret = | ||
1864 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
1865 | tv, wrs, wws, | ||
1866 | &server_v6_run, plugin); | ||
1867 | } | ||
1868 | GNUNET_NETWORK_fdset_destroy (wrs); | ||
1869 | GNUNET_NETWORK_fdset_destroy (wws); | ||
1870 | GNUNET_NETWORK_fdset_destroy (wes); | ||
1871 | return ret; | ||
1872 | } | 1875 | } |
1873 | 1876 | ||
1874 | 1877 | ||
@@ -1927,7 +1930,8 @@ server_load_certificate (struct HTTP_Server_Plugin *plugin) | |||
1927 | 1930 | ||
1928 | 1931 | ||
1929 | if (GNUNET_OK != | 1932 | if (GNUNET_OK != |
1930 | GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name, | 1933 | GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, |
1934 | plugin->name, | ||
1931 | "KEY_FILE", &key_file)) | 1935 | "KEY_FILE", &key_file)) |
1932 | { | 1936 | { |
1933 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | 1937 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, |
@@ -1935,7 +1939,8 @@ server_load_certificate (struct HTTP_Server_Plugin *plugin) | |||
1935 | return GNUNET_SYSERR; | 1939 | return GNUNET_SYSERR; |
1936 | } | 1940 | } |
1937 | if (GNUNET_OK != | 1941 | if (GNUNET_OK != |
1938 | GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name, | 1942 | GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, |
1943 | plugin->name, | ||
1939 | "CERT_FILE", &cert_file)) | 1944 | "CERT_FILE", &cert_file)) |
1940 | { | 1945 | { |
1941 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | 1946 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, |
@@ -2035,7 +2040,7 @@ server_load_certificate (struct HTTP_Server_Plugin *plugin) | |||
2035 | * Start the HTTP server | 2040 | * Start the HTTP server |
2036 | * | 2041 | * |
2037 | * @param plugin the plugin handle | 2042 | * @param plugin the plugin handle |
2038 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | 2043 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure |
2039 | */ | 2044 | */ |
2040 | static int | 2045 | static int |
2041 | server_start (struct HTTP_Server_Plugin *plugin) | 2046 | server_start (struct HTTP_Server_Plugin *plugin) |
@@ -2181,7 +2186,7 @@ server_start (struct HTTP_Server_Plugin *plugin) | |||
2181 | } | 2186 | } |
2182 | 2187 | ||
2183 | 2188 | ||
2184 | void | 2189 | static void |
2185 | server_stop (struct HTTP_Server_Plugin *plugin) | 2190 | server_stop (struct HTTP_Server_Plugin *plugin) |
2186 | { | 2191 | { |
2187 | if (plugin->server_v4 != NULL) | 2192 | if (plugin->server_v4 != NULL) |
@@ -2223,20 +2228,24 @@ server_stop (struct HTTP_Server_Plugin *plugin) | |||
2223 | * Add an address to the server's set of addresses and notify transport | 2228 | * Add an address to the server's set of addresses and notify transport |
2224 | * | 2229 | * |
2225 | * @param cls the plugin handle | 2230 | * @param cls the plugin handle |
2226 | * @param add_remove GNUNET_YES on add, GNUNET_NO on remove | 2231 | * @param add_remove #GNUNET_YES on add, #GNUNET_NO on remove |
2227 | * @param addr the address | 2232 | * @param addr the address |
2228 | * @param addrlen address length | 2233 | * @param addrlen address length |
2229 | */ | 2234 | */ |
2230 | static void | 2235 | static void |
2231 | server_add_address (void *cls, int add_remove, const struct sockaddr *addr, | 2236 | server_add_address (void *cls, |
2232 | socklen_t addrlen) | 2237 | int add_remove, |
2238 | const struct sockaddr *addr, | ||
2239 | socklen_t addrlen) | ||
2233 | { | 2240 | { |
2234 | struct HTTP_Server_Plugin *plugin = cls; | 2241 | struct HTTP_Server_Plugin *plugin = cls; |
2235 | struct GNUNET_HELLO_Address *address; | 2242 | struct GNUNET_HELLO_Address *address; |
2236 | struct HttpAddressWrapper *w = NULL; | 2243 | struct HttpAddressWrapper *w = NULL; |
2237 | 2244 | ||
2238 | w = GNUNET_new (struct HttpAddressWrapper); | 2245 | w = GNUNET_new (struct HttpAddressWrapper); |
2239 | w->address = http_common_address_from_socket (plugin->protocol, addr, addrlen); | 2246 | w->address = http_common_address_from_socket (plugin->protocol, |
2247 | addr, | ||
2248 | addrlen); | ||
2240 | if (NULL == w->address) | 2249 | if (NULL == w->address) |
2241 | { | 2250 | { |
2242 | GNUNET_free (w); | 2251 | GNUNET_free (w); |
@@ -2244,7 +2253,9 @@ server_add_address (void *cls, int add_remove, const struct sockaddr *addr, | |||
2244 | } | 2253 | } |
2245 | w->addrlen = http_common_address_get_size (w->address); | 2254 | w->addrlen = http_common_address_get_size (w->address); |
2246 | 2255 | ||
2247 | GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w); | 2256 | GNUNET_CONTAINER_DLL_insert (plugin->addr_head, |
2257 | plugin->addr_tail, | ||
2258 | w); | ||
2248 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2259 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2249 | "Notifying transport to add address `%s'\n", | 2260 | "Notifying transport to add address `%s'\n", |
2250 | http_common_plugin_address_to_string (plugin->protocol, | 2261 | http_common_plugin_address_to_string (plugin->protocol, |
@@ -2259,7 +2270,9 @@ server_add_address (void *cls, int add_remove, const struct sockaddr *addr, | |||
2259 | "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); | 2270 | "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); |
2260 | #endif | 2271 | #endif |
2261 | 2272 | ||
2262 | plugin->env->notify_address (plugin->env->cls, add_remove, address); | 2273 | plugin->env->notify_address (plugin->env->cls, |
2274 | add_remove, | ||
2275 | address); | ||
2263 | GNUNET_HELLO_address_free (address); | 2276 | GNUNET_HELLO_address_free (address); |
2264 | } | 2277 | } |
2265 | 2278 | ||
@@ -2268,28 +2281,38 @@ server_add_address (void *cls, int add_remove, const struct sockaddr *addr, | |||
2268 | * Remove an address from the server's set of addresses and notify transport | 2281 | * Remove an address from the server's set of addresses and notify transport |
2269 | * | 2282 | * |
2270 | * @param cls the plugin handle | 2283 | * @param cls the plugin handle |
2271 | * @param add_remove GNUNET_YES on add, GNUNET_NO on remove | 2284 | * @param add_remove #GNUNET_YES on add, #GNUNET_NO on remove |
2272 | * @param addr the address | 2285 | * @param addr the address |
2273 | * @param addrlen address length | 2286 | * @param addrlen address length |
2274 | */ | 2287 | */ |
2275 | static void | 2288 | static void |
2276 | server_remove_address (void *cls, int add_remove, const struct sockaddr *addr, | 2289 | server_remove_address (void *cls, |
2277 | socklen_t addrlen) | 2290 | int add_remove, |
2291 | const struct sockaddr *addr, | ||
2292 | socklen_t addrlen) | ||
2278 | { | 2293 | { |
2279 | struct HTTP_Server_Plugin *plugin = cls; | 2294 | struct HTTP_Server_Plugin *plugin = cls; |
2280 | struct GNUNET_HELLO_Address *address; | 2295 | struct GNUNET_HELLO_Address *address; |
2281 | struct HttpAddressWrapper *w = plugin->addr_head; | 2296 | struct HttpAddressWrapper *w = plugin->addr_head; |
2282 | size_t saddr_len; | 2297 | size_t saddr_len; |
2283 | void * saddr = http_common_address_from_socket (plugin->protocol, addr, addrlen); | 2298 | void * saddr; |
2299 | |||
2300 | saddr = http_common_address_from_socket (plugin->protocol, | ||
2301 | addr, | ||
2302 | addrlen); | ||
2284 | if (NULL == saddr) | 2303 | if (NULL == saddr) |
2285 | return; | 2304 | return; |
2286 | saddr_len = http_common_address_get_size (saddr); | 2305 | saddr_len = http_common_address_get_size (saddr); |
2287 | 2306 | ||
2288 | while (NULL != w) | 2307 | while (NULL != w) |
2289 | { | 2308 | { |
2290 | if (GNUNET_YES == http_common_cmp_addresses(w->address, w->addrlen, saddr, saddr_len)) | 2309 | if (GNUNET_YES == |
2291 | break; | 2310 | http_common_cmp_addresses (w->address, |
2292 | w = w->next; | 2311 | w->addrlen, |
2312 | saddr, | ||
2313 | saddr_len)) | ||
2314 | break; | ||
2315 | w = w->next; | ||
2293 | } | 2316 | } |
2294 | GNUNET_free (saddr); | 2317 | GNUNET_free (saddr); |
2295 | 2318 | ||
@@ -2301,10 +2324,9 @@ server_remove_address (void *cls, int add_remove, const struct sockaddr *addr, | |||
2301 | http_common_plugin_address_to_string (plugin->protocol, | 2324 | http_common_plugin_address_to_string (plugin->protocol, |
2302 | w->address, | 2325 | w->address, |
2303 | w->addrlen)); | 2326 | w->addrlen)); |
2304 | 2327 | GNUNET_CONTAINER_DLL_remove (plugin->addr_head, | |
2305 | 2328 | plugin->addr_tail, | |
2306 | GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w); | 2329 | w); |
2307 | |||
2308 | /* modify our published address list */ | 2330 | /* modify our published address list */ |
2309 | #if BUILD_HTTPS | 2331 | #if BUILD_HTTPS |
2310 | address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, | 2332 | address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, |
@@ -2325,16 +2347,17 @@ server_remove_address (void *cls, int add_remove, const struct sockaddr *addr, | |||
2325 | * Our external IP address/port mapping has changed. | 2347 | * Our external IP address/port mapping has changed. |
2326 | * | 2348 | * |
2327 | * @param cls closure, the 'struct LocalAddrList' | 2349 | * @param cls closure, the 'struct LocalAddrList' |
2328 | * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean | 2350 | * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean |
2329 | * the previous (now invalid) one | 2351 | * the previous (now invalid) one |
2330 | * @param addr either the previous or the new public IP address | 2352 | * @param addr either the previous or the new public IP address |
2331 | * @param addrlen actual lenght of the address | 2353 | * @param addrlen actual lenght of the address |
2332 | */ | 2354 | */ |
2333 | static void | 2355 | static void |
2334 | server_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr, | 2356 | server_nat_port_map_callback (void *cls, |
2335 | socklen_t addrlen) | 2357 | int add_remove, |
2358 | const struct sockaddr *addr, | ||
2359 | socklen_t addrlen) | ||
2336 | { | 2360 | { |
2337 | GNUNET_assert (cls != NULL); | ||
2338 | struct HTTP_Server_Plugin *plugin = cls; | 2361 | struct HTTP_Server_Plugin *plugin = cls; |
2339 | 2362 | ||
2340 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2363 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -2403,7 +2426,8 @@ static int | |||
2403 | server_get_addresses (struct HTTP_Server_Plugin *plugin, | 2426 | server_get_addresses (struct HTTP_Server_Plugin *plugin, |
2404 | const char *service_name, | 2427 | const char *service_name, |
2405 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 2428 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
2406 | struct sockaddr ***addrs, socklen_t ** addr_lens) | 2429 | struct sockaddr ***addrs, |
2430 | socklen_t ** addr_lens) | ||
2407 | { | 2431 | { |
2408 | int disablev6; | 2432 | int disablev6; |
2409 | unsigned long long port; | 2433 | unsigned long long port; |
@@ -2591,7 +2615,8 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin) | |||
2591 | socklen_t *addrlens; | 2615 | socklen_t *addrlens; |
2592 | 2616 | ||
2593 | res = server_get_addresses (plugin, | 2617 | res = server_get_addresses (plugin, |
2594 | plugin->name, plugin->env->cfg, | 2618 | plugin->name, |
2619 | plugin->env->cfg, | ||
2595 | &addrs, &addrlens); | 2620 | &addrs, &addrlens); |
2596 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2621 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2597 | _("Found %u addresses to report to NAT service\n"), | 2622 | _("Found %u addresses to report to NAT service\n"), |
@@ -2604,7 +2629,9 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin) | |||
2604 | } | 2629 | } |
2605 | 2630 | ||
2606 | plugin->nat = | 2631 | plugin->nat = |
2607 | GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port, | 2632 | GNUNET_NAT_register (plugin->env->cfg, |
2633 | GNUNET_YES, | ||
2634 | plugin->port, | ||
2608 | (unsigned int) res, | 2635 | (unsigned int) res, |
2609 | (const struct sockaddr **) addrs, addrlens, | 2636 | (const struct sockaddr **) addrs, addrlens, |
2610 | &server_nat_port_map_callback, NULL, plugin); | 2637 | &server_nat_port_map_callback, NULL, plugin); |
@@ -2627,17 +2654,21 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin) | |||
2627 | static void | 2654 | static void |
2628 | server_stop_report_addresses (struct HTTP_Server_Plugin *plugin) | 2655 | server_stop_report_addresses (struct HTTP_Server_Plugin *plugin) |
2629 | { | 2656 | { |
2657 | struct HttpAddressWrapper *w; | ||
2658 | |||
2630 | /* Stop NAT handle */ | 2659 | /* Stop NAT handle */ |
2631 | if (NULL != plugin->nat) | 2660 | if (NULL != plugin->nat) |
2661 | { | ||
2632 | GNUNET_NAT_unregister (plugin->nat); | 2662 | GNUNET_NAT_unregister (plugin->nat); |
2633 | 2663 | plugin->nat = NULL; | |
2664 | } | ||
2634 | /* Clean up addresses */ | 2665 | /* Clean up addresses */ |
2635 | struct HttpAddressWrapper *w; | 2666 | while (NULL != plugin->addr_head) |
2636 | |||
2637 | while (plugin->addr_head != NULL) | ||
2638 | { | 2667 | { |
2639 | w = plugin->addr_head; | 2668 | w = plugin->addr_head; |
2640 | GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w); | 2669 | GNUNET_CONTAINER_DLL_remove (plugin->addr_head, |
2670 | plugin->addr_tail, | ||
2671 | w); | ||
2641 | GNUNET_free (w->address); | 2672 | GNUNET_free (w->address); |
2642 | GNUNET_free (w); | 2673 | GNUNET_free (w); |
2643 | } | 2674 | } |
@@ -2648,7 +2679,7 @@ server_stop_report_addresses (struct HTTP_Server_Plugin *plugin) | |||
2648 | * Check if IPv6 supported on this system | 2679 | * Check if IPv6 supported on this system |
2649 | * | 2680 | * |
2650 | * @param plugin the plugin handle | 2681 | * @param plugin the plugin handle |
2651 | * @return GNUNET_YES on success, else GNUNET_NO | 2682 | * @return #GNUNET_YES on success, else #GNUNET_NO |
2652 | */ | 2683 | */ |
2653 | static int | 2684 | static int |
2654 | server_check_ipv6_support (struct HTTP_Server_Plugin *plugin) | 2685 | server_check_ipv6_support (struct HTTP_Server_Plugin *plugin) |
@@ -2689,7 +2720,8 @@ server_check_ipv6_support (struct HTTP_Server_Plugin *plugin) | |||
2689 | * @param tc task context (unused) | 2720 | * @param tc task context (unused) |
2690 | */ | 2721 | */ |
2691 | static void | 2722 | static void |
2692 | server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 2723 | server_notify_external_hostname (void *cls, |
2724 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2693 | { | 2725 | { |
2694 | struct HTTP_Server_Plugin *plugin = cls; | 2726 | struct HTTP_Server_Plugin *plugin = cls; |
2695 | struct HttpAddress *ext_addr; | 2727 | struct HttpAddress *ext_addr; |
@@ -2737,7 +2769,7 @@ server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskCo | |||
2737 | * Configure the plugin | 2769 | * Configure the plugin |
2738 | * | 2770 | * |
2739 | * @param plugin plugin handle | 2771 | * @param plugin plugin handle |
2740 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | 2772 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure |
2741 | */ | 2773 | */ |
2742 | static int | 2774 | static int |
2743 | server_configure_plugin (struct HTTP_Server_Plugin *plugin) | 2775 | server_configure_plugin (struct HTTP_Server_Plugin *plugin) |
@@ -2754,7 +2786,8 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2754 | (plugin->env->cfg, plugin->name, "USE_IPv4")) | 2786 | (plugin->env->cfg, plugin->name, "USE_IPv4")) |
2755 | { | 2787 | { |
2756 | plugin->use_ipv4 = | 2788 | plugin->use_ipv4 = |
2757 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, | 2789 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, |
2790 | plugin->name, | ||
2758 | "USE_IPv4"); | 2791 | "USE_IPv4"); |
2759 | } | 2792 | } |
2760 | else | 2793 | else |
@@ -2768,7 +2801,8 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2768 | (plugin->env->cfg, plugin->name, "USE_IPv6")) | 2801 | (plugin->env->cfg, plugin->name, "USE_IPv6")) |
2769 | { | 2802 | { |
2770 | plugin->use_ipv6 = | 2803 | plugin->use_ipv6 = |
2771 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, | 2804 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, |
2805 | plugin->name, | ||
2772 | "USE_IPv6"); | 2806 | "USE_IPv6"); |
2773 | } | 2807 | } |
2774 | else | 2808 | else |
@@ -2786,7 +2820,8 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2786 | 2820 | ||
2787 | /* Reading port number from config file */ | 2821 | /* Reading port number from config file */ |
2788 | if ((GNUNET_OK != | 2822 | if ((GNUNET_OK != |
2789 | GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name, | 2823 | GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, |
2824 | plugin->name, | ||
2790 | "PORT", &port)) || (port > 65535)) | 2825 | "PORT", &port)) || (port > 65535)) |
2791 | { | 2826 | { |
2792 | LOG (GNUNET_ERROR_TYPE_ERROR, | 2827 | LOG (GNUNET_ERROR_TYPE_ERROR, |
@@ -2830,7 +2865,8 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2830 | 2865 | ||
2831 | if ((plugin->use_ipv6 == GNUNET_YES) && | 2866 | if ((plugin->use_ipv6 == GNUNET_YES) && |
2832 | (GNUNET_YES == | 2867 | (GNUNET_YES == |
2833 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, | 2868 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, |
2869 | plugin->name, | ||
2834 | "BINDTO6", &bind6_address))) | 2870 | "BINDTO6", &bind6_address))) |
2835 | { | 2871 | { |
2836 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2872 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -2861,84 +2897,99 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2861 | 2897 | ||
2862 | plugin->verify_external_hostname = GNUNET_NO; | 2898 | plugin->verify_external_hostname = GNUNET_NO; |
2863 | #if BUILD_HTTPS | 2899 | #if BUILD_HTTPS |
2864 | plugin->verify_external_hostname = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, | 2900 | plugin->verify_external_hostname = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, |
2901 | plugin->name, | ||
2865 | "VERIFY_EXTERNAL_HOSTNAME"); | 2902 | "VERIFY_EXTERNAL_HOSTNAME"); |
2866 | if (GNUNET_SYSERR == plugin->verify_external_hostname) | 2903 | if (GNUNET_SYSERR == plugin->verify_external_hostname) |
2867 | plugin->verify_external_hostname = GNUNET_NO; | 2904 | plugin->verify_external_hostname = GNUNET_NO; |
2868 | if (GNUNET_YES == plugin->verify_external_hostname) | 2905 | if (GNUNET_YES == plugin->verify_external_hostname) |
2869 | plugin->options |= HTTP_OPTIONS_VERIFY_CERTIFICATE; | 2906 | plugin->options |= HTTP_OPTIONS_VERIFY_CERTIFICATE; |
2870 | #endif | 2907 | #endif |
2871 | external_hostname_use_port = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, | 2908 | external_hostname_use_port = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, |
2909 | plugin->name, | ||
2872 | "EXTERNAL_HOSTNAME_USE_PORT"); | 2910 | "EXTERNAL_HOSTNAME_USE_PORT"); |
2873 | if (GNUNET_SYSERR == external_hostname_use_port) | 2911 | if (GNUNET_SYSERR == external_hostname_use_port) |
2874 | external_hostname_use_port = GNUNET_NO; | 2912 | external_hostname_use_port = GNUNET_NO; |
2875 | 2913 | ||
2876 | 2914 | ||
2877 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, | 2915 | if (GNUNET_YES == |
2878 | "EXTERNAL_HOSTNAME", &eh_tmp)) | 2916 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, |
2917 | plugin->name, | ||
2918 | "EXTERNAL_HOSTNAME", | ||
2919 | &eh_tmp)) | ||
2879 | { | 2920 | { |
2880 | char * tmp = NULL; | 2921 | char *tmp; |
2881 | char * pos = NULL; | 2922 | char *pos = NULL; |
2882 | char * pos_url = NULL; | 2923 | char *pos_url = NULL; |
2883 | 2924 | ||
2884 | if (NULL != strstr(eh_tmp, "://")) | 2925 | if (NULL != strstr(eh_tmp, "://")) |
2885 | { | 2926 | tmp = &strstr(eh_tmp, "://")[3]; |
2886 | tmp = &strstr(eh_tmp, "://")[3]; | 2927 | else |
2887 | } | 2928 | tmp = eh_tmp; |
2888 | else | ||
2889 | tmp = eh_tmp; | ||
2890 | 2929 | ||
2891 | if (GNUNET_YES == external_hostname_use_port) | 2930 | if (GNUNET_YES == external_hostname_use_port) |
2931 | { | ||
2932 | if ( (strlen (tmp) > 1) && (NULL != (pos = strchr(tmp, '/'))) ) | ||
2892 | { | 2933 | { |
2893 | if ( (strlen (tmp) > 1) && (NULL != (pos = strchr(tmp, '/'))) ) | 2934 | pos_url = pos + 1; |
2894 | { | 2935 | pos[0] = '\0'; |
2895 | pos_url = pos + 1; | 2936 | GNUNET_asprintf (&plugin->external_hostname, |
2896 | pos[0] = '\0'; | 2937 | "%s:%u/%s", |
2897 | GNUNET_asprintf (&plugin->external_hostname, "%s:%u/%s", tmp, (uint16_t) port, (NULL == pos_url) ? "" : pos_url); | 2938 | tmp, |
2898 | } | 2939 | (uint16_t) port, |
2899 | else | 2940 | (NULL == pos_url) ? "" : pos_url); |
2900 | GNUNET_asprintf (&plugin->external_hostname, "%s:%u", tmp, (uint16_t) port); | ||
2901 | } | 2941 | } |
2902 | else | 2942 | else |
2903 | plugin->external_hostname = GNUNET_strdup (tmp); | 2943 | GNUNET_asprintf (&plugin->external_hostname, |
2904 | GNUNET_free (eh_tmp); | 2944 | "%s:%u", |
2905 | 2945 | tmp, | |
2906 | LOG (GNUNET_ERROR_TYPE_INFO, | 2946 | (uint16_t) port); |
2907 | _("Using external hostname `%s'\n"), | 2947 | } |
2908 | plugin->external_hostname); | 2948 | else |
2909 | plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, plugin); | 2949 | plugin->external_hostname = GNUNET_strdup (tmp); |
2950 | GNUNET_free (eh_tmp); | ||
2910 | 2951 | ||
2911 | /* Use only configured external hostname */ | 2952 | LOG (GNUNET_ERROR_TYPE_INFO, |
2912 | if (GNUNET_CONFIGURATION_have_value | 2953 | _("Using external hostname `%s'\n"), |
2913 | (plugin->env->cfg, plugin->name, "EXTERNAL_HOSTNAME_ONLY")) | 2954 | plugin->external_hostname); |
2914 | { | 2955 | plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, |
2915 | plugin->external_only = | 2956 | plugin); |
2916 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, | 2957 | |
2917 | "EXTERNAL_HOSTNAME_ONLY"); | 2958 | /* Use only configured external hostname */ |
2918 | } | 2959 | if (GNUNET_CONFIGURATION_have_value |
2919 | else | 2960 | (plugin->env->cfg, |
2920 | plugin->external_only = GNUNET_NO; | 2961 | plugin->name, |
2962 | "EXTERNAL_HOSTNAME_ONLY")) | ||
2963 | { | ||
2964 | plugin->external_only = | ||
2965 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, | ||
2966 | plugin->name, | ||
2967 | "EXTERNAL_HOSTNAME_ONLY"); | ||
2968 | } | ||
2969 | else | ||
2970 | plugin->external_only = GNUNET_NO; | ||
2921 | 2971 | ||
2922 | if (GNUNET_YES == plugin->external_only) | 2972 | if (GNUNET_YES == plugin->external_only) |
2923 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2973 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2924 | _("Notifying transport only about hostname `%s'\n"), | 2974 | _("Notifying transport only about hostname `%s'\n"), |
2925 | plugin->external_hostname); | 2975 | plugin->external_hostname); |
2926 | } | 2976 | } |
2927 | else | 2977 | else |
2928 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2978 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2929 | "No external hostname configured\n"); | 2979 | "No external hostname configured\n"); |
2930 | 2980 | ||
2931 | /* Optional parameters */ | 2981 | /* Optional parameters */ |
2932 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, | 2982 | if (GNUNET_OK != |
2933 | plugin->name, | 2983 | GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, |
2934 | "MAX_CONNECTIONS", &max_connections)) | 2984 | plugin->name, |
2985 | "MAX_CONNECTIONS", | ||
2986 | &max_connections)) | ||
2935 | max_connections = 128; | 2987 | max_connections = 128; |
2936 | plugin->max_connections = max_connections; | 2988 | plugin->max_connections = max_connections; |
2937 | 2989 | ||
2938 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2990 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2939 | _("Maximum number of connections is %u\n"), | 2991 | _("Maximum number of connections is %u\n"), |
2940 | plugin->max_connections); | 2992 | plugin->max_connections); |
2941 | |||
2942 | 2993 | ||
2943 | plugin->peer_id_length = strlen (GNUNET_i2s_full (plugin->env->my_identity)); | 2994 | plugin->peer_id_length = strlen (GNUNET_i2s_full (plugin->env->my_identity)); |
2944 | 2995 | ||
@@ -2947,74 +2998,6 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin) | |||
2947 | 2998 | ||
2948 | 2999 | ||
2949 | /** | 3000 | /** |
2950 | * Session was idle, so disconnect it | ||
2951 | * | ||
2952 | * @param cls the session | ||
2953 | * @param tc task context | ||
2954 | */ | ||
2955 | static void | ||
2956 | server_session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2957 | { | ||
2958 | struct Session *s = cls; | ||
2959 | |||
2960 | s->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
2961 | GNUNET_log (TIMEOUT_LOG, | ||
2962 | "Session %p was idle for %s, disconnecting\n", | ||
2963 | s, | ||
2964 | GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, | ||
2965 | GNUNET_YES)); | ||
2966 | |||
2967 | /* call session destroy function */ | ||
2968 | GNUNET_assert (GNUNET_OK == | ||
2969 | http_server_plugin_disconnect_session (s->plugin, s)); | ||
2970 | } | ||
2971 | |||
2972 | |||
2973 | /** | ||
2974 | * Start session timeout for session s | ||
2975 | * | ||
2976 | * @param s the session | ||
2977 | */ | ||
2978 | static void | ||
2979 | server_start_session_timeout (struct Session *s) | ||
2980 | { | ||
2981 | GNUNET_assert (NULL != s); | ||
2982 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task); | ||
2983 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, | ||
2984 | &server_session_timeout, | ||
2985 | s); | ||
2986 | GNUNET_log (TIMEOUT_LOG, | ||
2987 | "Timeout for session %p set to %s\n", | ||
2988 | s, | ||
2989 | GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, | ||
2990 | GNUNET_YES)); | ||
2991 | } | ||
2992 | |||
2993 | |||
2994 | /** | ||
2995 | * Increment session timeout due to activity session s | ||
2996 | * | ||
2997 | * @param s the session | ||
2998 | */ | ||
2999 | static void | ||
3000 | server_reschedule_session_timeout (struct Session *s) | ||
3001 | { | ||
3002 | GNUNET_assert (NULL != s); | ||
3003 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); | ||
3004 | |||
3005 | GNUNET_SCHEDULER_cancel (s->timeout_task); | ||
3006 | s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, | ||
3007 | &server_session_timeout, | ||
3008 | s); | ||
3009 | GNUNET_log (TIMEOUT_LOG, | ||
3010 | "Timeout rescheduled for session %p set to %s\n", | ||
3011 | s, | ||
3012 | GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, | ||
3013 | GNUNET_YES)); | ||
3014 | } | ||
3015 | |||
3016 | |||
3017 | /** | ||
3018 | * Exit point from the plugin. | 3001 | * Exit point from the plugin. |
3019 | * | 3002 | * |
3020 | * @param cls api | 3003 | * @param cls api |
@@ -3025,8 +3008,6 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) | |||
3025 | { | 3008 | { |
3026 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | 3009 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; |
3027 | struct HTTP_Server_Plugin *plugin = api->cls; | 3010 | struct HTTP_Server_Plugin *plugin = api->cls; |
3028 | struct Session *pos; | ||
3029 | struct Session *next; | ||
3030 | 3011 | ||
3031 | if (NULL == api->cls) | 3012 | if (NULL == api->cls) |
3032 | { | 3013 | { |
@@ -3068,29 +3049,17 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) | |||
3068 | /* Stop to report addresses to transport service */ | 3049 | /* Stop to report addresses to transport service */ |
3069 | server_stop_report_addresses (plugin); | 3050 | server_stop_report_addresses (plugin); |
3070 | server_stop (plugin); | 3051 | server_stop (plugin); |
3071 | next = plugin->head; | 3052 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, |
3072 | while (NULL != (pos = next)) | 3053 | &destroy_session_cb, |
3073 | { | 3054 | plugin); |
3074 | next = pos->next; | 3055 | GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); |
3075 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3056 | plugin->sessions = NULL; |
3076 | "Removing left over session %p\n", | ||
3077 | pos); | ||
3078 | |||
3079 | if ((GNUNET_YES == pos->session_passed) && (GNUNET_NO == pos->session_ended)) | ||
3080 | { | ||
3081 | /* Notify transport immediately that this session is invalid */ | ||
3082 | pos->session_ended = GNUNET_YES; | ||
3083 | plugin->env->session_end (plugin->env->cls, pos->address, pos); | ||
3084 | } | ||
3085 | server_delete_session (plugin, pos); | ||
3086 | } | ||
3087 | |||
3088 | /* Clean up */ | 3057 | /* Clean up */ |
3089 | GNUNET_free_non_null (plugin->external_hostname); | 3058 | GNUNET_free_non_null (plugin->external_hostname); |
3090 | GNUNET_free_non_null (plugin->ext_addr); | 3059 | GNUNET_free_non_null (plugin->ext_addr); |
3091 | GNUNET_free_non_null (plugin->server_addr_v4); | 3060 | GNUNET_free_non_null (plugin->server_addr_v4); |
3092 | GNUNET_free_non_null (plugin->server_addr_v6); | 3061 | GNUNET_free_non_null (plugin->server_addr_v6); |
3093 | regfree(&plugin->url_regex); | 3062 | regfree (&plugin->url_regex); |
3094 | 3063 | ||
3095 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3064 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3096 | _("Shutdown for plugin `%s' complete\n"), | 3065 | _("Shutdown for plugin `%s' complete\n"), |
@@ -3136,12 +3105,67 @@ static enum GNUNET_ATS_Network_Type | |||
3136 | http_server_get_network (void *cls, | 3105 | http_server_get_network (void *cls, |
3137 | struct Session *session) | 3106 | struct Session *session) |
3138 | { | 3107 | { |
3139 | GNUNET_assert (NULL != session); | ||
3140 | return ntohl (session->ats_address_network_type); | 3108 | return ntohl (session->ats_address_network_type); |
3141 | } | 3109 | } |
3142 | 3110 | ||
3143 | 3111 | ||
3144 | /** | 3112 | /** |
3113 | * Return information about the given session to the | ||
3114 | * monitor callback. | ||
3115 | * | ||
3116 | * @param cls the `struct Plugin` with the monitor callback (`sic`) | ||
3117 | * @param peer peer we send information about | ||
3118 | * @param value our `struct Session` to send information about | ||
3119 | * @return #GNUNET_OK (continue to iterate) | ||
3120 | */ | ||
3121 | static int | ||
3122 | send_session_info_iter (void *cls, | ||
3123 | const struct GNUNET_PeerIdentity *peer, | ||
3124 | void *value) | ||
3125 | { | ||
3126 | struct HTTP_Server_Plugin *plugin = cls; | ||
3127 | struct Session *session = value; | ||
3128 | |||
3129 | notify_session_monitor (plugin, | ||
3130 | session, | ||
3131 | GNUNET_TRANSPORT_SS_UP); | ||
3132 | return GNUNET_OK; | ||
3133 | } | ||
3134 | |||
3135 | |||
3136 | /** | ||
3137 | * Begin monitoring sessions of a plugin. There can only | ||
3138 | * be one active monitor per plugin (i.e. if there are | ||
3139 | * multiple monitors, the transport service needs to | ||
3140 | * multiplex the generated events over all of them). | ||
3141 | * | ||
3142 | * @param cls closure of the plugin | ||
3143 | * @param sic callback to invoke, NULL to disable monitor; | ||
3144 | * plugin will being by iterating over all active | ||
3145 | * sessions immediately and then enter monitor mode | ||
3146 | * @param sic_cls closure for @a sic | ||
3147 | */ | ||
3148 | static void | ||
3149 | http_server_plugin_setup_monitor (void *cls, | ||
3150 | GNUNET_TRANSPORT_SessionInfoCallback sic, | ||
3151 | void *sic_cls) | ||
3152 | { | ||
3153 | struct HTTP_Server_Plugin *plugin = cls; | ||
3154 | |||
3155 | plugin->sic = sic; | ||
3156 | plugin->sic_cls = sic_cls; | ||
3157 | if (NULL != sic) | ||
3158 | { | ||
3159 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, | ||
3160 | &send_session_info_iter, | ||
3161 | plugin); | ||
3162 | /* signal end of first iteration */ | ||
3163 | sic (sic_cls, NULL, NULL); | ||
3164 | } | ||
3165 | } | ||
3166 | |||
3167 | |||
3168 | /** | ||
3145 | * Entry point for the plugin. | 3169 | * Entry point for the plugin. |
3146 | * | 3170 | * |
3147 | * @param cls env | 3171 | * @param cls env |
@@ -3167,6 +3191,8 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) | |||
3167 | } | 3191 | } |
3168 | plugin = GNUNET_new (struct HTTP_Server_Plugin); | 3192 | plugin = GNUNET_new (struct HTTP_Server_Plugin); |
3169 | plugin->env = env; | 3193 | plugin->env = env; |
3194 | plugin->sessions = GNUNET_CONTAINER_multipeermap_create (128, | ||
3195 | GNUNET_YES); | ||
3170 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); | 3196 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); |
3171 | api->cls = plugin; | 3197 | api->cls = plugin; |
3172 | api->send = &http_server_plugin_send; | 3198 | api->send = &http_server_plugin_send; |
@@ -3181,6 +3207,8 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) | |||
3181 | api->address_pretty_printer = &http_common_plugin_address_pretty_printer; | 3207 | api->address_pretty_printer = &http_common_plugin_address_pretty_printer; |
3182 | api->get_network = &http_server_get_network; | 3208 | api->get_network = &http_server_get_network; |
3183 | api->update_session_timeout = &http_server_plugin_update_session_timeout; | 3209 | api->update_session_timeout = &http_server_plugin_update_session_timeout; |
3210 | // api->update_inbound_delay = &http_server_plugin_update_inbound_delay; // FIXME: implement/support! | ||
3211 | api->setup_monitor = &http_server_plugin_setup_monitor; | ||
3184 | #if BUILD_HTTPS | 3212 | #if BUILD_HTTPS |
3185 | plugin->name = "transport-https_server"; | 3213 | plugin->name = "transport-https_server"; |
3186 | plugin->protocol = "https"; | 3214 | plugin->protocol = "https"; |
diff --git a/src/transport/test_transport_api_http_reverse_peer1.conf b/src/transport/test_transport_api_http_reverse_peer1.conf index 351b29746..aebaf88e2 100644 --- a/src/transport/test_transport_api_http_reverse_peer1.conf +++ b/src/transport/test_transport_api_http_reverse_peer1.conf | |||
@@ -1,4 +1,4 @@ | |||
1 | INLINE@ template_cfg_peer1.conf | 1 | @INLINE@ template_cfg_peer1.conf |
2 | [PATHS] | 2 | [PATHS] |
3 | GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ | 3 | GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ |
4 | 4 | ||
diff --git a/src/transport/test_transport_api_http_reverse_peer2.conf b/src/transport/test_transport_api_http_reverse_peer2.conf index 0283d12b5..210e44a02 100644 --- a/src/transport/test_transport_api_http_reverse_peer2.conf +++ b/src/transport/test_transport_api_http_reverse_peer2.conf | |||
@@ -1,4 +1,4 @@ | |||
1 | INLINE@ template_cfg_peer2.conf | 1 | @INLINE@ template_cfg_peer2.conf |
2 | [PATHS] | 2 | [PATHS] |
3 | GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ | 3 | GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ |
4 | 4 | ||
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c index b2af478e1..d25d3f4b7 100644 --- a/src/transport/transport-testing.c +++ b/src/transport/transport-testing.c | |||
@@ -259,8 +259,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth | |||
259 | 259 | ||
260 | /* Create configuration and call testing lib to modify it */ | 260 | /* Create configuration and call testing lib to modify it */ |
261 | p->cfg = GNUNET_CONFIGURATION_create (); | 261 | p->cfg = GNUNET_CONFIGURATION_create (); |
262 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); | 262 | GNUNET_assert (GNUNET_OK == |
263 | 263 | GNUNET_CONFIGURATION_load (p->cfg, cfgname)); | |
264 | if (GNUNET_SYSERR == GNUNET_TESTING_configuration_create (tth->tl_system, p->cfg)) | 264 | if (GNUNET_SYSERR == GNUNET_TESTING_configuration_create (tth->tl_system, p->cfg)) |
265 | { | 265 | { |
266 | LOG (GNUNET_ERROR_TYPE_ERROR, | 266 | LOG (GNUNET_ERROR_TYPE_ERROR, |
diff --git a/src/transport/transport.conf.in b/src/transport/transport.conf.in index 20a878c2e..845c4d384 100644 --- a/src/transport/transport.conf.in +++ b/src/transport/transport.conf.in | |||
@@ -68,11 +68,11 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM; | |||
68 | # PROXY = | 68 | # PROXY = |
69 | 69 | ||
70 | # User name for proxy server | 70 | # User name for proxy server |
71 | # PROXY_USERNAME = | 71 | # PROXY_USERNAME = |
72 | # User password for proxy server | 72 | # User password for proxy server |
73 | # PROXY_PASSWORD = | 73 | # PROXY_PASSWORD = |
74 | 74 | ||
75 | # Type of proxy server, | 75 | # Type of proxy server, |
76 | # Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME | 76 | # Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME |
77 | # Default: HTTP | 77 | # Default: HTTP |
78 | # PROXY_TYPE = HTTP | 78 | # PROXY_TYPE = HTTP |
@@ -95,11 +95,11 @@ TESTING_IGNORE_KEYS = ACCEPT_FROM; | |||
95 | # PROXY = | 95 | # PROXY = |
96 | 96 | ||
97 | # User name for proxy server | 97 | # User name for proxy server |
98 | # PROXY_USERNAME = | 98 | # PROXY_USERNAME = |
99 | # User password for proxy server | 99 | # User password for proxy server |
100 | # PROXY_PASSWORD = | 100 | # PROXY_PASSWORD = |
101 | 101 | ||
102 | # Type of proxy server, | 102 | # Type of proxy server, |
103 | # Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME | 103 | # Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME |
104 | # Default: HTTP | 104 | # Default: HTTP |
105 | # PROXY_TYPE = HTTP | 105 | # PROXY_TYPE = HTTP |