tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / transport / transport-testing-send.c
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 it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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, 30)
31
32
33 /**
34  * Return @a cx in @a cls.
35  */
36 static void
37 find_cr (void *cls,   
38          struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
39 {
40   struct GNUNET_TRANSPORT_TESTING_ConnectRequest **cr = cls;
41
42   if (GNUNET_NO == cx->connected)
43     return;
44   *cr = cx;
45 }
46
47
48 /**
49  * Send a test message of type @a mtype and size @a msize from
50  * peer @a sender to peer @a receiver.  The peers should be
51  * connected when this function is called.
52  *
53  * @param sender the sending peer
54  * @param receiver the receiving peer
55  * @param mtype message type to use
56  * @param msize size of the message, at least `sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage)`
57  * @param num unique message number
58  * @param cont continuation to call after transmission
59  * @param cont_cls closure for @a cont
60  * @return #GNUNET_OK if message was queued,
61  *         #GNUNET_NO if peers are not connected
62  *         #GNUNET_SYSERR if @a msize is illegal
63  */
64 int
65 GNUNET_TRANSPORT_TESTING_send (struct GNUNET_TRANSPORT_TESTING_PeerContext *sender,
66                                struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
67                                uint16_t mtype,
68                                uint16_t msize,
69                                uint32_t num,
70                                GNUNET_SCHEDULER_TaskCallback cont,
71                                void *cont_cls)
72 {
73   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
74   struct GNUNET_MQ_Envelope *env;
75   struct GNUNET_TRANSPORT_TESTING_TestMessage *test;
76   
77   if (msize < sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage))
78   {
79     GNUNET_break (0);
80     return GNUNET_SYSERR;
81   }
82   cr = NULL;
83   GNUNET_TRANSPORT_TESTING_find_connecting_context (sender,
84                                                     receiver,
85                                                     &find_cr,
86                                                     &cr);
87   if (NULL == cr)
88     GNUNET_TRANSPORT_TESTING_find_connecting_context (receiver,
89                                                       sender,
90                                                       &find_cr,
91                                                       &cr);
92   if (NULL == cr)
93   {
94     GNUNET_break (0);
95     return GNUNET_NO;
96   }
97   if (NULL == cr->mq) 
98   {
99     GNUNET_break (0);
100     return GNUNET_NO;
101   }
102   {
103     char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id));
104
105     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
106                 "Sending message from peer %u (`%s') -> peer %u (`%s') !\n",
107                 sender->no,
108                 GNUNET_i2s (&sender->id),
109                 receiver->no,
110                 receiver_s);
111     GNUNET_free (receiver_s);
112   }
113   env = GNUNET_MQ_msg_extra (test,
114                              msize - sizeof (*test),
115                              mtype);
116   test->num = htonl (num);
117   memset (&test[1],
118           num,
119           msize - sizeof (*test));
120   GNUNET_MQ_notify_sent (env,
121                          cont,
122                          cont_cls);
123   GNUNET_MQ_send (cr->mq,
124                   env);
125   return GNUNET_OK;
126 }
127
128
129 /**
130  * Task that sends a test message from the 
131  * first peer to the second peer.
132  *
133  * @param ccc context which should contain at least two peers, the
134  *        first two of which should be currently connected
135  * @param size desired message size
136  * @param cont continuation to call after transmission
137  * @param cont_cls closure for @a cont
138  */
139 static void
140 do_send (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
141          uint16_t size,
142          GNUNET_SCHEDULER_TaskCallback cont,
143          void *cont_cls)
144 {
145   int ret;
146
147   ccc->global_ret = GNUNET_SYSERR;
148   ret = GNUNET_TRANSPORT_TESTING_send (ccc->p[0],
149                                        ccc->p[1],
150                                        GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE,
151                                        size,
152                                        ccc->send_num_gen++,
153                                        cont,
154                                        cont_cls);
155   GNUNET_assert (GNUNET_SYSERR != ret);
156   if (GNUNET_NO == ret)
157   {
158     GNUNET_break (0);
159     ccc->global_ret = GNUNET_SYSERR;
160     GNUNET_SCHEDULER_shutdown ();
161   }
162 }
163
164
165 /**
166  * Task that sends a minimalistic test message from the 
167  * first peer to the second peer.
168  *
169  * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
170  *        which should contain at least two peers, the first two
171  *        of which should be currently connected
172  */
173 void
174 GNUNET_TRANSPORT_TESTING_simple_send (void *cls)
175 {
176   struct GNUNET_TRANSPORT_TESTING_SendClosure *sc = cls;
177   int done;
178   size_t msize;
179
180   if (0 < sc->num_messages)
181   {
182     sc->num_messages--;
183     done = (0 == sc->num_messages);
184   }
185   else
186   {
187     done = 0; /* infinite loop */
188   }
189   msize = sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage);
190   if (NULL != sc->get_size_cb)
191     msize = sc->get_size_cb (sc->num_messages);
192   /* if this was the last message, call the continuation,
193      otherwise call this function again */
194   do_send (sc->ccc,
195            msize,
196            done ? sc->cont : &GNUNET_TRANSPORT_TESTING_simple_send,
197            done ? sc->cont_cls : sc);
198 }
199
200
201 /**
202  * Task that sends a large test message from the 
203  * first peer to the second peer.
204  *
205  * @param cls the `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
206  *        which should contain at least two peers, the first two
207  *        of which should be currently connected
208  */
209 void
210 GNUNET_TRANSPORT_TESTING_large_send (void *cls)
211 {
212   struct GNUNET_TRANSPORT_TESTING_SendClosure *sc = cls;
213   int done;
214   size_t msize;
215
216   if (0 < sc->num_messages)
217   {
218     sc->num_messages--;
219     done = (0 == sc->num_messages);
220   }
221   else
222   {
223     done = 0; /* infinite loop */
224   }
225   msize = 2600;
226   if (NULL != sc->get_size_cb)
227     msize = sc->get_size_cb (sc->num_messages);
228   /* if this was the last message, call the continuation,
229      otherwise call this function again */
230   do_send (sc->ccc,
231            msize,
232            done ? sc->cont : &GNUNET_TRANSPORT_TESTING_large_send,
233            done ? sc->cont_cls : sc);
234 }
235
236 /* end of transport-testing-send.c */