diff options
author | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-09-09 12:34:38 +0000 |
---|---|---|
committer | Christian Fuchs <christian.fuchs@cfuchs.net> | 2013-09-09 12:34:38 +0000 |
commit | 21cefae0b4ac6b8579590b52709bbab9f351475e (patch) | |
tree | d9203a9814fc65a38af0b2a0fef6829428d32a3b /src/scalarproduct | |
parent | de547f838e21de9f847c0b357c41cbfa6ecbe967 (diff) | |
download | gnunet-21cefae0b4ac6b8579590b52709bbab9f351475e.tar.gz gnunet-21cefae0b4ac6b8579590b52709bbab9f351475e.zip |
more reworking of the service's state machine
Diffstat (limited to 'src/scalarproduct')
-rw-r--r-- | src/scalarproduct/gnunet-service-scalarproduct.c | 73 |
1 files changed, 32 insertions, 41 deletions
diff --git a/src/scalarproduct/gnunet-service-scalarproduct.c b/src/scalarproduct/gnunet-service-scalarproduct.c index 54b54cc0a..f9024ed34 100644 --- a/src/scalarproduct/gnunet-service-scalarproduct.c +++ b/src/scalarproduct/gnunet-service-scalarproduct.c | |||
@@ -44,10 +44,12 @@ | |||
44 | */ | 44 | */ |
45 | enum SessionState | 45 | enum SessionState |
46 | { | 46 | { |
47 | CLIENT_REQUEST_RECEIVED, | ||
47 | WAITING_FOR_BOBS_CONNECT, | 48 | WAITING_FOR_BOBS_CONNECT, |
48 | MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED, | 49 | CLIENT_RESPONSE_RECEIVED, |
49 | WAITING_FOR_RESPONSE_FROM_SERVICE, | 50 | WAITING_FOR_SERVICE_REQUEST, |
50 | REQUEST_FROM_SERVICE_RECEIVED, | 51 | WAITING_FOR_SERVICE_RESPONSE, |
52 | SERVICE_REQUEST_RECEIVED, | ||
51 | FINALIZED | 53 | FINALIZED |
52 | }; | 54 | }; |
53 | 55 | ||
@@ -689,7 +691,7 @@ handle_client_disconnect (void *cls, | |||
689 | //we MUST terminate any client message underway | 691 | //we MUST terminate any client message underway |
690 | if (session->service_transmit_handle && session->tunnel) | 692 | if (session->service_transmit_handle && session->tunnel) |
691 | GNUNET_MESH_notify_transmit_ready_cancel (session->service_transmit_handle); | 693 | GNUNET_MESH_notify_transmit_ready_cancel (session->service_transmit_handle); |
692 | if (session->tunnel && session->state == WAITING_FOR_RESPONSE_FROM_SERVICE) | 694 | if (session->tunnel && session->state == WAITING_FOR_SERVICE_RESPONSE) |
693 | GNUNET_MESH_tunnel_destroy (session->tunnel); | 695 | GNUNET_MESH_tunnel_destroy (session->tunnel); |
694 | } | 696 | } |
695 | if (GNUNET_SCHEDULER_NO_TASK != session->client_notification_task) | 697 | if (GNUNET_SCHEDULER_NO_TASK != session->client_notification_task) |
@@ -738,6 +740,7 @@ prepare_client_end_notification (void * cls, | |||
738 | // 0 size and the first char in the product is 0, which should never be zero if encoding is used. | 740 | // 0 size and the first char in the product is 0, which should never be zero if encoding is used. |
739 | msg->product_length = htonl (0); | 741 | msg->product_length = htonl (0); |
740 | msg->range = 1; | 742 | msg->range = 1; |
743 | session->state = FINALIZED; | ||
741 | 744 | ||
742 | session->msg = &msg->header; | 745 | session->msg = &msg->header; |
743 | 746 | ||
@@ -870,30 +873,22 @@ prepare_service_response (gcry_mpi_t * r, | |||
870 | 873 | ||
871 | if (GNUNET_SERVER_MAX_MESSAGE_SIZE >= msg_length) | 874 | if (GNUNET_SERVER_MAX_MESSAGE_SIZE >= msg_length) |
872 | { | 875 | { |
873 | struct MessageObject * msg_obj; | 876 | request->msg = (struct GNUNET_MessageHeader *) msg; |
874 | |||
875 | msg_obj = GNUNET_new (struct MessageObject); | ||
876 | msg_obj->msg = (struct GNUNET_MessageHeader *) msg; | ||
877 | msg_obj->transmit_handle = (void *) &request->service_transmit_handle; //and reset the transmit handle | ||
878 | request->service_transmit_handle = | 877 | request->service_transmit_handle = |
879 | GNUNET_MESH_notify_transmit_ready (request->tunnel, | 878 | GNUNET_MESH_notify_transmit_ready (request->tunnel, |
880 | GNUNET_YES, | 879 | GNUNET_YES, |
881 | GNUNET_TIME_UNIT_FOREVER_REL, | 880 | GNUNET_TIME_UNIT_FOREVER_REL, |
882 | msg_length, | 881 | msg_length, |
883 | &do_send_message, | 882 | &do_send_message, |
884 | msg_obj); | 883 | request); |
885 | // we don't care if it could be send or not. either way, the session is over for us. | 884 | // we don't care if it could be send or not. either way, the session is over for us. |
886 | request->state = FINALIZED; | 885 | request->state = FINALIZED; |
887 | response->state = FINALIZED; | ||
888 | } | 886 | } |
889 | else | 887 | else |
890 | { | ||
891 | // TODO FEATURE: fallback to fragmentation, in case the message is too long | ||
892 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!)\n")); | 888 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!)\n")); |
893 | } | ||
894 | 889 | ||
895 | //disconnect our client | 890 | //disconnect our client |
896 | if ( ! request->service_transmit_handle) | 891 | if ( NULL == request->service_transmit_handle) |
897 | { | 892 | { |
898 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via mesh!)\n")); | 893 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via mesh!)\n")); |
899 | 894 | ||
@@ -1135,11 +1130,10 @@ prepare_service_request (void *cls, | |||
1135 | struct ServiceSession * session = cls; | 1130 | struct ServiceSession * session = cls; |
1136 | unsigned char * current; | 1131 | unsigned char * current; |
1137 | struct GNUNET_SCALARPRODUCT_service_request * msg; | 1132 | struct GNUNET_SCALARPRODUCT_service_request * msg; |
1138 | struct MessageObject * msg_obj; | ||
1139 | unsigned int i; | 1133 | unsigned int i; |
1140 | unsigned int j; | 1134 | unsigned int j; |
1141 | uint16_t msg_length; | 1135 | uint16_t msg_length; |
1142 | size_t element_length = 0; //gets initialized by gcry_mpi_print, but the compiler doesn't know that | 1136 | size_t element_length = 0; // initialized by gcry_mpi_print, but the compiler doesn't know that |
1143 | gcry_mpi_t a; | 1137 | gcry_mpi_t a; |
1144 | uint32_t value; | 1138 | uint32_t value; |
1145 | 1139 | ||
@@ -1157,15 +1151,14 @@ prepare_service_request (void *cls, | |||
1157 | + session->mask_length | 1151 | + session->mask_length |
1158 | + my_pubkey_external_length) | 1152 | + my_pubkey_external_length) |
1159 | { | 1153 | { |
1160 | // TODO FEATURE: fallback to fragmentation, in case the message is too long | ||
1161 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!\n")); | 1154 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Message too large, fragmentation is currently not supported!\n")); |
1162 | session->client_notification_task = | 1155 | session->client_notification_task = |
1163 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, | 1156 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, |
1164 | session); | 1157 | session); |
1165 | return; | 1158 | return; |
1166 | } | 1159 | } |
1160 | |||
1167 | msg = GNUNET_malloc (msg_length); | 1161 | msg = GNUNET_malloc (msg_length); |
1168 | |||
1169 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB); | 1162 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB); |
1170 | memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode)); | 1163 | memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode)); |
1171 | msg->mask_length = htons (session->mask_length); | 1164 | msg->mask_length = htons (session->mask_length); |
@@ -1223,27 +1216,26 @@ prepare_service_request (void *cls, | |||
1223 | } | 1216 | } |
1224 | gcry_mpi_release (a); | 1217 | gcry_mpi_release (a); |
1225 | 1218 | ||
1226 | msg_obj = GNUNET_new (struct MessageObject); | 1219 | session->msg = (struct GNUNET_MessageHeader *) msg; |
1227 | msg_obj->msg = (struct GNUNET_MessageHeader *) msg; | ||
1228 | msg_obj->transmit_handle = (void *) &session->service_transmit_handle; //and reset the transmit handle | ||
1229 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting service request.\n")); | 1220 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting service request.\n")); |
1230 | 1221 | ||
1231 | //transmit via mesh messaging | 1222 | //transmit via mesh messaging |
1232 | session->state = WAITING_FOR_RESPONSE_FROM_SERVICE; | ||
1233 | session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->tunnel, GNUNET_YES, | 1223 | session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->tunnel, GNUNET_YES, |
1234 | GNUNET_TIME_UNIT_FOREVER_REL, | 1224 | GNUNET_TIME_UNIT_FOREVER_REL, |
1235 | msg_length, | 1225 | msg_length, |
1236 | &do_send_message, | 1226 | &do_send_message, |
1237 | msg_obj); | 1227 | session); |
1238 | if ( ! session->service_transmit_handle) | 1228 | if ( ! session->service_transmit_handle) |
1239 | { | 1229 | { |
1240 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not send mutlicast message to tunnel!\n")); | 1230 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not send mutlicast message to tunnel!\n")); |
1241 | GNUNET_free (msg_obj); | ||
1242 | GNUNET_free (msg); | 1231 | GNUNET_free (msg); |
1232 | session->msg = NULL; | ||
1243 | session->client_notification_task = | 1233 | session->client_notification_task = |
1244 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, | 1234 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, |
1245 | session); | 1235 | session); |
1236 | return; | ||
1246 | } | 1237 | } |
1238 | session->state = WAITING_FOR_SERVICE_RESPONSE; | ||
1247 | } | 1239 | } |
1248 | 1240 | ||
1249 | /** | 1241 | /** |
@@ -1269,9 +1261,9 @@ handle_client_request (void *cls, | |||
1269 | int32_t * vector; | 1261 | int32_t * vector; |
1270 | uint32_t i; | 1262 | uint32_t i; |
1271 | 1263 | ||
1264 | // only one concurrent session per client connection allowed, simplifies logics a lot... | ||
1272 | GNUNET_SERVER_client_get_user_context (client, session); | 1265 | GNUNET_SERVER_client_get_user_context (client, session); |
1273 | if ((NULL != session) && (session->state != FINALIZED)){ | 1266 | if ((NULL != session) && (session->state != FINALIZED)){ |
1274 | // only one concurrent session per client connection allowed | ||
1275 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1267 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1276 | return; | 1268 | return; |
1277 | } | 1269 | } |
@@ -1318,8 +1310,6 @@ handle_client_request (void *cls, | |||
1318 | } | 1310 | } |
1319 | 1311 | ||
1320 | session = GNUNET_new (struct ServiceSession); | 1312 | session = GNUNET_new (struct ServiceSession); |
1321 | //FIXME: this actually should not happen here! | ||
1322 | GNUNET_SERVER_client_set_user_context (client, session); | ||
1323 | session->service_request_task = GNUNET_SCHEDULER_NO_TASK; | 1313 | session->service_request_task = GNUNET_SCHEDULER_NO_TASK; |
1324 | session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; | 1314 | session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; |
1325 | session->client = client; | 1315 | session->client = client; |
@@ -1377,7 +1367,6 @@ handle_client_request (void *cls, | |||
1377 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1367 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1378 | _ ("Creating new tunnel to for session with key %s.\n"), | 1368 | _ ("Creating new tunnel to for session with key %s.\n"), |
1379 | GNUNET_h2s (&session->key)); | 1369 | GNUNET_h2s (&session->key)); |
1380 | GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); | ||
1381 | session->tunnel = GNUNET_MESH_tunnel_create (my_mesh, session, | 1370 | session->tunnel = GNUNET_MESH_tunnel_create (my_mesh, session, |
1382 | &session->peer, | 1371 | &session->peer, |
1383 | GNUNET_APPLICATION_TYPE_SCALARPRODUCT, | 1372 | GNUNET_APPLICATION_TYPE_SCALARPRODUCT, |
@@ -1393,8 +1382,10 @@ handle_client_request (void *cls, | |||
1393 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1382 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1394 | return; | 1383 | return; |
1395 | } | 1384 | } |
1396 | session->state = WAITING_FOR_BOBS_CONNECT; | 1385 | GNUNET_SERVER_client_set_user_context (client, session); |
1386 | GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); | ||
1397 | 1387 | ||
1388 | session->state = CLIENT_REQUEST_RECEIVED; | ||
1398 | session->service_request_task = | 1389 | session->service_request_task = |
1399 | GNUNET_SCHEDULER_add_now (&prepare_service_request, | 1390 | GNUNET_SCHEDULER_add_now (&prepare_service_request, |
1400 | session); | 1391 | session); |
@@ -1403,7 +1394,7 @@ handle_client_request (void *cls, | |||
1403 | else | 1394 | else |
1404 | { | 1395 | { |
1405 | struct ServiceSession * requesting_session; | 1396 | struct ServiceSession * requesting_session; |
1406 | enum SessionState needed_state = REQUEST_FROM_SERVICE_RECEIVED; | 1397 | enum SessionState needed_state = SERVICE_REQUEST_RECEIVED; |
1407 | 1398 | ||
1408 | session->role = BOB; | 1399 | session->role = BOB; |
1409 | session->mask = NULL; | 1400 | session->mask = NULL; |
@@ -1411,9 +1402,11 @@ handle_client_request (void *cls, | |||
1411 | session->used_element_count = element_count; | 1402 | session->used_element_count = element_count; |
1412 | for (i = 0; i < element_count; i++) | 1403 | for (i = 0; i < element_count; i++) |
1413 | session->vector[i] = ntohl (vector[i]); | 1404 | session->vector[i] = ntohl (vector[i]); |
1414 | session->state = MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED; | 1405 | session->state = CLIENT_RESPONSE_RECEIVED; |
1415 | 1406 | ||
1407 | GNUNET_SERVER_client_set_user_context (client, session); | ||
1416 | GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); | 1408 | GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); |
1409 | |||
1417 | //check if service queue contains a matching request | 1410 | //check if service queue contains a matching request |
1418 | requesting_session = find_matching_session (from_service_tail, | 1411 | requesting_session = find_matching_session (from_service_tail, |
1419 | &session->key, | 1412 | &session->key, |
@@ -1459,6 +1452,7 @@ tunnel_incoming_handler (void *cls, | |||
1459 | c->peer = *initiator; | 1452 | c->peer = *initiator; |
1460 | c->tunnel = tunnel; | 1453 | c->tunnel = tunnel; |
1461 | c->role = BOB; | 1454 | c->role = BOB; |
1455 | c->state = WAITING_FOR_SERVICE_REQUEST; | ||
1462 | return c; | 1456 | return c; |
1463 | } | 1457 | } |
1464 | 1458 | ||
@@ -1763,16 +1757,16 @@ handle_service_request (void *cls, | |||
1763 | // Check if message was sent by me, which would be bad! | 1757 | // Check if message was sent by me, which would be bad! |
1764 | if ( ! memcmp (&session->peer, &me, sizeof (struct GNUNET_PeerIdentity))) | 1758 | if ( ! memcmp (&session->peer, &me, sizeof (struct GNUNET_PeerIdentity))) |
1765 | { | 1759 | { |
1766 | GNUNET_break (0); | ||
1767 | GNUNET_free (session); | 1760 | GNUNET_free (session); |
1761 | GNUNET_break (0); | ||
1768 | return GNUNET_SYSERR; | 1762 | return GNUNET_SYSERR; |
1769 | } | 1763 | } |
1770 | 1764 | ||
1771 | //we need at least a peer and one message id to compare | 1765 | //we need at least a peer and one message id to compare |
1772 | if (ntohs (msg->header.size) < sizeof (struct GNUNET_SCALARPRODUCT_service_request)) | 1766 | if (ntohs (msg->header.size) < sizeof (struct GNUNET_SCALARPRODUCT_service_request)) |
1773 | { | 1767 | { |
1774 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Too short message received from peer!\n")); | ||
1775 | GNUNET_free (session); | 1768 | GNUNET_free (session); |
1769 | GNUNET_break_op(0); | ||
1776 | return GNUNET_SYSERR; | 1770 | return GNUNET_SYSERR; |
1777 | } | 1771 | } |
1778 | mask_length = ntohs (msg->mask_length); | 1772 | mask_length = ntohs (msg->mask_length); |
@@ -1787,9 +1781,8 @@ handle_service_request (void *cls, | |||
1787 | || (used_elements == 0) || (mask_length != (element_count / 8 + (element_count % 8 ? 1 : 0))) | 1781 | || (used_elements == 0) || (mask_length != (element_count / 8 + (element_count % 8 ? 1 : 0))) |
1788 | ) | 1782 | ) |
1789 | { | 1783 | { |
1790 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Invalid message received from peer, message count does not match message length!\n")); | ||
1791 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Used elements: %hu\nElement Count: %hu\nExpected Mask Length: %hu\nCalculated Masklength: %d\n"), used_elements, element_count, mask_length, (element_count / 8 + (element_count % 8 ? 1 : 0))); | ||
1792 | GNUNET_free (session); | 1784 | GNUNET_free (session); |
1785 | GNUNET_break_op(0); | ||
1793 | return GNUNET_SYSERR; | 1786 | return GNUNET_SYSERR; |
1794 | } | 1787 | } |
1795 | if (find_matching_session (from_service_tail, | 1788 | if (find_matching_session (from_service_tail, |
@@ -1804,7 +1797,7 @@ handle_service_request (void *cls, | |||
1804 | } | 1797 | } |
1805 | 1798 | ||
1806 | memcpy (&session->peer, &session->peer, sizeof (struct GNUNET_PeerIdentity)); | 1799 | memcpy (&session->peer, &session->peer, sizeof (struct GNUNET_PeerIdentity)); |
1807 | session->state = REQUEST_FROM_SERVICE_RECEIVED; | 1800 | session->state = SERVICE_REQUEST_RECEIVED; |
1808 | session->element_count = ntohs (msg->element_count); | 1801 | session->element_count = ntohs (msg->element_count); |
1809 | session->used_element_count = used_elements; | 1802 | session->used_element_count = used_elements; |
1810 | session->tunnel = tunnel; | 1803 | session->tunnel = tunnel; |
@@ -1830,7 +1823,7 @@ handle_service_request (void *cls, | |||
1830 | current += pk_length; | 1823 | current += pk_length; |
1831 | 1824 | ||
1832 | //check if service queue contains a matching request | 1825 | //check if service queue contains a matching request |
1833 | needed_state = MESSAGE_FROM_RESPONDING_CLIENT_RECEIVED; | 1826 | needed_state = CLIENT_RESPONSE_RECEIVED; |
1834 | responder_session = find_matching_session (from_client_tail, | 1827 | responder_session = find_matching_session (from_client_tail, |
1835 | &session->key, | 1828 | &session->key, |
1836 | session->element_count, | 1829 | session->element_count, |
@@ -1875,6 +1868,7 @@ handle_service_request (void *cls, | |||
1875 | } | 1868 | } |
1876 | else | 1869 | else |
1877 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&session->key)); | 1870 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&session->key)); |
1871 | |||
1878 | return GNUNET_OK; | 1872 | return GNUNET_OK; |
1879 | } | 1873 | } |
1880 | else | 1874 | else |
@@ -1894,13 +1888,10 @@ except: | |||
1894 | free_session (session); | 1888 | free_session (session); |
1895 | // and notify our client-session that we could not complete the session | 1889 | // and notify our client-session that we could not complete the session |
1896 | if (responder_session) | 1890 | if (responder_session) |
1897 | { | ||
1898 | // we just found the responder session in this queue | 1891 | // we just found the responder session in this queue |
1899 | GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, responder_session); | ||
1900 | responder_session->client_notification_task = | 1892 | responder_session->client_notification_task = |
1901 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, | 1893 | GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, |
1902 | responder_session); | 1894 | responder_session); |
1903 | } | ||
1904 | return GNUNET_SYSERR; | 1895 | return GNUNET_SYSERR; |
1905 | } | 1896 | } |
1906 | 1897 | ||