023d5a7143aae1f19d9094cc3f72b2ee9709f6e7
[oweals/gnunet.git] / src / transport / test_transport_api_manipulation_recv_tcp.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 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/test_transport_api_manipulation_recv_tcp.c
22  * @brief base test case for transport traffic manipulation implementation
23  *
24  * This test case will setup 2 peers and connect them, the first message
25  * will be sent without manipulation, then a receive delay of 1 second will
26  * be configured and 2 more message will be sent. Time will be measured
27  *
28  * In addition the distance on receiver side will be manipulated to be 10
29  */
30 #include "platform.h"
31 #include "gnunet_transport_service.h"
32 #include "transport-testing.h"
33
34 /**
35  * How long until we give up on transmitting the message?
36  */
37 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
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, 30)
43
44 #define TEST_MESSAGE_SIZE 2600
45
46 #define TEST_MESSAGE_TYPE 12345
47
48
49 static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
50
51 static struct GNUNET_TRANSPORT_TransmitHandle *th;
52
53 static struct GNUNET_SCHEDULER_Task *send_task;
54
55 static int messages_recv;
56
57 static struct GNUNET_TIME_Absolute start_normal;
58
59 static struct GNUNET_TIME_Relative dur_normal;
60
61 static struct GNUNET_TIME_Absolute start_delayed;
62
63 static struct GNUNET_TIME_Relative dur_delayed;
64
65
66 static void
67 custom_shutdown (void *cls)
68 {
69   if (NULL != th)
70   {
71     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
72     th = NULL;
73   }
74   if (NULL != send_task)
75   {
76     GNUNET_SCHEDULER_cancel (send_task);
77     send_task = NULL;
78   }
79 }
80
81
82 static void
83 sendtask (void *cls);
84
85
86 static void
87 notify_receive (void *cls,
88                 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
89                 const struct GNUNET_PeerIdentity *sender,
90                 const struct GNUNET_MessageHeader *message)
91 {
92   {
93     char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
94
95     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
96                 "Peer %u (`%s') received message of type %d and size %u size from peer %s)!\n",
97                 receiver->no,
98                 ps,
99                 ntohs (message->type),
100                 ntohs (message->size),
101                 GNUNET_i2s (sender));
102     GNUNET_free (ps);
103   }
104   if ((TEST_MESSAGE_TYPE == ntohs (message->type)) &&
105       (TEST_MESSAGE_SIZE == ntohs (message->size)))
106   {
107     if (GNUNET_NO == ccc->global_ret)
108       ccc->global_ret = GNUNET_OK;
109   }
110   else
111   {
112     GNUNET_break (0);
113     ccc->global_ret = GNUNET_SYSERR;
114     GNUNET_SCHEDULER_shutdown ();
115     return;
116   }
117
118   if (messages_recv <= 1)
119   {
120     /* Received non-delayed message */
121     dur_normal = GNUNET_TIME_absolute_get_duration(start_normal);
122     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
123                 "Received non-delayed message %u after %s\n",
124                 messages_recv,
125                 GNUNET_STRINGS_relative_time_to_string (dur_normal,
126                                                         GNUNET_YES));
127
128     struct GNUNET_ATS_Properties prop;
129     struct GNUNET_TIME_Relative delay;
130
131     delay.rel_value_us = 1000 * 1000LL;
132     memset (&prop, 0, sizeof (prop));
133     prop.distance = 10;
134     GNUNET_TRANSPORT_set_traffic_metric (ccc->p[0]->th,
135                                          &ccc->p[1]->id,
136                                          &prop,
137                                          delay,
138                                          GNUNET_TIME_UNIT_ZERO);
139     send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL);
140   }
141   if (2 == messages_recv)
142   {
143         /* Received manipulated message */
144     dur_delayed = GNUNET_TIME_absolute_get_duration(start_delayed);
145     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146                 "Received delayed message %u after %s\n",
147                 messages_recv,
148                 GNUNET_STRINGS_relative_time_to_string (dur_delayed,
149                                                           GNUNET_YES));
150     if (dur_delayed.rel_value_us < GNUNET_TIME_UNIT_SECONDS.rel_value_us)
151     {
152       GNUNET_break (0);
153       ccc->global_ret = GNUNET_SYSERR;
154       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
155                   "Delayed message was not delayed correctly: took only %s\n",
156                   GNUNET_STRINGS_relative_time_to_string (dur_delayed,
157                                                           GNUNET_YES));
158     }
159     /* shutdown */
160     GNUNET_SCHEDULER_shutdown ();
161   }
162   messages_recv++;
163 }
164
165
166 static size_t
167 notify_ready (void *cls, size_t size, void *buf)
168 {
169   struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
170   struct GNUNET_MessageHeader *hdr;
171
172   th = NULL;
173   if (NULL == buf)
174   {
175     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176                 "Timeout occurred while waiting for transmit_ready\n");
177     GNUNET_SCHEDULER_shutdown ();
178     ccc->global_ret = 42;
179     return 0;
180   }
181
182   GNUNET_assert (size >= TEST_MESSAGE_SIZE);
183   memset (buf, '\0', TEST_MESSAGE_SIZE);
184   hdr = buf;
185   hdr->size = htons (TEST_MESSAGE_SIZE);
186   hdr->type = htons (TEST_MESSAGE_TYPE);
187
188   {
189     char *ps = GNUNET_strdup (GNUNET_i2s (&ccc->p[1]->id));
190
191     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
192                 "Peer %u (`%s') sending message with type %u and size %u bytes to peer %u (`%s')\n",
193                 ccc->p[1]->no,
194                 ps,
195                 ntohs (hdr->type),
196                 ntohs (hdr->size),
197                 p->no,
198                 GNUNET_i2s (&p->id));
199     GNUNET_free (ps);
200   }
201
202   return TEST_MESSAGE_SIZE;
203 }
204
205
206 static void
207 sendtask (void *cls)
208 {
209   if (NULL == send_task)
210     ccc->global_ret = GNUNET_NO; /* first call! */
211   send_task = NULL;
212   {
213     char *receiver_s = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
214
215     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216                 "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n",
217                 ccc->p[1]->no, GNUNET_i2s (&ccc->p[1]->id), ccc->p[0]->no, receiver_s);
218     GNUNET_free (receiver_s);
219   }
220   if (0 == messages_recv)
221   {
222     start_normal = GNUNET_TIME_absolute_get();
223   }
224   if (1 == messages_recv)
225   {
226     start_delayed = GNUNET_TIME_absolute_get();
227   }
228
229   th = GNUNET_TRANSPORT_notify_transmit_ready (ccc->p[1]->th,
230                                                &ccc->p[0]->id,
231                                                TEST_MESSAGE_SIZE,
232                                                TIMEOUT_TRANSMIT,
233                                                &notify_ready,
234                                                ccc->p[0]);
235 }
236
237
238 static void
239 notify_disconnect (void *cls,
240                    struct GNUNET_TRANSPORT_TESTING_PeerContext *me,
241                    const struct GNUNET_PeerIdentity *other)
242 {
243   GNUNET_TRANSPORT_TESTING_log_disconnect (cls,
244                                            me,
245                                            other);
246   if (NULL != th)
247   {
248     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
249     th = NULL;
250   }
251 }
252
253
254 int
255 main (int argc, char *argv[])
256 {
257   struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
258     .connect_continuation = &sendtask,
259     .config_file = "test_transport_api_data.conf",
260     .rec = &notify_receive,
261     .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
262     .nd = &notify_disconnect,
263     .shutdown_task = &custom_shutdown,
264     .timeout = TIMEOUT
265   };
266
267   ccc = &my_ccc;
268   if (GNUNET_OK !=
269       GNUNET_TRANSPORT_TESTING_main (2,
270                                      &GNUNET_TRANSPORT_TESTING_connect_check,
271                                      ccc))
272     return 1;
273   return 0;
274 }
275
276 /* end of test_transport_api_manipulation_recv_tcp.c */