aboutsummaryrefslogtreecommitdiff
path: root/src/scalarproduct
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2013-09-09 12:34:38 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2013-09-09 12:34:38 +0000
commit21cefae0b4ac6b8579590b52709bbab9f351475e (patch)
treed9203a9814fc65a38af0b2a0fef6829428d32a3b /src/scalarproduct
parentde547f838e21de9f847c0b357c41cbfa6ecbe967 (diff)
downloadgnunet-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.c73
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 */
45enum SessionState 45enum 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