aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorch3 <buenger@mytum.de>2024-01-27 18:31:06 +0100
committerch3 <buenger@mytum.de>2024-04-26 19:05:01 +0200
commita6e872e9111de5bc8b078511a16251c097323498 (patch)
treee916f6b51638603c98e6b29f638b42dc0be413c3 /src
parent0fedc84c96940ee13ff102c79926d64265620609 (diff)
downloadgnunet-a6e872e9111de5bc8b078511a16251c097323498.tar.gz
gnunet-a6e872e9111de5bc8b078511a16251c097323498.zip
cong: underlay dummy: enable multiple peers and peer discovery
This has still bugs
Diffstat (limited to 'src')
-rw-r--r--src/service/core/gnunet_core_underlay_dummy.c544
-rw-r--r--src/service/core/test_core_underlay_dummy.c3
2 files changed, 411 insertions, 136 deletions
diff --git a/src/service/core/gnunet_core_underlay_dummy.c b/src/service/core/gnunet_core_underlay_dummy.c
index 0c8b0ca8e..e98d849d6 100644
--- a/src/service/core/gnunet_core_underlay_dummy.c
+++ b/src/service/core/gnunet_core_underlay_dummy.c
@@ -56,47 +56,129 @@ extern "C" {
56#define LOG(kind, ...) GNUNET_log_from (kind, "core-underlay-dummy", __VA_ARGS__) 56#define LOG(kind, ...) GNUNET_log_from (kind, "core-underlay-dummy", __VA_ARGS__)
57 57
58#define SOCK_NAME_BASE "/tmp/gnunet-core-underlay-dummy-socket" 58#define SOCK_NAME_BASE "/tmp/gnunet-core-underlay-dummy-socket"
59#define SOCK_EXTENSION ".sock"
59#define BUFF_SIZE 8192 60#define BUFF_SIZE 8192
60#define BACKLOG 10 61#define BACKLOG 10
61 62
63
62/** 64/**
63 * Opaque handle to the service. 65 * @brief Closure used for the #peer_connect_task
64 */ 66 */
65struct GNUNET_CORE_UNDERLAY_DUMMY_Handle 67struct PeerConnectCls
66{ 68{
67 /** 69 /**
68 * Callback (from/to client) to call when another peer connects. 70 * @brief Linked list next
69 */ 71 */
70 GNUNET_CORE_UNDERLAY_DUMMY_NotifyConnect notify_connect; 72 struct PeerConnectCls *next;
71 73
72 /** 74 /**
73 * Callback (from/to client) to call when a peer disconnects. 75 * @brief Linked list previous
74 */ 76 */
75 GNUNET_CORE_UNDERLAY_DUMMY_NotifyDisconnect notify_disconnect; 77 struct PeerConnectCls *prev;
76 78
77 /** 79 /**
78 * Callback (from/to client) to call when our address changes. 80 * @brief The handle for the service
79 */ 81 */
80 GNUNET_CORE_UNDERLAY_DUMMY_NotifyAddressChange notify_address_change; 82 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h;
81 83
82 /** 84 /**
83 * Array of message handlers given by the client. 85 * @brief The file name to connect to
84 */ 86 */
85 struct GNUNET_MQ_MessageHandler *handlers; 87 char *sock_name;
88
89 /**
90 * Task to connect to another peer.
91 */
92 struct GNUNET_SCHEDULER_Task *peer_connect_task;
93};
94
95
96/**
97 * @brief Used to keep track of context of peer
98 */
99struct Connection
100{
101 /**
102 * @brief Linked list next
103 */
104 struct Connection *next;
105
106 /**
107 * @brief Linked list previous
108 */
109 struct Connection *prev;
86 110
87 /** 111 /**
88 * Message queue towards the connected peer. 112 * Message queue towards the connected peer.
89 * TODO our implementation currently allows for only one connected peer -
90 * build more flexible data structures.
91 */ 113 */
92 struct GNUNET_MQ_Handle *mq; 114 struct GNUNET_MQ_Handle *mq;
93 115
94 /** 116 /**
95 * Closure for the mq towards the client. 117 * Closure for the mq towards the client.
118 * TODO closure per connection or per Handle/Service?
96 */ 119 */
97 void *cls_mq; 120 void *cls_mq;
98 121
99 /** 122 /**
123 * Socket for the connected peer.
124 * TODO our implementation currently allows for only one connected peer -
125 * build more flexible data structures.
126 */
127 struct GNUNET_NETWORK_Handle *sock;
128
129 /**
130 * Address of the connected peer.
131 */
132 char *peer_addr;
133
134 /**
135 * Task waiting for incoming messages.
136 */
137 struct GNUNET_SCHEDULER_Task *recv_task;
138
139 /**
140 * Task waiting until the socket becomes ready to be written to.
141 */
142 struct GNUNET_SCHEDULER_Task *write_task;
143
144 /**
145 * Currently handled message.
146 */
147 struct GNUNET_MessageHeader *msg_next;
148
149 /**
150 * @brief Handle to the service
151 */
152 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *handle;
153};
154
155
156/**
157 * Opaque handle to the service.
158 */
159struct GNUNET_CORE_UNDERLAY_DUMMY_Handle
160{
161 /**
162 * Callback (from/to client) to call when another peer connects.
163 */
164 GNUNET_CORE_UNDERLAY_DUMMY_NotifyConnect notify_connect;
165
166 /**
167 * Callback (from/to client) to call when a peer disconnects.
168 */
169 GNUNET_CORE_UNDERLAY_DUMMY_NotifyDisconnect notify_disconnect;
170
171 /**
172 * Callback (from/to client) to call when our address changes.
173 */
174 GNUNET_CORE_UNDERLAY_DUMMY_NotifyAddressChange notify_address_change;
175
176 /**
177 * Array of message handlers given by the client.
178 */
179 struct GNUNET_MQ_MessageHandler *handlers;
180
181 /**
100 * Closure for handlers given by the client 182 * Closure for handlers given by the client
101 * (#notify_connect, #notify_disconnect, #notify_address_change) 183 * (#notify_connect, #notify_disconnect, #notify_address_change)
102 * TODO what's the doxygen way of linking to other members of this struct? 184 * TODO what's the doxygen way of linking to other members of this struct?
@@ -114,13 +196,6 @@ struct GNUNET_CORE_UNDERLAY_DUMMY_Handle
114 struct GNUNET_NETWORK_Handle *sock_listen; 196 struct GNUNET_NETWORK_Handle *sock_listen;
115 197
116 /** 198 /**
117 * Socket for the connected peer.
118 * TODO our implementation currently allows for only one connected peer -
119 * build more flexible data structures.
120 */
121 struct GNUNET_NETWORK_Handle *sock;
122
123 /**
124 * Hash over the current address(es). 199 * Hash over the current address(es).
125 */ 200 */
126 struct GNUNET_HashCode network_location_hash; 201 struct GNUNET_HashCode network_location_hash;
@@ -136,25 +211,34 @@ struct GNUNET_CORE_UNDERLAY_DUMMY_Handle
136 struct GNUNET_SCHEDULER_Task *listen_task; 211 struct GNUNET_SCHEDULER_Task *listen_task;
137 212
138 /** 213 /**
139 * Task waiting for incoming messages. 214 * Task to notify core about address changes.
140 */ 215 */
141 struct GNUNET_SCHEDULER_Task *recv_task; 216 struct GNUNET_SCHEDULER_Task *notify_address_change_task;
142 217
143 /** 218 /**
144 * Task to notify core about address changes. 219 * Task to discover other peers.
145 */ 220 */
146 struct GNUNET_SCHEDULER_Task *notify_address_change_task; 221 struct GNUNET_SCHEDULER_Task *peer_discovery_task;
147 222
148 /** 223 /**
149 * Task waiting until the socket becomes ready to be written to. 224 * @brief Head of linked list with peer connect closures
150 */ 225 */
151 struct GNUNET_SCHEDULER_Task *write_task; 226 struct PeerConnectCls *peer_connect_cls_head;
152 227
153 /** 228 /**
154 * Currently handled message. 229 * @brief Tail of linked list with peer connect closures
155 */ 230 */
156 struct GNUNET_MessageHeader *msg_next; 231 struct PeerConnectCls *peer_connect_cls_tail;
157 // TODO create mechanism to manage peers/queues 232
233 /**
234 * @brief Head of linked list with peer connect closures
235 */
236 struct Connection *connections_head;
237
238 /**
239 * @brief Tail of linked list with peer connect closures
240 */
241 struct Connection *connections_tail;
158}; 242};
159 243
160 244
@@ -167,20 +251,30 @@ struct GNUNET_CORE_UNDERLAY_DUMMY_Handle
167static void 251static void
168do_read (void *cls) 252do_read (void *cls)
169{ 253{
170 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls; 254 struct Connection *connection = cls;
171 255
172 ssize_t ret; 256 ssize_t ret;
173 char buf[65536] GNUNET_ALIGN; 257 char buf[65536] GNUNET_ALIGN;
174 struct GNUNET_MessageHeader *msg; 258 struct GNUNET_MessageHeader *msg;
175 259
176 h->recv_task = NULL; 260 connection->recv_task = NULL;
177 ret = GNUNET_NETWORK_socket_recv (h->sock, 261 ret = GNUNET_NETWORK_socket_recv (connection->sock,
178 buf, 262 buf,
179 sizeof(buf)); 263 sizeof(buf));
180 //LOG (GNUNET_ERROR_TYPE_INFO, "Read %d bytes\n", (int) ret); 264 if (0 > ret)
265 {
266 LOG (GNUNET_ERROR_TYPE_ERROR, "Error reading from socket\n");
267 return;
268 }
269 LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes\n", (int) ret);
181 msg = GNUNET_malloc (ret); 270 msg = GNUNET_malloc (ret);
182 GNUNET_memcpy (msg, buf, ret); 271 GNUNET_memcpy (msg, buf, ret);
183 GNUNET_MQ_handle_message (h->handlers, msg); 272 if (2 > ret)
273 {
274 GNUNET_break_op (0);
275 return;
276 }
277 GNUNET_MQ_handle_message (connection->handle->handlers, msg);
184 // TODO do proper rate limiting in sync with 278 // TODO do proper rate limiting in sync with
185 // GNUNET_CORE_UNDERLAY_DUMMY_receive_continue 279 // GNUNET_CORE_UNDERLAY_DUMMY_receive_continue
186} 280}
@@ -196,27 +290,27 @@ static void
196write_cb (void *cls) 290write_cb (void *cls)
197{ 291{
198 ssize_t sent; 292 ssize_t sent;
199 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls; 293 struct Connection *connection = cls;
200 294
201 h->write_task = NULL; 295 connection->write_task = NULL;
202 sent = GNUNET_NETWORK_socket_send (h->sock, 296 sent = GNUNET_NETWORK_socket_send (connection->sock,
203 h->msg_next, 297 connection->msg_next,
204 sizeof(h->msg_next)); 298 sizeof(connection->msg_next));
205 if (GNUNET_SYSERR == sent) 299 if (GNUNET_SYSERR == sent)
206 { 300 {
207 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to send message\n"); 301 LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to send message\n");
208 return; // TODO proper handling 302 return; // TODO proper handling
209 } 303 }
210 LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully sent message\n"); 304 LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully sent message\n");
211 GNUNET_free (h->msg_next); 305 GNUNET_free (connection->msg_next);
212 h->msg_next = NULL; 306 connection->msg_next = NULL;
213 // TODO reschedule for the next round. With the current implementation of the 307 // TODO reschedule for the next round. With the current implementation of the
214 // single message buffer, this doesn't make sense 308 // single message buffer, this doesn't make sense
215 //h->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 309 //h->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
216 // sock_listen, 310 // sock_listen,
217 // &write_cb, 311 // &write_cb,
218 // NULL); 312 // NULL);
219 GNUNET_MQ_impl_send_continue (h->mq); 313 GNUNET_MQ_impl_send_continue (connection->mq);
220} 314}
221 315
222/** 316/**
@@ -232,21 +326,27 @@ mq_send_impl (struct GNUNET_MQ_Handle *mq,
232 const struct GNUNET_MessageHeader *msg, 326 const struct GNUNET_MessageHeader *msg,
233 void *impl_state) 327 void *impl_state)
234{ 328{
235 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = impl_state; 329 struct Connection *connection = impl_state;
236 330
237 LOG(GNUNET_ERROR_TYPE_DEBUG, "from mq_send_impl\n"); 331 LOG(GNUNET_ERROR_TYPE_DEBUG, "from mq_send_impl\n");
238 if (NULL != h->msg_next) return; // FIXME 332 if (NULL != connection->msg_next)
239 // This is a very sloppy implementation - a 333 {
240 // dummy. This might cause problems later 334 // FIXME
241 h->msg_next = GNUNET_new (struct GNUNET_MessageHeader); 335 // This is a very sloppy implementation - a
242 GNUNET_memcpy (h->msg_next, msg, sizeof (msg)); 336 // dummy. This might cause problems later
243 if (NULL == h->write_task) 337 LOG(GNUNET_ERROR_TYPE_WARNING, "Not scheduled sending of message - buffer is still in use\n");
338 return;
339 }
340 connection->msg_next = GNUNET_malloc (sizeof (msg));
341 memset (connection->msg_next, 0, sizeof (msg));
342 GNUNET_memcpy (connection->msg_next, msg, sizeof (msg));
343 if (NULL == connection->write_task)
244 { 344 {
245 h->write_task = 345 connection->write_task =
246 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 346 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
247 h->sock, 347 connection->sock,
248 &write_cb, 348 &write_cb,
249 h); 349 connection);
250 LOG(GNUNET_ERROR_TYPE_DEBUG, "Scheduled sending of message\n"); 350 LOG(GNUNET_ERROR_TYPE_DEBUG, "Scheduled sending of message\n");
251 } 351 }
252 else 352 else
@@ -264,27 +364,28 @@ mq_send_impl (struct GNUNET_MQ_Handle *mq,
264static void 364static void
265mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) 365mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
266{ 366{
267 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = impl_state; 367 struct Connection *connection = impl_state;
268 368
269 if (NULL != h->recv_task) 369 if (NULL != connection->recv_task)
270 { 370 {
271 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling recv task\n"); 371 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling recv task\n");
272 GNUNET_SCHEDULER_cancel (h->recv_task); 372 GNUNET_SCHEDULER_cancel (connection->recv_task);
273 h->recv_task = NULL; 373 connection->recv_task = NULL;
274 } 374 }
275 if ((NULL != h->sock) && 375 if ((NULL != connection->sock) &&
276 (GNUNET_YES != GNUNET_NETWORK_socket_shutdown (h->sock, SHUT_RDWR))) 376 (GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock,
377 SHUT_RDWR)))
277 { 378 {
278 LOG (GNUNET_ERROR_TYPE_ERROR, "Faild to shutdown socket operations\n"); 379 LOG (GNUNET_ERROR_TYPE_ERROR, "Faild to shutdown socket operations\n");
279 } 380 }
280 if (NULL != h->sock) 381 connection->sock = NULL;
281 { 382 // TODO clean up whole connection and remove from DLL, right?
282 GNUNET_NETWORK_socket_close (h->sock); 383 // TODO connection needs a pointer to the handle then
283 h->sock = NULL; 384 //GNUNET_CONTAINER_DLL_remove ();
284 } 385 //GNUNET_free (connection);
285 // TODO adapt to multiple peers
286} 386}
287 387
388
288/** 389/**
289 * @brief Callback to cancel sending a message. 390 * @brief Callback to cancel sending a message.
290 * 391 *
@@ -294,19 +395,26 @@ mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
294static void 395static void
295mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) 396mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
296{ 397{
297 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = impl_state; 398 struct Connection *connection = impl_state;
298 399
299 if (NULL != h->msg_next) 400 if (NULL != connection->msg_next)
300 { 401 {
301 GNUNET_free (h->msg_next); 402 GNUNET_free (connection->msg_next);
302 h->msg_next = NULL; 403 connection->msg_next = NULL;
303 } 404 }
304 if (NULL != h->write_task) 405 if (NULL != connection->write_task)
305 { 406 {
306 GNUNET_SCHEDULER_cancel (h->write_task); 407 GNUNET_SCHEDULER_cancel (connection->write_task);
307 h->write_task = NULL; 408 connection->write_task = NULL;
308 } 409 }
309 // TODO adapt to multiple peers 410 // TODO anything left to clean?
411}
412
413
414static void
415mq_error_handler_impl (void *cls, enum GNUNET_MQ_Error error)
416{
417 LOG (GNUNET_ERROR_TYPE_ERROR, "mq_error_handler_impl: %u\n", error);
310} 418}
311 419
312/** 420/**
@@ -319,16 +427,19 @@ do_accept (void *cls)
319{ 427{
320 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls; 428 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls;
321 429
430 struct Connection *connection;
322 struct GNUNET_NETWORK_Handle *sock; 431 struct GNUNET_NETWORK_Handle *sock;
323 struct sockaddr_un addr_other; 432 struct sockaddr_un addr_other;
324 struct sockaddr *addr_other_p; 433 struct sockaddr *addr_other_p;
325 socklen_t addr_other_len = sizeof(addr_other); 434 socklen_t addr_other_len = sizeof(addr_other);
326 435 memset (&addr_other, 0, sizeof (addr_other));
327 GNUNET_assert (NULL != h->sock_listen);
328 GNUNET_assert (NULL == h->sock);
329 436
330 h->listen_task = NULL; 437 h->listen_task = NULL;
331 438
439 LOG(GNUNET_ERROR_TYPE_INFO, "Handling incoming connection\n");
440
441 GNUNET_assert (NULL != h->sock_listen);
442
332 LOG(GNUNET_ERROR_TYPE_INFO, "Accepting incoming connection\n"); 443 LOG(GNUNET_ERROR_TYPE_INFO, "Accepting incoming connection\n");
333 sock = GNUNET_NETWORK_socket_accept (h->sock_listen, 444 sock = GNUNET_NETWORK_socket_accept (h->sock_listen,
334 (struct sockaddr *) &addr_other, 445 (struct sockaddr *) &addr_other,
@@ -336,17 +447,23 @@ do_accept (void *cls)
336 if (NULL == sock) 447 if (NULL == sock)
337 { 448 {
338 //LOG(GNUNET_ERROR_TYPE_ERROR, "Error accepting incoming connection, %s", strerror(errno)); 449 //LOG(GNUNET_ERROR_TYPE_ERROR, "Error accepting incoming connection, %s", strerror(errno));
339 LOG(GNUNET_ERROR_TYPE_ERROR, "Error accepting incoming connection\n"); 450 LOG (GNUNET_ERROR_TYPE_ERROR, "Error accepting incoming connection\n");
340 return; 451 return;
341 } 452 }
342 h->sock = sock; 453 connection = GNUNET_new (struct Connection);
454 connection->sock = sock;
455 connection->peer_addr = GNUNET_strdup (addr_other.sun_path);
456 connection->handle = h;
457 // TODO fill out all fields of connection
343 LOG(GNUNET_ERROR_TYPE_INFO, "Peer connected\n"); 458 LOG(GNUNET_ERROR_TYPE_INFO, "Peer connected\n");
344 // TODO create mechanism to manage peers 459 GNUNET_CONTAINER_DLL_insert (h->connections_head,
460 h->connections_tail,
461 connection);
345 if (NULL != h->notify_connect) 462 if (NULL != h->notify_connect)
346 { 463 {
347 // TODO maybe do some of this even if handler doesnt exist 464 // TODO maybe do some of this even if handler doesnt exist
348 char **addresses = GNUNET_new_array (1, char *); 465 char **addresses = GNUNET_new_array (1, char *);
349 addresses[0] = GNUNET_malloc (sizeof (char) * strlen (addr_other.sun_path)); 466 addresses[0] = GNUNET_malloc ((sizeof (char) * strlen (addr_other.sun_path)) + 1);
350 addresses[0][0] = '\0'; 467 addresses[0][0] = '\0';
351 // TODO get the socket name of the connecting socket or check if it doesn't 468 // TODO get the socket name of the connecting socket or check if it doesn't
352 // have a proper name 469 // have a proper name
@@ -359,28 +476,46 @@ do_accept (void *cls)
359 //LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check1: %s\n", addresses[0]); 476 //LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check1: %s\n", addresses[0]);
360 ////addr_other_p = GNUNET_NETWORK_get_addr (sock); 477 ////addr_other_p = GNUNET_NETWORK_get_addr (sock);
361 ////LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check2: %s\n", addr_other_p->sa_data); 478 ////LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check2: %s\n", addr_other_p->sa_data);
362 h->mq = 479 connection->mq =
363 GNUNET_MQ_queue_for_callbacks (mq_send_impl, 480 GNUNET_MQ_queue_for_callbacks (mq_send_impl,
364 mq_destroy_impl, 481 mq_destroy_impl,
365 mq_cancel_impl, 482 mq_cancel_impl,
366 h, // impl_state - gets passed to _impls 483 connection, // impl_state - gets passed to _impls
367 // TODO we probably need to replace
368 // this by Queues per peer (or so)
369 h->handlers, // handlers - may be NULL? 484 h->handlers, // handlers - may be NULL?
370 NULL, // mq_error_handler_impl 485 mq_error_handler_impl,
371 h->cls); // cls 486 h->cls); // cls FIXME verify that global cls is fine
372 h->cls_mq = h->notify_connect (h->cls, 487 // FIXME check for existence of callback
373 1, 488 connection->cls_mq = h->notify_connect (h->cls, // FIXME verify that global cls is fine
374 (const char **) addresses, 489 1,
375 h->mq); 490 (const char **) addresses,
491 connection->mq);
376 } 492 }
377 GNUNET_assert (NULL == h->recv_task); 493 connection->recv_task =
378 h->recv_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 494 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
379 h->sock, 495 connection->sock,
380 do_read, 496 do_read, // FIXME adapt to connection as cls
381 h); 497 connection);
382} 498}
383 499
500
501static void
502do_connect_to_peer (void *cls)
503{
504 struct PeerConnectCls *peer_connect_cls = cls;
505
506 peer_connect_cls->peer_connect_task = NULL;
507 GNUNET_CONTAINER_DLL_remove (peer_connect_cls->h->peer_connect_cls_head,
508 peer_connect_cls->h->peer_connect_cls_tail,
509 peer_connect_cls);
510 GNUNET_CORE_UNDERLAY_DUMMY_connect_to_peer (peer_connect_cls->h,
511 peer_connect_cls->sock_name,
512 GNUNET_MQ_PRIO_BEST_EFFORT,
513 GNUNET_BANDWIDTH_VALUE_MAX);
514 GNUNET_free (peer_connect_cls->sock_name);
515 GNUNET_free (peer_connect_cls);
516}
517
518
384/** 519/**
385 * @brief Notify core about address change. 520 * @brief Notify core about address change.
386 * 521 *
@@ -394,12 +529,85 @@ do_notify_address_change (void *cls)
394{ 529{
395 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls; 530 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls;
396 531
532 h->notify_address_change_task = NULL;
397 h->notify_address_change (h->cls, 533 h->notify_address_change (h->cls,
398 h->network_location_hash, 534 h->network_location_hash,
399 h->network_generation_id); 535 h->network_generation_id);
400} 536}
401 537
402 538
539static enum GNUNET_GenericReturnValue
540discovered_socket_cb (void *cls,
541 const char *filename)
542{
543 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls;
544 struct PeerConnectCls *peer_connect_cls;
545
546 LOG (
547 GNUNET_ERROR_TYPE_INFO,
548 "Discovered another peer with address `%s' trying to connect\n",
549 filename);
550 for (struct Connection *conn_iter = h->connections_head;
551 NULL != conn_iter;
552 conn_iter = conn_iter->next)
553 {
554 if (0 == memcmp (filename,
555 conn_iter->peer_addr,
556 strlen (filename)))
557 {
558 LOG (GNUNET_ERROR_TYPE_DEBUG, "Already connected to this peer\n");
559 return GNUNET_OK;
560 }
561 }
562 for (struct PeerConnectCls *pcc_iter = h->peer_connect_cls_head;
563 NULL != pcc_iter;
564 pcc_iter = pcc_iter->next)
565 {
566 if (0 == memcmp (filename,
567 pcc_iter->sock_name,
568 strlen (filename)))
569 {
570 LOG (GNUNET_ERROR_TYPE_DEBUG, "Already this peer and waiting to connect\n");
571 return GNUNET_OK;
572 }
573 }
574 // TODO check if address is already in DLL
575 peer_connect_cls = GNUNET_new (struct PeerConnectCls);
576 peer_connect_cls->h = h;
577 peer_connect_cls->sock_name = GNUNET_strdup (filename);
578 // TODO schedule a single task that iterates over DLL
579 peer_connect_cls->peer_connect_task =
580 GNUNET_SCHEDULER_add_now (do_connect_to_peer,
581 peer_connect_cls);
582 GNUNET_CONTAINER_DLL_insert (h->peer_connect_cls_head,
583 h->peer_connect_cls_tail,
584 peer_connect_cls);
585
586 return GNUNET_OK;
587}
588
589
590static void
591do_discover_peers (void *cls)
592{
593 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls;
594 int ret;
595
596 LOG (GNUNET_ERROR_TYPE_INFO,
597 "Discovering peers with pattern `%s'\n",
598 SOCK_NAME_BASE "*" SOCK_EXTENSION);
599 ret = GNUNET_DISK_glob (SOCK_NAME_BASE "*" SOCK_EXTENSION,
600 discovered_socket_cb,
601 h);
602 LOG (GNUNET_ERROR_TYPE_INFO, "Discovered %u peers\n", ret);
603
604 h->peer_discovery_task = GNUNET_SCHEDULER_add_delayed (
605 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
606 do_discover_peers,
607 h);
608}
609
610
403/** 611/**
404 * Opens UNIX domain socket. 612 * Opens UNIX domain socket.
405 * 613 *
@@ -411,9 +619,8 @@ do_open_socket (void *cls)
411 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls; 619 struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *h = cls;
412 struct sockaddr_un *addr_un; 620 struct sockaddr_un *addr_un;
413 socklen_t addr_un_len; 621 socklen_t addr_un_len;
414 char buff[BUFF_SIZE]; 622 uint64_t sock_name_ctr = 0; // Append to the socket name to avoid collisions
415 uint64_t sock_name_ctr; // Append to the socket name to avoid collisions 623 uint8_t ret = GNUNET_NO;
416 uint8_t ret;
417 // TODO check that everything gets freed and closed in error cases 624 // TODO check that everything gets freed and closed in error cases
418 625
419 h->sock_listen = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); 626 h->sock_listen = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
@@ -431,7 +638,7 @@ do_open_socket (void *cls)
431 do { 638 do {
432 GNUNET_snprintf (addr_un->sun_path, 639 GNUNET_snprintf (addr_un->sun_path,
433 addr_un_len - sizeof (sa_family_t), 640 addr_un_len - sizeof (sa_family_t),
434 SOCK_NAME_BASE "%u\0", sock_name_ctr++); 641 SOCK_NAME_BASE "%u" SOCK_EXTENSION "\0", sock_name_ctr++);
435 LOG (GNUNET_ERROR_TYPE_INFO, "Trying to bind to `%s'\n", addr_un->sun_path); 642 LOG (GNUNET_ERROR_TYPE_INFO, "Trying to bind to `%s'\n", addr_un->sun_path);
436 ret = GNUNET_NETWORK_socket_bind (h->sock_listen, 643 ret = GNUNET_NETWORK_socket_bind (h->sock_listen,
437 (struct sockaddr *) addr_un, 644 (struct sockaddr *) addr_un,
@@ -455,10 +662,14 @@ do_open_socket (void *cls)
455 { 662 {
456 // FIXME compute the network_location_hash and network_generation_id 663 // FIXME compute the network_location_hash and network_generation_id
457 // FIXME _schedule_now() 664 // FIXME _schedule_now()
665 // TODO cancel and cleanup task on run and shutdown
458 h->notify_address_change_task = 666 h->notify_address_change_task =
459 GNUNET_SCHEDULER_add_now (do_notify_address_change, h); 667 GNUNET_SCHEDULER_add_now (do_notify_address_change, h);
460 } 668 }
461 669
670 h->peer_discovery_task = GNUNET_SCHEDULER_add_now (do_discover_peers,
671 h);
672
462 LOG(GNUNET_ERROR_TYPE_INFO, "Mark socket as accepting connections\n"); 673 LOG(GNUNET_ERROR_TYPE_INFO, "Mark socket as accepting connections\n");
463 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (h->sock_listen, BACKLOG)) 674 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (h->sock_listen, BACKLOG))
464 { 675 {
@@ -545,9 +756,34 @@ void
545GNUNET_CORE_UNDERLAY_DUMMY_disconnect 756GNUNET_CORE_UNDERLAY_DUMMY_disconnect
546(struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *handle) 757(struct GNUNET_CORE_UNDERLAY_DUMMY_Handle *handle)
547{ 758{
759 struct PeerConnectCls *pcc_next;
760 struct Connection *conn_next;
761
548 LOG (GNUNET_ERROR_TYPE_INFO, "Core disconnects\n"); 762 LOG (GNUNET_ERROR_TYPE_INFO, "Core disconnects\n");
549 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core disconnects\n");
550 // TODO delete, free and close everything 763 // TODO delete, free and close everything
764 if (NULL != handle->notify_address_change_task)
765 {
766 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling notify address change task\n");
767 GNUNET_SCHEDULER_cancel (handle->notify_address_change_task);
768 }
769 if (NULL != handle->peer_discovery_task)
770 {
771 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling peer discovery task\n");
772 GNUNET_SCHEDULER_cancel (handle->peer_discovery_task);
773 }
774 for (struct PeerConnectCls *pcc = handle->peer_connect_cls_head;
775 NULL != pcc;
776 pcc = pcc_next)
777 {
778 pcc_next = pcc->next;
779 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling peer connect task\n");
780 GNUNET_SCHEDULER_cancel (pcc->peer_connect_task);
781 GNUNET_CONTAINER_DLL_remove (handle->peer_connect_cls_head,
782 handle->peer_connect_cls_tail,
783 pcc);
784 GNUNET_free (pcc->sock_name);
785 GNUNET_free (pcc);
786 }
551 if (NULL != handle->listen_task) 787 if (NULL != handle->listen_task)
552 { 788 {
553 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling listen task\n"); 789 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling listen task\n");
@@ -557,17 +793,33 @@ GNUNET_CORE_UNDERLAY_DUMMY_disconnect
557 { 793 {
558 GNUNET_NETWORK_socket_close (handle->sock_listen); 794 GNUNET_NETWORK_socket_close (handle->sock_listen);
559 } 795 }
560 GNUNET_MQ_destroy (handle->mq); 796 for (struct Connection *conn_iter = handle->connections_head;
561 if (NULL != handle->recv_task) 797 NULL != conn_iter;
798 )
562 { 799 {
563 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling recv task\n"); 800 if (NULL != conn_iter->write_task)
564 GNUNET_SCHEDULER_cancel (handle->recv_task); 801 {
565 } 802 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling write task\n");
566 if (NULL != handle->sock) 803 GNUNET_SCHEDULER_cancel (conn_iter->write_task);
567 { 804 }
568 GNUNET_NETWORK_socket_close (handle->sock); 805 GNUNET_MQ_destroy (conn_iter->mq);
806 if (NULL != conn_iter->recv_task)
807 {
808 LOG (GNUNET_ERROR_TYPE_INFO, "Cancelling recv task\n");
809 GNUNET_SCHEDULER_cancel (conn_iter->recv_task);
810 }
811 if (NULL != conn_iter->sock)
812 {
813 GNUNET_NETWORK_socket_close (conn_iter->sock);
814 }
815 GNUNET_free (conn_iter->peer_addr);
816 // TODO what else?
817 conn_next = conn_iter->next;
818 GNUNET_CONTAINER_DLL_remove (handle->connections_head,
819 handle->connections_tail,
820 conn_iter);
821 GNUNET_free (conn_iter);
569 } 822 }
570 GNUNET_free (handle->sock_name);
571 // TODO handlers 823 // TODO handlers
572 GNUNET_free (handle); 824 GNUNET_free (handle);
573} 825}
@@ -599,10 +851,22 @@ GNUNET_CORE_UNDERLAY_DUMMY_receive_continue (
599 struct GNUNET_MQ_Handle *mq) 851 struct GNUNET_MQ_Handle *mq)
600{ 852{
601 // TODO we currently have a window size of 1 - expand it! 853 // TODO we currently have a window size of 1 - expand it!
602 h->recv_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 854 for (struct Connection *conn_iter = h->connections_head;
603 h->sock, 855 NULL != conn_iter;
604 do_read, 856 conn_iter = conn_iter->next)
605 h); 857 {
858 if (mq == conn_iter->mq)
859 {
860 conn_iter->recv_task =
861 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
862 conn_iter->sock,
863 do_read,
864 conn_iter);
865 return;
866 }
867 }
868 LOG (GNUNET_ERROR_TYPE_ERROR, "No connection with the given mq!\n");
869 GNUNET_assert (0);
606} 870}
607 871
608 872
@@ -626,7 +890,9 @@ GNUNET_CORE_UNDERLAY_DUMMY_connect_to_peer (
626 enum GNUNET_MQ_PriorityPreferences pp, 890 enum GNUNET_MQ_PriorityPreferences pp,
627 struct GNUNET_BANDWIDTH_Value32NBO bw) 891 struct GNUNET_BANDWIDTH_Value32NBO bw)
628{ 892{
893 struct Connection *connection;
629 struct sockaddr_un addr_other; 894 struct sockaddr_un addr_other;
895 memset (&addr_other, 0, sizeof (addr_other));
630 896
631 LOG(GNUNET_ERROR_TYPE_INFO, "Trying to connect to socket: `%s'\n", peer_address); 897 LOG(GNUNET_ERROR_TYPE_INFO, "Trying to connect to socket: `%s'\n", peer_address);
632 if (0 == strcmp (peer_address, h->sock_name)) 898 if (0 == strcmp (peer_address, h->sock_name))
@@ -636,53 +902,61 @@ GNUNET_CORE_UNDERLAY_DUMMY_connect_to_peer (
636 LOG(GNUNET_ERROR_TYPE_INFO, "Not going to connect to own address\n"); 902 LOG(GNUNET_ERROR_TYPE_INFO, "Not going to connect to own address\n");
637 return; 903 return;
638 } 904 }
639 GNUNET_assert (NULL == h->sock); 905 // TODO check whether we are already connected to that address!
640 h->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); 906 connection = GNUNET_new (struct Connection);
641 if (NULL == h->sock) 907 connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
908 connection->handle = h;
909 if (NULL == connection->sock)
642 { 910 {
643 LOG(GNUNET_ERROR_TYPE_ERROR, "Socket does not open\n"); 911 LOG(GNUNET_ERROR_TYPE_ERROR, "Socket does not open\n");
912 GNUNET_free (connection);
644 return; 913 return;
645 } 914 }
646 915
647 addr_other.sun_family = AF_UNIX; 916 addr_other.sun_family = AF_UNIX;
648 //strcpy (addr_other.sun_path, peer_address); 917 //strcpy (addr_other.sun_path, peer_address);
649 GNUNET_memcpy (addr_other.sun_path, peer_address, strlen (peer_address)); 918 GNUNET_memcpy (addr_other.sun_path, peer_address, strlen (peer_address));
650 if (GNUNET_OK != GNUNET_NETWORK_socket_connect (h->sock, 919 if (GNUNET_OK != GNUNET_NETWORK_socket_connect (connection->sock,
651 (struct sockaddr *) &addr_other, 920 (struct sockaddr *) &addr_other,
652 sizeof(addr_other))) 921 sizeof(addr_other)))
653 //sizeof(struct sockaddr_un)))
654 //sizeof(struct sockaddr)))
655 { 922 {
656 LOG(GNUNET_ERROR_TYPE_ERROR, "failed to connect to the socket: %u %s\n", errno, strerror(errno)); 923 LOG(GNUNET_ERROR_TYPE_ERROR, "failed to connect to the socket: %u %s\n", errno, strerror(errno));
924 GNUNET_NETWORK_socket_close (connection->sock);
925 GNUNET_free (connection);
657 //LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check: %s\n", addr_other.sun_path); 926 //LOG (GNUNET_ERROR_TYPE_INFO, "Sanity check: %s\n", addr_other.sun_path);
658 return; 927 return;
659 } 928 }
929 connection->peer_addr = GNUNET_strdup (peer_address);
660 LOG(GNUNET_ERROR_TYPE_INFO, "Successfully connected to socket\n"); 930 LOG(GNUNET_ERROR_TYPE_INFO, "Successfully connected to socket\n");
661 GNUNET_assert (NULL == h->recv_task); 931 connection->recv_task =
662 h->recv_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 932 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
663 h->sock, 933 connection->sock,
664 do_read, 934 do_read, // FIXME adapt to new closure
665 h); 935 connection);
666 GNUNET_assert (NULL == h->mq); 936 connection->mq =
667 h->mq =
668 GNUNET_MQ_queue_for_callbacks (mq_send_impl, 937 GNUNET_MQ_queue_for_callbacks (mq_send_impl,
669 mq_destroy_impl, 938 mq_destroy_impl,
670 mq_cancel_impl, 939 mq_cancel_impl,
671 h, // impl_state - gets passed to _impls 940 connection, // impl_state - gets passed to _impls
672 // TODO we probably need to replace
673 // this by Queues per peer (or so)
674 h->handlers, // handlers - may be NULL? 941 h->handlers, // handlers - may be NULL?
675 NULL, // mq_error_handler_impl 942 mq_error_handler_impl,
676 h->cls); // cls 943 h->cls); // cls // FIXME global cls or per connection? - seems global
944 // TODO fill all fields of connection
945 GNUNET_CONTAINER_DLL_insert (h->connections_head,
946 h->connections_tail,
947 connection);
677 if (NULL != h->notify_connect) 948 if (NULL != h->notify_connect)
678 { 949 {
679 h->notify_connect(h->cls, 950 // FIXME ?? schedule_now()
680 1, 951 connection->cls_mq =
681 (const char **) &peer_address, // FIXME put on heap - 952 h->notify_connect(h->cls, // FIXME global cls or per connection? - seems global
682 // don't pass stack 953 1,
683 // address 954 (const char **) &peer_address, // FIXME put on heap -
684 h->mq); 955 // don't pass stack
956 // address
957 connection->mq);
685 } 958 }
959
686 // FIXME: proper array 960 // FIXME: proper array
687 // FIXME: proper address format ("dummy:<sock_name>") 961 // FIXME: proper address format ("dummy:<sock_name>")
688} 962}
diff --git a/src/service/core/test_core_underlay_dummy.c b/src/service/core/test_core_underlay_dummy.c
index bc31f4bf3..a7323daa9 100644
--- a/src/service/core/test_core_underlay_dummy.c
+++ b/src/service/core/test_core_underlay_dummy.c
@@ -46,6 +46,7 @@ extern "C" {
46#define LOG(kind, ...) GNUNET_log_from (kind, "core", __VA_ARGS__) 46#define LOG(kind, ...) GNUNET_log_from (kind, "core", __VA_ARGS__)
47 47
48#define SOCK_NAME_BASE "/tmp/gnunet-core-underlay-dummy-socket" 48#define SOCK_NAME_BASE "/tmp/gnunet-core-underlay-dummy-socket"
49#define SOCK_EXTENSION ".sock"
49 50
50#define MTYPE 12345 51#define MTYPE 12345
51#define NUMBER_MESSAGES 100 52#define NUMBER_MESSAGES 100
@@ -116,7 +117,7 @@ void address_change_cb (void *cls,
116 result_address_callback = GNUNET_YES; 117 result_address_callback = GNUNET_YES;
117 LOG(GNUNET_ERROR_TYPE_INFO, "Got informed of address change\n"); 118 LOG(GNUNET_ERROR_TYPE_INFO, "Got informed of address change\n");
118 GNUNET_CORE_UNDERLAY_DUMMY_connect_to_peer (dc->h, 119 GNUNET_CORE_UNDERLAY_DUMMY_connect_to_peer (dc->h,
119 SOCK_NAME_BASE "1", 120 SOCK_NAME_BASE "1" SOCK_EXTENSION,
120 GNUNET_MQ_PRIO_BEST_EFFORT, 121 GNUNET_MQ_PRIO_BEST_EFFORT,
121 GNUNET_BANDWIDTH_VALUE_MAX); 122 GNUNET_BANDWIDTH_VALUE_MAX);
122} 123}