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