aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/Makefile.am3
-rw-r--r--src/transport/test_transport_api.c117
-rw-r--r--src/transport/transport-testing-send.c241
-rw-r--r--src/transport/transport-testing.c223
-rw-r--r--src/transport/transport-testing.h183
5 files changed, 613 insertions, 154 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 767031e6f..d6c4e3ccf 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -153,7 +153,8 @@ libgnunettransporttesting_la_SOURCES = \
153 transport-testing.c transport-testing.h \ 153 transport-testing.c transport-testing.h \
154 transport-testing-filenames.c \ 154 transport-testing-filenames.c \
155 transport-testing-loggers.c \ 155 transport-testing-loggers.c \
156 transport-testing-main.c 156 transport-testing-main.c \
157 transport-testing-send.c
157libgnunettransporttesting_la_LIBADD = \ 158libgnunettransporttesting_la_LIBADD = \
158 libgnunettransport.la \ 159 libgnunettransport.la \
159 $(top_builddir)/src/hello/libgnunethello.la \ 160 $(top_builddir)/src/hello/libgnunethello.la \
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index bc0061363..4da4f2533 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -36,31 +36,8 @@
36 */ 36 */
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) 37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38 38
39/**
40 * How long until we give up on transmitting the message?
41 */
42#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
43
44#define TEST_MESSAGE_SIZE 2600
45
46#define TEST_MESSAGE_TYPE 12345
47
48
49static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc; 39static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
50 40
51static struct GNUNET_TRANSPORT_TransmitHandle *th;
52
53
54static void
55custom_shutdown (void *cls)
56{
57 if (NULL != th)
58 {
59 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
60 th = NULL;
61 }
62}
63
64 41
65static void 42static void
66notify_receive (void *cls, 43notify_receive (void *cls,
@@ -81,8 +58,8 @@ notify_receive (void *cls,
81 GNUNET_free (ps); 58 GNUNET_free (ps);
82 } 59 }
83 60
84 if ((TEST_MESSAGE_TYPE == ntohs (message->type)) && 61 if ((GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE == ntohs (message->type)) &&
85 (TEST_MESSAGE_SIZE == ntohs (message->size))) 62 (GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE == ntohs (message->size)))
86 { 63 {
87 ccc->global_ret = GNUNET_OK; 64 ccc->global_ret = GNUNET_OK;
88 GNUNET_SCHEDULER_shutdown (); 65 GNUNET_SCHEDULER_shutdown ();
@@ -96,90 +73,6 @@ notify_receive (void *cls,
96} 73}
97 74
98 75
99static size_t
100notify_ready (void *cls,
101 size_t size,
102 void *buf)
103{
104 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
105 struct GNUNET_MessageHeader *hdr;
106
107 th = NULL;
108 if (buf == NULL)
109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
111 "Timeout occurred while waiting for transmit_ready\n");
112 GNUNET_SCHEDULER_shutdown ();
113 ccc->global_ret = 42;
114 return 0;
115 }
116
117 GNUNET_assert (size >= TEST_MESSAGE_SIZE);
118 if (NULL != buf)
119 {
120 memset (buf, '\0', TEST_MESSAGE_SIZE);
121 hdr = buf;
122 hdr->size = htons (TEST_MESSAGE_SIZE);
123 hdr->type = htons (TEST_MESSAGE_TYPE);
124 }
125
126 {
127 char *ps = GNUNET_strdup (GNUNET_i2s (&ccc->p[1]->id));
128 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
129 "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n",
130 ccc->p[1]->no,
131 ps,
132 ntohs (hdr->type),
133 ntohs (hdr->size),
134 p->no,
135 GNUNET_i2s (&p->id));
136 GNUNET_free (ps);
137 }
138 return TEST_MESSAGE_SIZE;
139}
140
141
142static void
143sendtask (void *cls)
144{
145 {
146 char *receiver_s = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
147
148 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
149 "Sending message from peer %u (`%s') -> peer %u (`%s') !\n",
150 ccc->p[1]->no,
151 GNUNET_i2s (&ccc->p[1]->id),
152 ccc->p[0]->no,
153 receiver_s);
154 GNUNET_free (receiver_s);
155 }
156 ccc->global_ret = GNUNET_SYSERR;
157 th = GNUNET_TRANSPORT_notify_transmit_ready (ccc->p[1]->th,
158 &ccc->p[0]->id,
159 TEST_MESSAGE_SIZE,
160 TIMEOUT_TRANSMIT,
161 &notify_ready,
162 ccc->p[0]);
163 GNUNET_assert (NULL != th);
164}
165
166
167static void
168notify_disconnect (void *cls,
169 struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
170 const struct GNUNET_PeerIdentity *other)
171{
172 GNUNET_TRANSPORT_TESTING_log_disconnect (cls,
173 me,
174 other);
175 if (NULL != th)
176 {
177 GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
178 th = NULL;
179 }
180}
181
182
183/** 76/**
184 * Runs the test. 77 * Runs the test.
185 * 78 *
@@ -192,12 +85,12 @@ test (char *argv[],
192 int bi_directional) 85 int bi_directional)
193{ 86{
194 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = { 87 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
195 .connect_continuation = &sendtask, 88 .connect_continuation = &GNUNET_TRANSPORT_TESTING_large_send,
89 .connect_continuation_cls = &my_ccc,
196 .config_file = "test_transport_api_data.conf", 90 .config_file = "test_transport_api_data.conf",
197 .rec = &notify_receive, 91 .rec = &notify_receive,
198 .nc = &GNUNET_TRANSPORT_TESTING_log_connect, 92 .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
199 .nd = &notify_disconnect, 93 .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
200 .shutdown_task = &custom_shutdown,
201 .timeout = TIMEOUT, 94 .timeout = TIMEOUT,
202 .bi_directional = bi_directional 95 .bi_directional = bi_directional
203 }; 96 };
diff --git a/src/transport/transport-testing-send.c b/src/transport/transport-testing-send.c
new file mode 100644
index 000000000..20d1f2fbc
--- /dev/null
+++ b/src/transport/transport-testing-send.c
@@ -0,0 +1,241 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file transport-testing-send.c
22 * @brief convenience transmission function for tests
23 * @author Christian Grothoff
24 */
25#include "transport-testing.h"
26
27/**
28 * Acceptable transmission delay.
29 */
30#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
31
32
33static size_t
34notify_ready (void *cls,
35 size_t size,
36 void *buf)
37{
38 struct TRANSPORT_TESTING_SendJob *sj = cls;
39 struct GNUNET_TRANSPORT_TESTING_PeerContext *sender = sj->sender;
40 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver = sj->receiver;
41 struct GNUNET_TRANSPORT_TESTING_Handle *tth = sender->tth;
42 uint16_t msize = sj->msize;
43 struct GNUNET_TRANSPORT_TESTING_TestMessage *test;
44
45 sj->th = NULL;
46 GNUNET_CONTAINER_DLL_remove (tth->sj_head,
47 tth->sj_tail,
48 sj);
49 if (NULL == buf)
50 {
51 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
52 "Timeout occurred while waiting for transmit_ready\n");
53 GNUNET_SCHEDULER_shutdown ();
54 GNUNET_free (sj);
55 return 0;
56 }
57
58 GNUNET_assert (size >= msize);
59 if (NULL != buf)
60 {
61 memset (buf, '\0', msize);
62 test = buf;
63 test->header.size = htons (msize);
64 test->header.type = htons (sj->mtype);
65 test->num = htonl (sj->num);
66 }
67
68 {
69 char *ps = GNUNET_strdup (GNUNET_i2s (&sender->id));
70
71 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
72 "Sending message %u from %u (%s) with type %u and size %u bytes to peer %u (%s)\n",
73 (unsigned int) sj->num,
74 sender->no,
75 ps,
76 sj->mtype,
77 msize,
78 receiver->no,
79 GNUNET_i2s (&receiver->id));
80 GNUNET_free (ps);
81 }
82 GNUNET_free (sj);
83 return msize;
84}
85
86
87/**
88 * Return @a cx in @a cls.
89 */
90static void
91find_cr (void *cls,
92 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
93{
94 struct GNUNET_TRANSPORT_TESTING_ConnectRequest **cr = cls;
95
96 *cr = cx;
97}
98
99
100/**
101 * Send a test message of type @a mtype and size @a msize from
102 * peer @a sender to peer @a receiver. The peers should be
103 * connected when this function is called.
104 *
105 * @param sender the sending peer
106 * @param receiver the receiving peer
107 * @param mtype message type to use
108 * @param msize size of the message, at least `sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage)`
109 * @param num unique message number
110 * @return #GNUNET_OK if message was queued,
111 * #GNUNET_NO if peers are not connected
112 * #GNUNET_SYSERR if @a msize is illegal
113 */
114int
115GNUNET_TRANSPORT_TESTING_send (struct GNUNET_TRANSPORT_TESTING_PeerContext *sender,
116 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
117 uint16_t mtype,
118 uint16_t msize,
119 uint32_t num)
120{
121 struct GNUNET_TRANSPORT_TESTING_Handle *tth = sender->tth;
122 struct TRANSPORT_TESTING_SendJob *sj;
123 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
124
125 if (msize < sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage))
126 {
127 GNUNET_break (0);
128 return GNUNET_SYSERR;
129 }
130 cr = NULL;
131 GNUNET_TRANSPORT_TESTING_find_connecting_context (sender,
132 receiver,
133 &find_cr,
134 &cr);
135 if (NULL == cr)
136 GNUNET_TRANSPORT_TESTING_find_connecting_context (receiver,
137 sender,
138 &find_cr,
139 &cr);
140 if ( (NULL == cr) ||
141 (GNUNET_YES != cr->connected) )
142 {
143 GNUNET_break (0);
144 return GNUNET_NO;
145 }
146 sj = GNUNET_new (struct TRANSPORT_TESTING_SendJob);
147 sj->num = num;
148 sj->sender = sender;
149 sj->receiver = receiver;
150 sj->mtype = mtype;
151 sj->msize = msize;
152 GNUNET_CONTAINER_DLL_insert (tth->sj_head,
153 tth->sj_tail,
154 sj);
155 {
156 char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id));
157
158 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
159 "Sending message from peer %u (`%s') -> peer %u (`%s') !\n",
160 sender->no,
161 GNUNET_i2s (&sender->id),
162 receiver->no,
163 receiver_s);
164 GNUNET_free (receiver_s);
165 }
166 sj->th = GNUNET_TRANSPORT_notify_transmit_ready (sender->th,
167 &receiver->id,
168 msize,
169 TIMEOUT_TRANSMIT,
170 &notify_ready,
171 sj);
172 GNUNET_assert (NULL != sj->th);
173 return GNUNET_OK;
174}
175
176
177/**
178 * Task that sends a test message from the
179 * first peer to the second peer.
180 *
181 * @param ccc context which should contain at least two peers, the
182 * first two of which should be currently connected
183 */
184static void
185do_send (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
186 uint16_t size)
187{
188 int ret;
189
190 ccc->global_ret = GNUNET_SYSERR;
191 ret = GNUNET_TRANSPORT_TESTING_send (ccc->p[0],
192 ccc->p[1],
193 GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
194 size,
195 ccc->send_num_gen++);
196 GNUNET_assert (GNUNET_SYSERR != ret);
197 if (GNUNET_NO == ret)
198 {
199 GNUNET_break (0);
200 ccc->global_ret = GNUNET_SYSERR;
201 GNUNET_SCHEDULER_shutdown ();
202 }
203}
204
205
206/**
207 * Task that sends a minimalistic test message from the
208 * first peer to the second peer.
209 *
210 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
211 * which should contain at least two peers, the first two
212 * of which should be currently connected
213 */
214void
215GNUNET_TRANSPORT_TESTING_simple_send (void *cls)
216{
217 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
218
219 do_send (ccc,
220 sizeof (struct GNUNET_MessageHeader));
221}
222
223
224/**
225 * Task that sends a large test message from the
226 * first peer to the second peer.
227 *
228 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
229 * which should contain at least two peers, the first two
230 * of which should be currently connected
231 */
232void
233GNUNET_TRANSPORT_TESTING_large_send (void *cls)
234{
235 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
236
237 do_send (ccc,
238 2600);
239}
240
241/* end of transport-testing-send.c */
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c
index 322627459..50c297389 100644
--- a/src/transport/transport-testing.c
+++ b/src/transport/transport-testing.c
@@ -44,11 +44,21 @@ find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
44} 44}
45 45
46 46
47static void 47/**
48notify_connecting_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth, 48 * Find any connecting context matching the given pair of peers.
49 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1, 49 *
50 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2) 50 * @param p1 first peer
51 * @param p2 second peer
52 * @param cb function to call
53 * @param cb_cls closure for @a cb
54 */
55void
56GNUNET_TRANSPORT_TESTING_find_connecting_context (struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
57 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
58 GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb,
59 void *cb_cls)
51{ 60{
61 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
52 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc; 62 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
53 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn; 63 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
54 64
@@ -56,28 +66,55 @@ notify_connecting_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
56 { 66 {
57 ccn = cc->next; 67 ccn = cc->next;
58 if ( (cc->p1 == p1) && 68 if ( (cc->p1 == p1) &&
59 (cc->p2 == p2) ) 69 (cc->p2 == p2) )
60 cc->p1_c = GNUNET_YES; 70 cb (cb_cls,
61 if ( (cc->p1 == p2) && 71 cc);
62 (cc->p2 == p1) )
63 cc->p2_c = GNUNET_YES;
64 if ( (cc->p1_c == GNUNET_YES) &&
65 (cc->p2_c == GNUNET_YES) )
66 {
67 cc->cb (cc->cb_cls);
68 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
69 }
70 } 72 }
71} 73}
72 74
73 75
74static void 76static void
77set_p1c (void *cls,
78 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
79{
80 cx->p1_c = GNUNET_YES;
81}
82
83
84static void
85set_p2c (void *cls,
86 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
87{
88 cx->p2_c = GNUNET_YES;
89}
90
91
92static void
93clear_p1c (void *cls,
94 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
95{
96 cx->p1_c = GNUNET_NO;
97}
98
99
100static void
101clear_p2c (void *cls,
102 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
103{
104 cx->p2_c = GNUNET_NO;
105}
106
107
108static void
75notify_connect (void *cls, 109notify_connect (void *cls,
76 const struct GNUNET_PeerIdentity *peer) 110 const struct GNUNET_PeerIdentity *peer)
77{ 111{
78 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; 112 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
113 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
79 char *p2_s; 114 char *p2_s;
80 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2; 115 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
116 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
117 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
81 118
82 p2 = find_peer_context (p->tth, 119 p2 = find_peer_context (p->tth,
83 peer); 120 peer);
@@ -100,30 +137,83 @@ notify_connect (void *cls,
100 p->no, 137 p->no,
101 GNUNET_i2s (&p->id)); 138 GNUNET_i2s (&p->id));
102 GNUNET_free (p2_s); 139 GNUNET_free (p2_s);
103 notify_connecting_context (p->tth, 140 /* update flags in connecting contexts */
104 p, 141 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
105 p2); 142 p2,
143 &set_p1c,
144 NULL);
145 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
146 p,
147 &set_p2c,
148 NULL);
149 /* update set connected flag for all requests */
150 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
151 {
152 if (GNUNET_YES == cc->connected)
153 continue;
154 if ( (GNUNET_YES == cc->p1_c) &&
155 (GNUNET_YES == cc->p2_c) )
156 {
157 cc->connected = GNUNET_YES;
158 /* stop trying to connect */
159 if (NULL != cc->tct)
160 {
161 GNUNET_SCHEDULER_cancel (cc->tct);
162 cc->tct = NULL;
163 }
164 if (NULL != cc->oh)
165 {
166 GNUNET_TRANSPORT_offer_hello_cancel (cc->oh);
167 cc->oh = NULL;
168 }
169 if (NULL != cc->ats_sh)
170 {
171 GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
172 cc->ats_sh = NULL;
173 }
174 }
175 }
176 /* then notify application */
177 for (cc = tth->cc_head; NULL != cc; cc = ccn)
178 {
179 ccn = cc->next;
180 if ( (GNUNET_YES == cc->connected) &&
181 (NULL != cc->cb) )
182 {
183 cc->cb (cc->cb_cls);
184 cc->cb = NULL; /* only notify once! */
185 }
186 }
106} 187}
107 188
108 189
190/**
191 * Offer the current HELLO of P2 to P1.
192 *
193 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
194 */
195static void
196offer_hello (void *cls);
197
198
109static void 199static void
110notify_disconnect (void *cls, 200notify_disconnect (void *cls,
111 const struct GNUNET_PeerIdentity *peer) 201 const struct GNUNET_PeerIdentity *peer)
112{ 202{
113 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls; 203 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
204 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
114 char *p2_s; 205 char *p2_s;
115 /* Find PeerContext */ 206 /* Find PeerContext */
116 int no = 0; 207 int no = 0;
117 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL; 208 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
118 209 struct TRANSPORT_TESTING_SendJob *sj;
119 if (NULL != p) 210 struct TRANSPORT_TESTING_SendJob *sjn;
120 { 211 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
121 p2 = find_peer_context (p->tth, 212
122 peer); 213 p2 = find_peer_context (p->tth,
123 no = p->no; 214 peer);
124 } 215 no = p->no;
125 216 if (NULL != p2)
126 if (p2 != NULL)
127 GNUNET_asprintf (&p2_s, 217 GNUNET_asprintf (&p2_s,
128 "%u (`%s')", 218 "%u (`%s')",
129 p2->no, 219 p2->no,
@@ -138,12 +228,57 @@ notify_disconnect (void *cls,
138 no, 228 no,
139 GNUNET_i2s (&p->id)); 229 GNUNET_i2s (&p->id));
140 GNUNET_free (p2_s); 230 GNUNET_free (p2_s);
141 231 /* notify about disconnect */
142 if (NULL == p)
143 return;
144 if (NULL != p->nd) 232 if (NULL != p->nd)
145 p->nd (p->cb_cls, 233 p->nd (p->cb_cls,
146 peer); 234 peer);
235 if (NULL == p2)
236 return;
237 /* abort all transmissions this disconnected pair is involved in */
238 for (sj = tth->sj_head; NULL != sj; sj = sjn)
239 {
240 sjn = sj->next;
241 if ( ( (sj->sender == p2) &&
242 (sj->receiver == p) ) ||
243 ( (sj->receiver == p2) &&
244 (sj->sender == p) ) )
245 {
246 GNUNET_CONTAINER_DLL_remove (tth->sj_head,
247 tth->sj_tail,
248 sj);
249 GNUNET_TRANSPORT_notify_transmit_ready_cancel (sj->th);
250 GNUNET_free (sj);
251 }
252 }
253 /* update set connected flags for all requests */
254 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
255 p2,
256 &clear_p1c,
257 NULL);
258 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
259 p,
260 &clear_p2c,
261 NULL);
262 /* resume connectivity requests as necessary */
263 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
264 {
265 if (GNUNET_NO == cc->connected)
266 continue;
267 if ( (GNUNET_YES != cc->p1_c) ||
268 (GNUNET_YES != cc->p2_c) )
269 {
270 cc->connected = GNUNET_NO;
271 /* start trying to connect */
272 if ( (NULL == cc->tct) &&
273 (NULL == cc->oh) )
274 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
275 cc);
276 if (NULL == cc->ats_sh)
277 cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
278 &p2->id,
279 1);
280 }
281 }
147} 282}
148 283
149 284
@@ -352,6 +487,9 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerConte
352 GNUNET_TRANSPORT_TESTING_StartCallback restart_cb, 487 GNUNET_TRANSPORT_TESTING_StartCallback restart_cb,
353 void *restart_cb_cls) 488 void *restart_cb_cls)
354{ 489{
490 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
491 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
492
355 /* shutdown */ 493 /* shutdown */
356 LOG (GNUNET_ERROR_TYPE_DEBUG, 494 LOG (GNUNET_ERROR_TYPE_DEBUG,
357 "Stopping peer %u (`%s')\n", 495 "Stopping peer %u (`%s')\n",
@@ -367,6 +505,13 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_PeerConte
367 GNUNET_TRANSPORT_disconnect (p->th); 505 GNUNET_TRANSPORT_disconnect (p->th);
368 p->th = NULL; 506 p->th = NULL;
369 } 507 }
508 for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
509 {
510 ccn = cc->next;
511 if ( (cc->p1 == p) ||
512 (cc->p2 == p) )
513 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
514 }
370 if (NULL != p->ats) 515 if (NULL != p->ats)
371 { 516 {
372 GNUNET_ATS_connectivity_done (p->ats); 517 GNUNET_ATS_connectivity_done (p->ats);
@@ -427,7 +572,16 @@ void
427GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *p) 572GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext *p)
428{ 573{
429 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth; 574 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
575 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
576 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
430 577
578 for (cc = tth->cc_head; NULL != cc; cc = ccn)
579 {
580 ccn = cc->next;
581 if ( (cc->p1 == p) ||
582 (cc->p2 == p) )
583 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
584 }
431 if (NULL != p->ghh) 585 if (NULL != p->ghh)
432 { 586 {
433 GNUNET_TRANSPORT_get_hello_cancel (p->ghh); 587 GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
@@ -478,15 +632,6 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_PeerContext
478 632
479 633
480/** 634/**
481 * Offer the current HELLO of P2 to P1.
482 *
483 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
484 */
485static void
486offer_hello (void *cls);
487
488
489/**
490 * Function called after the HELLO was passed to the 635 * Function called after the HELLO was passed to the
491 * transport service. 636 * transport service.
492 */ 637 */
diff --git a/src/transport/transport-testing.h b/src/transport/transport-testing.h
index 4be451d35..e61621b2e 100644
--- a/src/transport/transport-testing.h
+++ b/src/transport/transport-testing.h
@@ -207,8 +207,69 @@ struct GNUNET_TRANSPORT_TESTING_ConnectRequest
207 */ 207 */
208 void *cb_cls; 208 void *cb_cls;
209 209
210 int p1_c; // dead? 210 /**
211 int p2_c; // dead? 211 * Set if peer1 says the connection is up to peer2.
212 */
213 int p1_c;
214
215 /**
216 * Set if peer2 says the connection is up to peer1.
217 */
218 int p2_c;
219
220 /**
221 * #GNUNET_YES if both @e p1_c and @e p2_c are #GNUNET_YES.
222 */
223 int connected;
224};
225
226
227/**
228 * Information we keep for active transmission jobs.
229 */
230struct TRANSPORT_TESTING_SendJob
231{
232
233 /**
234 * Kept in a DLL.
235 */
236 struct TRANSPORT_TESTING_SendJob *next;
237
238 /**
239 * Kept in a DLL.
240 */
241 struct TRANSPORT_TESTING_SendJob *prev;
242
243 /**
244 * Sender of the message.
245 */
246 struct GNUNET_TRANSPORT_TESTING_PeerContext *sender;
247
248 /**
249 * Receiver of the message.
250 */
251 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver;
252
253 /**
254 * Operation handle.
255 */
256 struct GNUNET_TRANSPORT_TransmitHandle *th;
257
258 /**
259 * Number of the message.
260 */
261 uint32_t num;
262
263 /**
264 * Type of message to send.
265 */
266 uint16_t mtype;
267
268 /**
269 * Length of the message.
270 */
271 uint16_t msize;
272
212}; 273};
213 274
214 275
@@ -233,6 +294,16 @@ struct GNUNET_TRANSPORT_TESTING_Handle
233 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail; 294 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc_tail;
234 295
235 /** 296 /**
297 * Kept in a DLL.
298 */
299 struct TRANSPORT_TESTING_SendJob *sj_head;
300
301 /**
302 * Kept in a DLL.
303 */
304 struct TRANSPORT_TESTING_SendJob *sj_tail;
305
306 /**
236 * head DLL of peers 307 * head DLL of peers
237 */ 308 */
238 struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head; 309 struct GNUNET_TRANSPORT_TESTING_PeerContext *p_head;
@@ -341,6 +412,32 @@ void
341GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc); 412GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
342 413
343 414
415/**
416 * Function called on matching connect requests.
417 *
418 * @param cls closure
419 * @param cc request matching the query
420 */
421typedef void
422(*GNUNET_TRANSPORT_TESTING_ConnectContextCallback)(void *cls,
423 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc);
424
425
426/**
427 * Find any connecting context matching the given pair of peers.
428 *
429 * @param p1 first peer
430 * @param p2 second peer
431 * @param cb function to call
432 * @param cb_cls closure for @a cb
433 */
434void
435GNUNET_TRANSPORT_TESTING_find_connecting_context (struct GNUNET_TRANSPORT_TESTING_PeerContext *p1,
436 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2,
437 GNUNET_TRANSPORT_TESTING_ConnectContextCallback cb,
438 void *cb_cls);
439
440
344/* ********************** high-level process functions *************** */ 441/* ********************** high-level process functions *************** */
345 442
346 443
@@ -531,6 +628,14 @@ struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext
531 */ 628 */
532 int global_ret; 629 int global_ret;
533 630
631 /**
632 * Generator for the `num` field in test messages. Incremented each
633 * time #GNUNET_TRANSPORT_TESTING_simple_send or
634 * #GNUNET_TRANSPORT_TESTING_large_send are used to transmit a
635 * message.
636 */
637 uint32_t send_num_gen;
638
534 /* ******* internal state, clients should not mess with this **** */ 639 /* ******* internal state, clients should not mess with this **** */
535 640
536 /** 641 /**
@@ -652,6 +757,80 @@ GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
652#define GNUNET_TRANSPORT_TESTING_main(num_peers,check,check_cls) \ 757#define GNUNET_TRANSPORT_TESTING_main(num_peers,check,check_cls) \
653 GNUNET_TRANSPORT_TESTING_main_ (argv[0], __FILE__, num_peers, check, check_cls) 758 GNUNET_TRANSPORT_TESTING_main_ (argv[0], __FILE__, num_peers, check, check_cls)
654 759
760/* ***************** Convenience functions for sending ********* */
761
762
763/**
764 * Send a test message of type @a mtype and size @a msize from
765 * peer @a sender to peer @a receiver. The peers should be
766 * connected when this function is called.
767 *
768 * @param sender the sending peer
769 * @param receiver the receiving peer
770 * @param mtype message type to use
771 * @param msize size of the message, at least `sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage)`
772 * @param num unique message number
773 * @return #GNUNET_OK if message was queued,
774 * #GNUNET_NO if peers are not connected
775 * #GNUNET_SYSERR if @a msize is illegal
776 */
777int
778GNUNET_TRANSPORT_TESTING_send (struct GNUNET_TRANSPORT_TESTING_PeerContext *sender,
779 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
780 uint16_t mtype,
781 uint16_t msize,
782 uint32_t num);
783
784
785/**
786 * Message type used by #GNUNET_TRANSPORT_TESTING_simple_send().
787 */
788#define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE 12345
789
790GNUNET_NETWORK_STRUCT_BEGIN
791struct GNUNET_TRANSPORT_TESTING_TestMessage
792{
793 /**
794 * Type is #GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE.
795 */
796 struct GNUNET_MessageHeader header;
797
798 /**
799 * Monotonically increasing counter throughout the test.
800 */
801 uint32_t num GNUNET_PACKED;
802};
803GNUNET_NETWORK_STRUCT_END
804
805
806/**
807 * Task that sends a minimalistic test message from the
808 * first peer to the second peer.
809 *
810 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
811 * which should contain at least two peers, the first two
812 * of which should be currently connected
813 */
814void
815GNUNET_TRANSPORT_TESTING_simple_send (void *cls);
816
817/**
818 * Size of a message sent with
819 * #GNUNET_TRANSPORT_TESTING_large_send(). Big enough
820 * to usually force defragmentation.
821 */
822#define GNUNET_TRANSPORT_TESTING_LARGE_MESSAGE_SIZE 2600
823
824/**
825 * Task that sends a large test message from the
826 * first peer to the second peer.
827 *
828 * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
829 * which should contain at least two peers, the first two
830 * of which should be currently connected
831 */
832void
833GNUNET_TRANSPORT_TESTING_large_send (void *cls);
655 834
656 835
657/* ********************** log-only convenience functions ************* */ 836/* ********************** log-only convenience functions ************* */