diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-09-18 20:43:47 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-09-18 20:43:47 +0000 |
commit | af6f9ae173e641a15639b59238bd5e86113a9113 (patch) | |
tree | 2b58c7c7a89cc2406a1efd44f7aa5c6b2eaa4e85 /src/util | |
parent | c1ef5b83f7c31c7d6db19d1eb3fa0d1fcef2d595 (diff) | |
download | gnunet-af6f9ae173e641a15639b59238bd5e86113a9113.tar.gz gnunet-af6f9ae173e641a15639b59238bd5e86113a9113.zip |
more work on new MST and service logic
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/mst.c | 67 | ||||
-rw-r--r-- | src/util/service_new.c | 318 |
2 files changed, 278 insertions, 107 deletions
diff --git a/src/util/mst.c b/src/util/mst.c index 578ba8e04..82a21b880 100644 --- a/src/util/mst.c +++ b/src/util/mst.c | |||
@@ -144,15 +144,20 @@ do_align: | |||
144 | { | 144 | { |
145 | /* need to align or need more space */ | 145 | /* need to align or need more space */ |
146 | mst->pos -= mst->off; | 146 | mst->pos -= mst->off; |
147 | memmove (ibuf, &ibuf[mst->off], mst->pos); | 147 | memmove (ibuf, |
148 | &ibuf[mst->off], | ||
149 | mst->pos); | ||
148 | mst->off = 0; | 150 | mst->off = 0; |
149 | } | 151 | } |
150 | if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) | 152 | if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) |
151 | { | 153 | { |
152 | delta = | 154 | delta |
153 | GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - | 155 | = GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) |
154 | (mst->pos - mst->off), size); | 156 | - (mst->pos - mst->off), |
155 | GNUNET_memcpy (&ibuf[mst->pos], buf, delta); | 157 | size); |
158 | GNUNET_memcpy (&ibuf[mst->pos], | ||
159 | buf, | ||
160 | delta); | ||
156 | mst->pos += delta; | 161 | mst->pos += delta; |
157 | buf += delta; | 162 | buf += delta; |
158 | size -= delta; | 163 | size -= delta; |
@@ -178,23 +183,29 @@ do_align: | |||
178 | { | 183 | { |
179 | /* can get more space by moving */ | 184 | /* can get more space by moving */ |
180 | mst->pos -= mst->off; | 185 | mst->pos -= mst->off; |
181 | memmove (ibuf, &ibuf[mst->off], mst->pos); | 186 | memmove (ibuf, |
187 | &ibuf[mst->off], | ||
188 | mst->pos); | ||
182 | mst->off = 0; | 189 | mst->off = 0; |
183 | } | 190 | } |
184 | if (mst->curr_buf < want) | 191 | if (mst->curr_buf < want) |
185 | { | 192 | { |
186 | /* need to get more space by growing buffer */ | 193 | /* need to get more space by growing buffer */ |
187 | GNUNET_assert (0 == mst->off); | 194 | GNUNET_assert (0 == mst->off); |
188 | mst->hdr = GNUNET_realloc (mst->hdr, want); | 195 | mst->hdr = GNUNET_realloc (mst->hdr, |
196 | want); | ||
189 | ibuf = (char *) mst->hdr; | 197 | ibuf = (char *) mst->hdr; |
190 | mst->curr_buf = want; | 198 | mst->curr_buf = want; |
191 | } | 199 | } |
192 | hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; | 200 | hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; |
193 | if (mst->pos - mst->off < want) | 201 | if (mst->pos - mst->off < want) |
194 | { | 202 | { |
195 | delta = GNUNET_MIN (want - (mst->pos - mst->off), size); | 203 | delta = GNUNET_MIN (want - (mst->pos - mst->off), |
204 | size); | ||
196 | GNUNET_assert (mst->pos + delta <= mst->curr_buf); | 205 | GNUNET_assert (mst->pos + delta <= mst->curr_buf); |
197 | GNUNET_memcpy (&ibuf[mst->pos], buf, delta); | 206 | GNUNET_memcpy (&ibuf[mst->pos], |
207 | buf, | ||
208 | delta); | ||
198 | mst->pos += delta; | 209 | mst->pos += delta; |
199 | buf += delta; | 210 | buf += delta; |
200 | size -= delta; | 211 | size -= delta; |
@@ -278,12 +289,15 @@ copy: | |||
278 | { | 289 | { |
279 | if (size + mst->pos > mst->curr_buf) | 290 | if (size + mst->pos > mst->curr_buf) |
280 | { | 291 | { |
281 | mst->hdr = GNUNET_realloc (mst->hdr, size + mst->pos); | 292 | mst->hdr = GNUNET_realloc (mst->hdr, |
293 | size + mst->pos); | ||
282 | ibuf = (char *) mst->hdr; | 294 | ibuf = (char *) mst->hdr; |
283 | mst->curr_buf = size + mst->pos; | 295 | mst->curr_buf = size + mst->pos; |
284 | } | 296 | } |
285 | GNUNET_assert (size + mst->pos <= mst->curr_buf); | 297 | GNUNET_assert (size + mst->pos <= mst->curr_buf); |
286 | GNUNET_memcpy (&ibuf[mst->pos], buf, size); | 298 | GNUNET_memcpy (&ibuf[mst->pos], |
299 | buf, | ||
300 | size); | ||
287 | mst->pos += size; | 301 | mst->pos += size; |
288 | } | 302 | } |
289 | if (purge) | 303 | if (purge) |
@@ -318,8 +332,35 @@ GNUNET_MST_read (struct GNUNET_MessageStreamTokenizer *mst, | |||
318 | int purge, | 332 | int purge, |
319 | int one_shot) | 333 | int one_shot) |
320 | { | 334 | { |
321 | GNUNET_assert (0); // not implemented | 335 | ssize_t ret; |
322 | return GNUNET_SYSERR; | 336 | size_t left; |
337 | char *buf; | ||
338 | |||
339 | left = mst->curr_buf - mst->pos; | ||
340 | buf = (char *) mst->hdr; | ||
341 | ret = GNUNET_NETWORK_socket_recv (sock, | ||
342 | &buf[mst->pos], | ||
343 | left); | ||
344 | if (-1 == ret) | ||
345 | { | ||
346 | if ( (EAGAIN == errno) || | ||
347 | (EINTR == errno) ) | ||
348 | return GNUNET_OK; | ||
349 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, | ||
350 | "recv"); | ||
351 | return GNUNET_SYSERR; | ||
352 | } | ||
353 | if (0 == ret) | ||
354 | { | ||
355 | /* other side closed connection, treat as error */ | ||
356 | return GNUNET_SYSERR; | ||
357 | } | ||
358 | mst->pos += ret; | ||
359 | return GNUNET_MST_from_buffer (mst, | ||
360 | NULL, | ||
361 | 0, | ||
362 | purge, | ||
363 | one_shot); | ||
323 | } | 364 | } |
324 | 365 | ||
325 | 366 | ||
diff --git a/src/util/service_new.c b/src/util/service_new.c index 6d17720fd..30fb88f7d 100644 --- a/src/util/service_new.c +++ b/src/util/service_new.c | |||
@@ -205,9 +205,8 @@ struct GNUNET_SERVICE_Handle | |||
205 | int ret; | 205 | int ret; |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * If GNUNET_YES, consider unknown message types an error where the | 208 | * If #GNUNET_YES, consider unknown message types an error where the |
209 | * client is disconnected. | 209 | * client is disconnected. |
210 | * FIXME: remove? | ||
211 | */ | 210 | */ |
212 | int require_found; | 211 | int require_found; |
213 | }; | 212 | }; |
@@ -247,7 +246,7 @@ struct GNUNET_SERVICE_Client | |||
247 | /** | 246 | /** |
248 | * Tokenizer we use for processing incoming data. | 247 | * Tokenizer we use for processing incoming data. |
249 | */ | 248 | */ |
250 | struct GNUNET_SERVER_MessageStreamTokenizer *mst; | 249 | struct GNUNET_MessageStreamTokenizer *mst; |
251 | 250 | ||
252 | /** | 251 | /** |
253 | * Task that warns about missing calls to | 252 | * Task that warns about missing calls to |
@@ -273,6 +272,12 @@ struct GNUNET_SERVICE_Client | |||
273 | void *user_context; | 272 | void *user_context; |
274 | 273 | ||
275 | /** | 274 | /** |
275 | * Time when we last gave a message from this client | ||
276 | * to the application. | ||
277 | */ | ||
278 | struct GNUNET_TIME_Absolute warn_start; | ||
279 | |||
280 | /** | ||
276 | * Persist the file handle for this client no matter what happens, | 281 | * Persist the file handle for this client no matter what happens, |
277 | * force the OS to close once the process actually dies. Should only | 282 | * force the OS to close once the process actually dies. Should only |
278 | * be used in special cases! | 283 | * be used in special cases! |
@@ -287,6 +292,11 @@ struct GNUNET_SERVICE_Client | |||
287 | int is_monitor; | 292 | int is_monitor; |
288 | 293 | ||
289 | /** | 294 | /** |
295 | * Are we waiting for the application to call #GNUNET_SERVICE_client_continue()? | ||
296 | */ | ||
297 | int needs_continue; | ||
298 | |||
299 | /** | ||
290 | * Type of last message processed (for warn_no_receive_done). | 300 | * Type of last message processed (for warn_no_receive_done). |
291 | */ | 301 | */ |
292 | uint16_t warn_type; | 302 | uint16_t warn_type; |
@@ -386,7 +396,9 @@ process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, | |||
386 | { | 396 | { |
387 | char *opt; | 397 | char *opt; |
388 | 398 | ||
389 | if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option)) | 399 | if (! GNUNET_CONFIGURATION_have_value (sh->cfg, |
400 | sh->service_name, | ||
401 | option)) | ||
390 | { | 402 | { |
391 | *ret = NULL; | 403 | *ret = NULL; |
392 | return GNUNET_OK; | 404 | return GNUNET_OK; |
@@ -394,7 +406,8 @@ process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, | |||
394 | GNUNET_break (GNUNET_OK == | 406 | GNUNET_break (GNUNET_OK == |
395 | GNUNET_CONFIGURATION_get_value_string (sh->cfg, | 407 | GNUNET_CONFIGURATION_get_value_string (sh->cfg, |
396 | sh->service_name, | 408 | sh->service_name, |
397 | option, &opt)); | 409 | option, |
410 | &opt)); | ||
398 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt))) | 411 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt))) |
399 | { | 412 | { |
400 | LOG (GNUNET_ERROR_TYPE_WARNING, | 413 | LOG (GNUNET_ERROR_TYPE_WARNING, |
@@ -426,7 +439,9 @@ process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, | |||
426 | { | 439 | { |
427 | char *opt; | 440 | char *opt; |
428 | 441 | ||
429 | if (!GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option)) | 442 | if (! GNUNET_CONFIGURATION_have_value (sh->cfg, |
443 | sh->service_name, | ||
444 | option)) | ||
430 | { | 445 | { |
431 | *ret = NULL; | 446 | *ret = NULL; |
432 | return GNUNET_OK; | 447 | return GNUNET_OK; |
@@ -434,12 +449,15 @@ process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, | |||
434 | GNUNET_break (GNUNET_OK == | 449 | GNUNET_break (GNUNET_OK == |
435 | GNUNET_CONFIGURATION_get_value_string (sh->cfg, | 450 | GNUNET_CONFIGURATION_get_value_string (sh->cfg, |
436 | sh->service_name, | 451 | sh->service_name, |
437 | option, &opt)); | 452 | option, |
453 | &opt)); | ||
438 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt))) | 454 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt))) |
439 | { | 455 | { |
440 | LOG (GNUNET_ERROR_TYPE_WARNING, | 456 | LOG (GNUNET_ERROR_TYPE_WARNING, |
441 | _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), | 457 | _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), |
442 | opt, sh->service_name, option); | 458 | opt, |
459 | sh->service_name, | ||
460 | option); | ||
443 | GNUNET_free (opt); | 461 | GNUNET_free (opt); |
444 | return GNUNET_SYSERR; | 462 | return GNUNET_SYSERR; |
445 | } | 463 | } |
@@ -469,7 +487,9 @@ add_unixpath (struct sockaddr **saddrs, | |||
469 | 487 | ||
470 | un = GNUNET_new (struct sockaddr_un); | 488 | un = GNUNET_new (struct sockaddr_un); |
471 | un->sun_family = AF_UNIX; | 489 | un->sun_family = AF_UNIX; |
472 | strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1); | 490 | strncpy (un->sun_path, |
491 | unixpath, | ||
492 | sizeof (un->sun_path) - 1); | ||
473 | #ifdef LINUX | 493 | #ifdef LINUX |
474 | if (GNUNET_YES == abstract) | 494 | if (GNUNET_YES == abstract) |
475 | un->sun_path[0] = '\0'; | 495 | un->sun_path[0] = '\0'; |
@@ -554,10 +574,10 @@ get_server_addresses (const char *service_name, | |||
554 | 0); | 574 | 0); |
555 | if (NULL == desc) | 575 | if (NULL == desc) |
556 | { | 576 | { |
557 | if ((ENOBUFS == errno) || | 577 | if ( (ENOBUFS == errno) || |
558 | (ENOMEM == errno) || | 578 | (ENOMEM == errno) || |
559 | (ENFILE == errno) || | 579 | (ENFILE == errno) || |
560 | (EACCES == errno)) | 580 | (EACCES == errno) ) |
561 | { | 581 | { |
562 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, | 582 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, |
563 | "socket"); | 583 | "socket"); |
@@ -571,7 +591,8 @@ get_server_addresses (const char *service_name, | |||
571 | } | 591 | } |
572 | else | 592 | else |
573 | { | 593 | { |
574 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); | 594 | GNUNET_break (GNUNET_OK == |
595 | GNUNET_NETWORK_socket_close (desc)); | ||
575 | desc = NULL; | 596 | desc = NULL; |
576 | } | 597 | } |
577 | } | 598 | } |
@@ -648,9 +669,9 @@ get_server_addresses (const char *service_name, | |||
648 | if (GNUNET_SYSERR == abstract) | 669 | if (GNUNET_SYSERR == abstract) |
649 | abstract = GNUNET_NO; | 670 | abstract = GNUNET_NO; |
650 | #endif | 671 | #endif |
651 | if ((GNUNET_YES != abstract) | 672 | if ( (GNUNET_YES != abstract) && |
652 | && (GNUNET_OK != | 673 | (GNUNET_OK != |
653 | GNUNET_DISK_directory_create_for_file (unixpath))) | 674 | GNUNET_DISK_directory_create_for_file (unixpath)) ) |
654 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | 675 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, |
655 | "mkdir", | 676 | "mkdir", |
656 | unixpath); | 677 | unixpath); |
@@ -682,7 +703,8 @@ get_server_addresses (const char *service_name, | |||
682 | } | 703 | } |
683 | else | 704 | else |
684 | { | 705 | { |
685 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); | 706 | GNUNET_break (GNUNET_OK == |
707 | GNUNET_NETWORK_socket_close (desc)); | ||
686 | desc = NULL; | 708 | desc = NULL; |
687 | } | 709 | } |
688 | } | 710 | } |
@@ -994,7 +1016,8 @@ receive_sockets_from_parent (struct GNUNET_SERVICE_Handle *sh) | |||
994 | LOG (GNUNET_ERROR_TYPE_ERROR, | 1016 | LOG (GNUNET_ERROR_TYPE_ERROR, |
995 | _("Could not access a pre-bound socket, will try to bind myself\n")); | 1017 | _("Could not access a pre-bound socket, will try to bind myself\n")); |
996 | for (i = 0; (i < count) && (NULL != lsocks[i]); i++) | 1018 | for (i = 0; (i < count) && (NULL != lsocks[i]); i++) |
997 | GNUNET_break (0 == GNUNET_NETWORK_socket_close (lsocks[i])); | 1019 | GNUNET_break (GNUNET_OK == |
1020 | GNUNET_NETWORK_socket_close (lsocks[i])); | ||
998 | GNUNET_free (lsocks); | 1021 | GNUNET_free (lsocks); |
999 | return NULL; | 1022 | return NULL; |
1000 | } | 1023 | } |
@@ -1081,7 +1104,8 @@ open_listen_socket (const struct sockaddr *server_addr, | |||
1081 | GNUNET_a2s (server_addr, socklen)); | 1104 | GNUNET_a2s (server_addr, socklen)); |
1082 | } | 1105 | } |
1083 | } | 1106 | } |
1084 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | 1107 | GNUNET_break (GNUNET_OK == |
1108 | GNUNET_NETWORK_socket_close (sock)); | ||
1085 | errno = eno; | 1109 | errno = eno; |
1086 | return NULL; | 1110 | return NULL; |
1087 | } | 1111 | } |
@@ -1090,7 +1114,8 @@ open_listen_socket (const struct sockaddr *server_addr, | |||
1090 | { | 1114 | { |
1091 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, | 1115 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, |
1092 | "listen"); | 1116 | "listen"); |
1093 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | 1117 | GNUNET_break (GNUNET_OK == |
1118 | GNUNET_NETWORK_socket_close (sock)); | ||
1094 | errno = 0; | 1119 | errno = 0; |
1095 | return NULL; | 1120 | return NULL; |
1096 | } | 1121 | } |
@@ -1177,7 +1202,8 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) | |||
1177 | (unsigned int) 3 + cnt); | 1202 | (unsigned int) 3 + cnt); |
1178 | cnt++; | 1203 | cnt++; |
1179 | while (NULL != lsocks[cnt]) | 1204 | while (NULL != lsocks[cnt]) |
1180 | GNUNET_break (0 == GNUNET_NETWORK_socket_close (lsocks[cnt++])); | 1205 | GNUNET_break (GNUNET_OK == |
1206 | GNUNET_NETWORK_socket_close (lsocks[cnt++])); | ||
1181 | GNUNET_free (lsocks); | 1207 | GNUNET_free (lsocks); |
1182 | lsocks = NULL; | 1208 | lsocks = NULL; |
1183 | break; | 1209 | break; |
@@ -1694,7 +1720,10 @@ shutdown: | |||
1694 | struct ServiceListenContext *slc = sh.slc_head; | 1720 | struct ServiceListenContext *slc = sh.slc_head; |
1695 | 1721 | ||
1696 | sh.slc_head = slc->next; | 1722 | sh.slc_head = slc->next; |
1697 | // FIXME: destroy slc | 1723 | if (NULL != slc->listen_task) |
1724 | GNUNET_SCHEDULER_cancel (slc->listen_task); | ||
1725 | GNUNET_break (GNUNET_OK == | ||
1726 | GNUNET_NETWORK_socket_close (slc->listen_socket)); | ||
1698 | GNUNET_free (slc); | 1727 | GNUNET_free (slc); |
1699 | } | 1728 | } |
1700 | 1729 | ||
@@ -1778,7 +1807,7 @@ service_mq_cancel (struct GNUNET_MQ_Handle *mq, | |||
1778 | * the message queue. | 1807 | * the message queue. |
1779 | * Not every message queue implementation supports an error handler. | 1808 | * Not every message queue implementation supports an error handler. |
1780 | * | 1809 | * |
1781 | * @param cls closure | 1810 | * @param cls closure with our `struct GNUNET_SERVICE_Client` |
1782 | * @param error error code | 1811 | * @param error error code |
1783 | */ | 1812 | */ |
1784 | static void | 1813 | static void |
@@ -1786,8 +1815,35 @@ service_mq_error_handler (void *cls, | |||
1786 | enum GNUNET_MQ_Error error) | 1815 | enum GNUNET_MQ_Error error) |
1787 | { | 1816 | { |
1788 | struct GNUNET_SERVICE_Client *client = cls; | 1817 | struct GNUNET_SERVICE_Client *client = cls; |
1818 | struct GNUNET_SERVICE_Handle *sh = client->sh; | ||
1789 | 1819 | ||
1790 | // FIXME! | 1820 | if ( (GNUNET_MQ_ERROR_NO_MATCH == error) && |
1821 | (GNUNET_NO == sh->require_found) ) | ||
1822 | return; /* ignore error */ | ||
1823 | GNUNET_SERVICE_client_drop (client); | ||
1824 | } | ||
1825 | |||
1826 | |||
1827 | /** | ||
1828 | * Task run to warn about missing calls to #GNUNET_SERVICE_client_continue(). | ||
1829 | * | ||
1830 | * @param cls our `struct GNUNET_SERVICE_Client *` to process more requests from | ||
1831 | */ | ||
1832 | static void | ||
1833 | warn_no_client_continue (void *cls) | ||
1834 | { | ||
1835 | struct GNUNET_SERVICE_Client *client = cls; | ||
1836 | |||
1837 | GNUNET_break (0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */ | ||
1838 | client->warn_task | ||
1839 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
1840 | &warn_no_client_continue, | ||
1841 | client); | ||
1842 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1843 | _("Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"), | ||
1844 | (unsigned int) client->warn_type, | ||
1845 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start), | ||
1846 | GNUNET_YES)); | ||
1791 | } | 1847 | } |
1792 | 1848 | ||
1793 | 1849 | ||
@@ -1795,21 +1851,27 @@ service_mq_error_handler (void *cls, | |||
1795 | * Functions with this signature are called whenever a | 1851 | * Functions with this signature are called whenever a |
1796 | * complete message is received by the tokenizer for a client. | 1852 | * complete message is received by the tokenizer for a client. |
1797 | * | 1853 | * |
1798 | * Do not call #GNUNET_SERVER_mst_destroy() from within | 1854 | * Do not call #GNUNET_MST_destroy() from within |
1799 | * the scope of this callback. | 1855 | * the scope of this callback. |
1800 | * | 1856 | * |
1801 | * @param cls closure with the `struct GNUNET_SERVICE_Client *` | 1857 | * @param cls closure with the `struct GNUNET_SERVICE_Client *` |
1802 | * @param client_cls closure with the `struct GNUNET_SERVICE_Client *` | ||
1803 | * @param message the actual message | 1858 | * @param message the actual message |
1804 | * @return #GNUNET_OK on success (always) | 1859 | * @return #GNUNET_OK on success (always) |
1805 | */ | 1860 | */ |
1806 | static int | 1861 | static int |
1807 | service_client_mst_cb (void *cls, | 1862 | service_client_mst_cb (void *cls, |
1808 | void *client_cls, | ||
1809 | const struct GNUNET_MessageHeader *message) | 1863 | const struct GNUNET_MessageHeader *message) |
1810 | { | 1864 | { |
1811 | struct GNUNET_SERVICE_Client *client = cls; | 1865 | struct GNUNET_SERVICE_Client *client = cls; |
1812 | 1866 | ||
1867 | GNUNET_assert (GNUNET_NO == client->needs_continue); | ||
1868 | client->needs_continue = GNUNET_YES; | ||
1869 | client->warn_type = ntohs (message->type); | ||
1870 | client->warn_start = GNUNET_TIME_absolute_get (); | ||
1871 | client->warn_task | ||
1872 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
1873 | &warn_no_client_continue, | ||
1874 | client); | ||
1813 | GNUNET_MQ_inject_message (client->mq, | 1875 | GNUNET_MQ_inject_message (client->mq, |
1814 | message); | 1876 | message); |
1815 | return GNUNET_OK; | 1877 | return GNUNET_OK; |
@@ -1826,10 +1888,31 @@ static void | |||
1826 | service_client_recv (void *cls) | 1888 | service_client_recv (void *cls) |
1827 | { | 1889 | { |
1828 | struct GNUNET_SERVICE_Client *client = cls; | 1890 | struct GNUNET_SERVICE_Client *client = cls; |
1891 | int ret; | ||
1829 | 1892 | ||
1830 | // FIXME: read into buffer, pass to MST, then client->mq inject! | 1893 | client->recv_task = NULL; |
1831 | // FIXME: revise MST API to avoid the memcpy! | 1894 | ret = GNUNET_MST_read (client->mst, |
1832 | // i.e.: GNUNET_MST_read (client->sock); | 1895 | client->sock, |
1896 | GNUNET_NO, | ||
1897 | GNUNET_YES); | ||
1898 | if (GNUNET_SYSERR == ret) | ||
1899 | { | ||
1900 | GNUNET_break (0); | ||
1901 | GNUNET_SERVICE_client_drop (client); | ||
1902 | return; | ||
1903 | } | ||
1904 | if (GNUNET_NO == ret) | ||
1905 | return; /* more messages in buffer, wait for application | ||
1906 | to be done processing */ | ||
1907 | GNUNET_assert (GNUNET_OK == ret); | ||
1908 | if (GNUNET_YES == client->needs_continue) | ||
1909 | return; | ||
1910 | /* MST needs more data, re-schedule read job */ | ||
1911 | client->recv_task | ||
1912 | = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
1913 | client->sock, | ||
1914 | &service_client_recv, | ||
1915 | client); | ||
1833 | } | 1916 | } |
1834 | 1917 | ||
1835 | 1918 | ||
@@ -1859,8 +1942,8 @@ start_client (struct GNUNET_SERVICE_Handle *sh, | |||
1859 | sh->handlers, | 1942 | sh->handlers, |
1860 | &service_mq_error_handler, | 1943 | &service_mq_error_handler, |
1861 | client); | 1944 | client); |
1862 | client->mst = GNUNET_SERVER_mst_create (&service_client_mst_cb, | 1945 | client->mst = GNUNET_MST_create (&service_client_mst_cb, |
1863 | client); | 1946 | client); |
1864 | client->user_context = sh->connect_cb (sh->cb_cls, | 1947 | client->user_context = sh->connect_cb (sh->cb_cls, |
1865 | client, | 1948 | client, |
1866 | client->mq); | 1949 | client->mq); |
@@ -1955,69 +2038,70 @@ accept_client (void *cls) | |||
1955 | 2038 | ||
1956 | slc->listen_task = NULL; | 2039 | slc->listen_task = NULL; |
1957 | while (1) | 2040 | while (1) |
2041 | { | ||
2042 | struct GNUNET_NETWORK_Handle *sock; | ||
2043 | const struct sockaddr_in *v4; | ||
2044 | const struct sockaddr_in6 *v6; | ||
2045 | struct sockaddr_storage sa; | ||
2046 | socklen_t addrlen; | ||
2047 | int ok; | ||
2048 | |||
2049 | addrlen = sizeof (sa); | ||
2050 | sock = GNUNET_NETWORK_socket_accept (slc->listen_socket, | ||
2051 | (struct sockaddr *) &sa, | ||
2052 | &addrlen); | ||
2053 | if (NULL == sock) | ||
2054 | break; | ||
2055 | switch (sa.ss_family) | ||
1958 | { | 2056 | { |
1959 | struct GNUNET_NETWORK_Handle *sock; | 2057 | case AF_INET: |
1960 | const struct sockaddr_in *v4; | 2058 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); |
1961 | const struct sockaddr_in6 *v6; | 2059 | v4 = (const struct sockaddr_in *) &sa; |
1962 | struct sockaddr_storage sa; | 2060 | ok = ( ( (NULL == sh->v4_allowed) || |
1963 | socklen_t addrlen; | 2061 | (check_ipv4_listed (sh->v4_allowed, |
1964 | int ok; | 2062 | &v4->sin_addr))) && |
1965 | 2063 | ( (NULL == sh->v4_denied) || | |
1966 | addrlen = sizeof (sa); | 2064 | (! check_ipv4_listed (sh->v4_denied, |
1967 | sock = GNUNET_NETWORK_socket_accept (slc->listen_socket, | 2065 | &v4->sin_addr)) ) ); |
1968 | (struct sockaddr *) &sa, | 2066 | break; |
1969 | &addrlen); | 2067 | case AF_INET6: |
1970 | if (NULL == sock) | 2068 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in6)); |
1971 | break; | 2069 | v6 = (const struct sockaddr_in6 *) &sa; |
1972 | switch (sa.ss_family) | 2070 | ok = ( ( (NULL == sh->v6_allowed) || |
1973 | { | 2071 | (check_ipv6_listed (sh->v6_allowed, |
1974 | case AF_INET: | 2072 | &v6->sin6_addr))) && |
1975 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); | 2073 | ( (NULL == sh->v6_denied) || |
1976 | v4 = (const struct sockaddr_in *) &sa; | 2074 | (! check_ipv6_listed (sh->v6_denied, |
1977 | ok = ( ( (NULL == sh->v4_allowed) || | 2075 | &v6->sin6_addr)) ) ); |
1978 | (check_ipv4_listed (sh->v4_allowed, | 2076 | break; |
1979 | &v4->sin_addr))) && | ||
1980 | ( (NULL == sh->v4_denied) || | ||
1981 | (! check_ipv4_listed (sh->v4_denied, | ||
1982 | &v4->sin_addr)) ) ); | ||
1983 | break; | ||
1984 | case AF_INET6: | ||
1985 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in6)); | ||
1986 | v6 = (const struct sockaddr_in6 *) &sa; | ||
1987 | ok = ( ( (NULL == sh->v6_allowed) || | ||
1988 | (check_ipv6_listed (sh->v6_allowed, | ||
1989 | &v6->sin6_addr))) && | ||
1990 | ( (NULL == sh->v6_denied) || | ||
1991 | (! check_ipv6_listed (sh->v6_denied, | ||
1992 | &v6->sin6_addr)) ) ); | ||
1993 | break; | ||
1994 | #ifndef WINDOWS | 2077 | #ifndef WINDOWS |
1995 | case AF_UNIX: | 2078 | case AF_UNIX: |
1996 | ok = GNUNET_OK; /* controlled using file-system ACL now */ | 2079 | ok = GNUNET_OK; /* controlled using file-system ACL now */ |
1997 | break; | 2080 | break; |
1998 | #endif | 2081 | #endif |
1999 | default: | 2082 | default: |
2000 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2083 | LOG (GNUNET_ERROR_TYPE_WARNING, |
2001 | _("Unknown address family %d\n"), | 2084 | _("Unknown address family %d\n"), |
2002 | sa.ss_family); | 2085 | sa.ss_family); |
2003 | return; | 2086 | return; |
2004 | } | 2087 | } |
2005 | if (! ok) | 2088 | if (! ok) |
2006 | { | 2089 | { |
2007 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2008 | "Service rejected incoming connection from %s due to policy.\n", | ||
2009 | GNUNET_a2s ((const struct sockaddr *) &sa, | ||
2010 | addrlen)); | ||
2011 | GNUNET_NETWORK_socket_close (sock); | ||
2012 | continue; | ||
2013 | } | ||
2014 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2090 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2015 | "Service accepted incoming connection from %s.\n", | 2091 | "Service rejected incoming connection from %s due to policy.\n", |
2016 | GNUNET_a2s ((const struct sockaddr *) &sa, | 2092 | GNUNET_a2s ((const struct sockaddr *) &sa, |
2017 | addrlen)); | 2093 | addrlen)); |
2018 | start_client (slc->sh, | 2094 | GNUNET_break (GNUNET_OK == |
2019 | sock); | 2095 | GNUNET_NETWORK_socket_close (sock)); |
2096 | continue; | ||
2020 | } | 2097 | } |
2098 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2099 | "Service accepted incoming connection from %s.\n", | ||
2100 | GNUNET_a2s ((const struct sockaddr *) &sa, | ||
2101 | addrlen)); | ||
2102 | start_client (slc->sh, | ||
2103 | sock); | ||
2104 | } | ||
2021 | slc->listen_task | 2105 | slc->listen_task |
2022 | = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 2106 | = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
2023 | slc->listen_socket, | 2107 | slc->listen_socket, |
@@ -2049,6 +2133,42 @@ GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh) | |||
2049 | 2133 | ||
2050 | 2134 | ||
2051 | /** | 2135 | /** |
2136 | * Task run to resume receiving data from the client after | ||
2137 | * the client called #GNUNET_SERVICE_client_continue(). | ||
2138 | * | ||
2139 | * @param cls our `struct GNUNET_SERVICE_Client` | ||
2140 | */ | ||
2141 | static void | ||
2142 | resume_client_receive (void *cls) | ||
2143 | { | ||
2144 | struct GNUNET_SERVICE_Client *c = cls; | ||
2145 | int ret; | ||
2146 | |||
2147 | c->recv_task = NULL; | ||
2148 | /* first, check if there is still something in the buffer */ | ||
2149 | ret = GNUNET_MST_next (c->mst, | ||
2150 | GNUNET_YES); | ||
2151 | if (GNUNET_SYSERR == ret) | ||
2152 | { | ||
2153 | GNUNET_break (0); | ||
2154 | GNUNET_SERVICE_client_drop (c); | ||
2155 | return; | ||
2156 | } | ||
2157 | if (GNUNET_NO == ret) | ||
2158 | return; /* done processing, wait for more later */ | ||
2159 | GNUNET_assert (GNUNET_OK == ret); | ||
2160 | if (GNUNET_YES == c->needs_continue) | ||
2161 | return; /* #GNUNET_MST_next() did give a message to the client */ | ||
2162 | /* need to receive more data from the network first */ | ||
2163 | c->recv_task | ||
2164 | = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2165 | c->sock, | ||
2166 | &service_client_recv, | ||
2167 | c); | ||
2168 | } | ||
2169 | |||
2170 | |||
2171 | /** | ||
2052 | * Continue receiving further messages from the given client. | 2172 | * Continue receiving further messages from the given client. |
2053 | * Must be called after each message received. | 2173 | * Must be called after each message received. |
2054 | * | 2174 | * |
@@ -2057,7 +2177,16 @@ GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh) | |||
2057 | void | 2177 | void |
2058 | GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) | 2178 | GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c) |
2059 | { | 2179 | { |
2060 | GNUNET_break (0); // not implemented | 2180 | GNUNET_assert (GNUNET_YES == c->needs_continue); |
2181 | GNUNET_assert (NULL == c->recv_task); | ||
2182 | c->needs_continue = GNUNET_NO; | ||
2183 | if (NULL != c->warn_task) | ||
2184 | { | ||
2185 | GNUNET_SCHEDULER_cancel (c->warn_task); | ||
2186 | c->warn_task = NULL; | ||
2187 | } | ||
2188 | c->recv_task = GNUNET_SCHEDULER_add_now (&resume_client_receive, | ||
2189 | c); | ||
2061 | } | 2190 | } |
2062 | 2191 | ||
2063 | 2192 | ||
@@ -2117,11 +2246,12 @@ GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c) | |||
2117 | GNUNET_SCHEDULER_cancel (c->send_task); | 2246 | GNUNET_SCHEDULER_cancel (c->send_task); |
2118 | c->send_task = NULL; | 2247 | c->send_task = NULL; |
2119 | } | 2248 | } |
2120 | GNUNET_SERVER_mst_destroy (c->mst); | 2249 | GNUNET_MST_destroy (c->mst); |
2121 | GNUNET_MQ_destroy (c->mq); | 2250 | GNUNET_MQ_destroy (c->mq); |
2122 | if (GNUNET_NO == c->persist) | 2251 | if (GNUNET_NO == c->persist) |
2123 | { | 2252 | { |
2124 | GNUNET_NETWORK_socket_close (c->sock); | 2253 | GNUNET_break (GNUNET_OK == |
2254 | GNUNET_NETWORK_socket_close (c->sock)); | ||
2125 | } | 2255 | } |
2126 | else | 2256 | else |
2127 | { | 2257 | { |