aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2011-02-03 16:11:49 +0000
committerNathan S. Evans <evans@in.tum.de>2011-02-03 16:11:49 +0000
commit7a441138e549ac5bbc1974a23653bb77c51a8bb1 (patch)
tree04405168216df13a370a106fd7f92f554887dae9
parent7b7f7a9152bec8f8bd6d85e88cc57ba231a22bd2 (diff)
downloadgnunet-7a441138e549ac5bbc1974a23653bb77c51a8bb1.tar.gz
gnunet-7a441138e549ac5bbc1974a23653bb77c51a8bb1.zip
unix domain socket transport, associated test cases
-rw-r--r--src/transport/Makefile.am84
-rw-r--r--src/transport/plugin_transport_udp.c2
-rw-r--r--src/transport/plugin_transport_unix.c1155
-rw-r--r--src/transport/test_quota_compliance.c25
-rw-r--r--src/transport/test_quota_compliance_unix_peer1.conf104
-rw-r--r--src/transport/test_quota_compliance_unix_peer2.conf102
-rw-r--r--src/transport/test_transport_api.c12
-rw-r--r--src/transport/test_transport_api_reliability.c24
-rw-r--r--src/transport/test_transport_api_unix_peer1.conf110
-rw-r--r--src/transport/test_transport_api_unix_peer2.conf108
-rw-r--r--src/transport/test_transport_api_unreliability.c922
11 files changed, 2632 insertions, 16 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 0498408f2..c3b90cc9d 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -43,6 +43,10 @@ endif
43endif 43endif
44 44
45if LINUX 45if LINUX
46UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la
47UNIX_PLUGIN_TEST = test_transport_api_unix
48UNIX_REL_TEST = test_transport_api_unreliability_unix
49UNIX_QUOTA_TEST = test_quota_compliance_unix
46NATBIN = gnunet-nat-server gnunet-nat-client 50NATBIN = gnunet-nat-server gnunet-nat-client
47install-exec-hook: 51install-exec-hook:
48 chown root $(bindir)/gnunet-nat-server $(bindir)/gnunet-nat-client $(bindir)/gnunet-wlan || true 52 chown root $(bindir)/gnunet-nat-server $(bindir)/gnunet-nat-client $(bindir)/gnunet-wlan || true
@@ -114,6 +118,7 @@ gnunet_service_transport_DEPENDENCIES = \
114plugin_LTLIBRARIES = \ 118plugin_LTLIBRARIES = \
115 libgnunet_plugin_transport_tcp.la \ 119 libgnunet_plugin_transport_tcp.la \
116 libgnunet_plugin_transport_udp.la \ 120 libgnunet_plugin_transport_udp.la \
121 $(UNIX_PLUGIN_LA) \
117 $(HTTP_PLUGIN_LA) \ 122 $(HTTP_PLUGIN_LA) \
118 $(HTTPS_PLUGIN_LA) \ 123 $(HTTPS_PLUGIN_LA) \
119 $(WLAN_PLUGIN_LA) \ 124 $(WLAN_PLUGIN_LA) \
@@ -157,16 +162,16 @@ libgnunet_plugin_transport_udp_la_LIBADD = \
157 $(top_builddir)/src/util/libgnunetutil.la 162 $(top_builddir)/src/util/libgnunetutil.la
158libgnunet_plugin_transport_udp_la_LDFLAGS = \ 163libgnunet_plugin_transport_udp_la_LDFLAGS = \
159 $(GN_PLUGIN_LDFLAGS) 164 $(GN_PLUGIN_LDFLAGS)
160 165
161#libgnunet_plugin_transport_udp_nat_la_SOURCES = \ 166libgnunet_plugin_transport_unix_la_SOURCES = \
162# plugin_transport_udp_nat.c 167 plugin_transport_unix.c
163#libgnunet_plugin_transport_udp_nat_la_LIBADD = \ 168libgnunet_plugin_transport_unix_la_LIBADD = \
164# $(top_builddir)/src/hello/libgnunethello.la \ 169 $(top_builddir)/src/hello/libgnunethello.la \
165# $(top_builddir)/src/statistics/libgnunetstatistics.la \ 170 $(top_builddir)/src/statistics/libgnunetstatistics.la \
166# $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 171 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
167# $(top_builddir)/src/util/libgnunetutil.la 172 $(top_builddir)/src/util/libgnunetutil.la
168#libgnunet_plugin_transport_udp_nat_la_LDFLAGS = \ 173libgnunet_plugin_transport_unix_la_LDFLAGS = \
169# $(GN_PLUGIN_LDFLAGS) 174 $(GN_PLUGIN_LDFLAGS)
170 175
171libgnunet_plugin_transport_http_la_SOURCES = \ 176libgnunet_plugin_transport_http_la_SOURCES = \
172 plugin_transport_http.c 177 plugin_transport_http.c
@@ -199,6 +204,7 @@ check_PROGRAMS = \
199 test_transport_api_tcp \ 204 test_transport_api_tcp \
200 test_transport_api_tcp_nat \ 205 test_transport_api_tcp_nat \
201 test_transport_api_udp \ 206 test_transport_api_udp \
207 $(UNIX_PLUGIN_TEST) \
202 test_transport_api_udp_nat \ 208 test_transport_api_udp_nat \
203 $(HTTP_PLUGIN_TEST) \ 209 $(HTTP_PLUGIN_TEST) \
204 $(HTTP_API_TEST) \ 210 $(HTTP_API_TEST) \
@@ -208,13 +214,16 @@ check_PROGRAMS = \
208 test_transport_api_multi \ 214 test_transport_api_multi \
209 test_transport_api_reliability_tcp \ 215 test_transport_api_reliability_tcp \
210 test_transport_api_reliability_tcp_nat \ 216 test_transport_api_reliability_tcp_nat \
211 test_transport_api_reliability_udp \ 217 test_transport_api_unreliability_udp \
218 test_transport_api_unreliability_unix \
219 $(UNIX_REL_TEST) \
212 $(HTTP_REL_TEST) \ 220 $(HTTP_REL_TEST) \
213 $(HTTPS_REL_TEST) \ 221 $(HTTPS_REL_TEST) \
214 test_quota_compliance_tcp \ 222 test_quota_compliance_tcp \
215 test_quota_compliance_tcp_asymmetric_recv_constant \ 223 test_quota_compliance_tcp_asymmetric_recv_constant \
216 test_quota_compliance_udp \ 224 test_quota_compliance_udp \
217 test_quota_compliance_udp_asymmetric_recv_constant \ 225 test_quota_compliance_udp_asymmetric_recv_constant \
226 $(UNIX_QUOTA_TEST) \
218 $(HTTP_QUOTA_TEST) \ 227 $(HTTP_QUOTA_TEST) \
219 $(HTTPS_QUOTA_TEST) 228 $(HTTPS_QUOTA_TEST)
220# TODO: add tests for nat, etc. 229# TODO: add tests for nat, etc.
@@ -224,6 +233,7 @@ TESTS = \
224 test_transport_api_tcp \ 233 test_transport_api_tcp \
225 test_transport_api_tcp_nat \ 234 test_transport_api_tcp_nat \
226 test_transport_api_udp \ 235 test_transport_api_udp \
236 $(UNIX_PLUGIN_TEST) \
227 test_transport_api_udp_nat \ 237 test_transport_api_udp_nat \
228 $(HTTP_PLUGIN_TEST) \ 238 $(HTTP_PLUGIN_TEST) \
229 $(HTTP_API_TEST) \ 239 $(HTTP_API_TEST) \
@@ -233,12 +243,15 @@ TESTS = \
233 test_transport_api_multi \ 243 test_transport_api_multi \
234 test_transport_api_reliability_tcp \ 244 test_transport_api_reliability_tcp \
235 test_transport_api_reliability_tcp_nat \ 245 test_transport_api_reliability_tcp_nat \
246 test_transport_api_unreliability_udp \
247 test_transport_api_unreliability_unix \
236 $(HTTP_REL_TEST) \ 248 $(HTTP_REL_TEST) \
237 $(HTTPS_REL_TEST) \ 249 $(HTTPS_REL_TEST) \
238 test_quota_compliance_tcp \ 250 test_quota_compliance_tcp \
239 test_quota_compliance_tcp_asymmetric_recv_constant \ 251 test_quota_compliance_tcp_asymmetric_recv_constant \
240 test_quota_compliance_udp \ 252 test_quota_compliance_udp \
241 test_quota_compliance_udp_asymmetric_recv_constant \ 253 test_quota_compliance_udp_asymmetric_recv_constant \
254 $(UNIX_QUOTA_TEST) \
242 $(HTTP_QUOTA_TEST) \ 255 $(HTTP_QUOTA_TEST) \
243 $(HTTPS_QUOTA_TEST) 256 $(HTTPS_QUOTA_TEST)
244endif 257endif
@@ -271,19 +284,31 @@ test_transport_api_reliability_udp_SOURCES = \
271 test_transport_api_reliability.c 284 test_transport_api_reliability.c
272test_transport_api_reliability_udp_LDADD = \ 285test_transport_api_reliability_udp_LDADD = \
273 $(top_builddir)/src/transport/libgnunettransport.la \ 286 $(top_builddir)/src/transport/libgnunettransport.la \
274 $(top_builddir)/src/util/libgnunetutil.la 287 $(top_builddir)/src/util/libgnunetutil.la
288
289test_transport_api_reliability_unix_SOURCES = \
290 test_transport_api_reliability.c
291test_transport_api_reliability_unix_LDADD = \
292 $(top_builddir)/src/transport/libgnunettransport.la \
293 $(top_builddir)/src/util/libgnunetutil.la
275 294
276test_transport_api_udp_SOURCES = \ 295test_transport_api_udp_SOURCES = \
277 test_transport_api.c 296 test_transport_api.c
278test_transport_api_udp_LDADD = \ 297test_transport_api_udp_LDADD = \
279 $(top_builddir)/src/transport/libgnunettransport.la \ 298 $(top_builddir)/src/transport/libgnunettransport.la \
280 $(top_builddir)/src/util/libgnunetutil.la 299 $(top_builddir)/src/util/libgnunetutil.la
281 300
282test_transport_api_udp_nat_SOURCES = \ 301test_transport_api_udp_nat_SOURCES = \
283 test_transport_api.c 302 test_transport_api.c
284test_transport_api_udp_nat_LDADD = \ 303test_transport_api_udp_nat_LDADD = \
285 $(top_builddir)/src/transport/libgnunettransport.la \ 304 $(top_builddir)/src/transport/libgnunettransport.la \
286 $(top_builddir)/src/util/libgnunetutil.la 305 $(top_builddir)/src/util/libgnunetutil.la
306
307test_transport_api_unix_SOURCES = \
308 test_transport_api.c
309test_transport_api_unix_LDADD = \
310 $(top_builddir)/src/transport/libgnunettransport.la \
311 $(top_builddir)/src/util/libgnunetutil.la
287 312
288test_plugin_transport_http_SOURCES = \ 313test_plugin_transport_http_SOURCES = \
289 test_plugin_transport_http.c 314 test_plugin_transport_http.c
@@ -324,6 +349,18 @@ test_transport_api_reliability_https_SOURCES = \
324test_transport_api_reliability_https_LDADD = \ 349test_transport_api_reliability_https_LDADD = \
325 $(top_builddir)/src/transport/libgnunettransport.la \ 350 $(top_builddir)/src/transport/libgnunettransport.la \
326 $(top_builddir)/src/util/libgnunetutil.la 351 $(top_builddir)/src/util/libgnunetutil.la
352
353test_transport_api_unreliability_unix_SOURCES = \
354 test_transport_api_unreliability.c
355test_transport_api_unreliability_unix_LDADD = \
356 $(top_builddir)/src/transport/libgnunettransport.la \
357 $(top_builddir)/src/util/libgnunetutil.la
358
359test_transport_api_unreliability_udp_SOURCES = \
360 test_transport_api_unreliability.c
361test_transport_api_unreliability_udp_LDADD = \
362 $(top_builddir)/src/transport/libgnunettransport.la \
363 $(top_builddir)/src/util/libgnunetutil.la
327 364
328if HAVE_PCAP 365if HAVE_PCAP
329if LINUX 366if LINUX
@@ -407,6 +444,19 @@ test_quota_compliance_udp_asymmetric_recv_constant_LDADD = \
407# $(top_builddir)/src/transport/libgnunettransport.la \ 444# $(top_builddir)/src/transport/libgnunettransport.la \
408# $(top_builddir)/src/util/libgnunetutil.la 445# $(top_builddir)/src/util/libgnunetutil.la
409 446
447test_quota_compliance_unix_SOURCES = \
448 test_quota_compliance.c
449test_quota_compliance_unix_LDADD = \
450 $(top_builddir)/src/transport/libgnunettransport.la \
451 $(top_builddir)/src/util/libgnunetutil.la
452
453test_quota_compliance_unix_asymmetric_recv_constant_SOURCES = \
454 test_quota_compliance.c
455test_quota_compliance_unix_asymmetric_recv_constant_LDADD = \
456 $(top_builddir)/src/transport/libgnunettransport.la \
457 $(top_builddir)/src/util/libgnunetutil.la
458
459
410test_transport_api_multi_SOURCES = \ 460test_transport_api_multi_SOURCES = \
411 test_transport_api.c 461 test_transport_api.c
412test_transport_api_multi_LDADD = \ 462test_transport_api_multi_LDADD = \
@@ -419,6 +469,8 @@ EXTRA_DIST = \
419 test_transport_api_tcp_peer2.conf \ 469 test_transport_api_tcp_peer2.conf \
420 test_transport_api_udp_peer1.conf \ 470 test_transport_api_udp_peer1.conf \
421 test_transport_api_udp_peer2.conf \ 471 test_transport_api_udp_peer2.conf \
472 test_transport_api_unix_peer1.conf \
473 test_transport_api_unix_peer2.conf \
422 test_transport_api_udp_nat_peer1.conf \ 474 test_transport_api_udp_nat_peer1.conf \
423 test_transport_api_udp_nat_peer2.conf \ 475 test_transport_api_udp_nat_peer2.conf \
424 test_transport_api_tcp_nat_peer1.conf \ 476 test_transport_api_tcp_nat_peer1.conf \
@@ -446,4 +498,6 @@ EXTRA_DIST = \
446 test_quota_compliance_https_peer1.conf \ 498 test_quota_compliance_https_peer1.conf \
447 test_quota_compliance_https_peer2.conf \ 499 test_quota_compliance_https_peer2.conf \
448 test_quota_compliance_udp_peer1.conf \ 500 test_quota_compliance_udp_peer1.conf \
449 test_quota_compliance_udp_peer2.conf 501 test_quota_compliance_udp_peer2.conf \
502 test_quota_compliance_unix_peer1.conf \
503 test_quota_compliance_unix_peer2.conf
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 21f2b17d7..ca6bbe138 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -662,6 +662,8 @@ udp_real_send (void *cls,
662 GNUNET_NETWORK_socket_sendto (send_handle, message, ssize, 662 GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
663 sb, 663 sb,
664 sbs); 664 sbs);
665 if (GNUNET_SYSERR == sent)
666 GNUNET_log_strerror(GNUNET_ERROR_TYPE_DEBUG, "sendto");
665 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 667 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
666 "UDP transmit %u-byte message to %s (%d: %s)\n", 668 "UDP transmit %u-byte message to %s (%d: %s)\n",
667 (unsigned int) ssize, 669 (unsigned int) ssize,
diff --git a/src/transport/plugin_transport_unix.c b/src/transport/plugin_transport_unix.c
new file mode 100644
index 000000000..4d08a252b
--- /dev/null
+++ b/src/transport/plugin_transport_unix.c
@@ -0,0 +1,1155 @@
1/*
2 This file is part of GNUnet
3 (C) 2010 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file transport/plugin_transport_unix.c
23 * @brief Transport plugin using unix domain sockets (!)
24 * Clearly, can only be used locally on Unix/Linux hosts...
25 * ONLY INTENDED FOR TESTING!!!
26 * @author Christian Grothoff
27 * @author Nathan Evans
28 */
29
30#include "platform.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_connection_lib.h"
33#include "gnunet_container_lib.h"
34#include "gnunet_os_lib.h"
35#include "gnunet_peerinfo_service.h"
36#include "gnunet_protocols.h"
37#include "gnunet_resolver_service.h"
38#include "gnunet_server_lib.h"
39#include "gnunet_signatures.h"
40#include "gnunet_statistics_service.h"
41#include "gnunet_transport_service.h"
42#include "gnunet_transport_plugin.h"
43#include "transport.h"
44
45#define DEBUG_UNIX GNUNET_YES
46
47#define MAX_PROBES 20
48
49/*
50 * Transport cost to peer, always 1 for UNIX (direct connection)
51 */
52#define UNIX_DIRECT_DISTANCE 1
53
54#define DEFAULT_NAT_PORT 0
55
56/**
57 * How long until we give up on transmitting the welcome message?
58 */
59#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
60
61/**
62 * Starting port for listening and sending, eventually a config value
63 */
64#define UNIX_NAT_DEFAULT_PORT 22086
65
66/**
67 * UNIX Message-Packet header.
68 */
69struct UNIXMessage
70{
71 /**
72 * Message header.
73 */
74 struct GNUNET_MessageHeader header;
75
76 /**
77 * What is the identity of the sender (GNUNET_hash of public key)
78 */
79 struct GNUNET_PeerIdentity sender;
80
81};
82
83/**
84 * Network format for IPv4 addresses.
85 */
86struct IPv4UdpAddress
87{
88 /**
89 * IPv4 address, in network byte order.
90 */
91 uint32_t ipv4_addr GNUNET_PACKED;
92
93 /**
94 * Port number, in network byte order.
95 */
96 uint16_t u_port GNUNET_PACKED;
97};
98
99
100/**
101 * Network format for IPv6 addresses.
102 */
103struct IPv6UdpAddress
104{
105 /**
106 * IPv6 address.
107 */
108 struct in6_addr ipv6_addr GNUNET_PACKED;
109
110 /**
111 * Port number, in network byte order.
112 */
113 uint16_t u6_port GNUNET_PACKED;
114};
115
116/* Forward definition */
117struct Plugin;
118
119struct PrettyPrinterContext
120{
121 GNUNET_TRANSPORT_AddressStringCallback asc;
122 void *asc_cls;
123 uint16_t port;
124};
125
126struct RetrySendContext
127{
128
129 /**
130 * Main plugin handle.
131 */
132 struct Plugin *plugin;
133
134 /**
135 * Address of recipient.
136 */
137 char *addr;
138
139 /**
140 * Length of address.
141 */
142 ssize_t addrlen;
143
144 /**
145 * Message to send.
146 */
147 char *msg;
148
149 /**
150 * Size of the message.
151 */
152 int msg_size;
153
154 /**
155 * Handle to send message out on.
156 */
157 struct GNUNET_NETWORK_Handle *send_handle;
158
159 /**
160 * Continuation to call on success or
161 * timeout.
162 */
163 GNUNET_TRANSPORT_TransmitContinuation cont;
164
165 /**
166 * Closure for continuation.
167 */
168 void *cont_cls;
169
170 /**
171 * The peer the message is destined for.
172 */
173 struct GNUNET_PeerIdentity target;
174
175 /**
176 * How long before not retrying any longer.
177 */
178 struct GNUNET_TIME_Absolute timeout;
179
180 /**
181 * How long the last message was delayed.
182 */
183 struct GNUNET_TIME_Relative delay;
184
185 /**
186 * The actual retry task.
187 */
188 GNUNET_SCHEDULER_TaskIdentifier retry_task;
189
190 /**
191 * The priority of the message.
192 */
193 unsigned int priority;
194};
195
196/**
197 * Local network addresses (actual unix path follows).
198 */
199struct LocalAddrList
200{
201
202 /**
203 * This is a doubly linked list.
204 */
205 struct LocalAddrList *next;
206
207 /**
208 * This is a doubly linked list.
209 */
210 struct LocalAddrList *prev;
211
212 /**
213 * Number of bytes of the address that follow
214 */
215 size_t size;
216
217};
218
219
220/**
221 * UNIX NAT "Session"
222 */
223struct PeerSession
224{
225
226 /**
227 * Stored in a linked list.
228 */
229 struct PeerSession *next;
230
231 /**
232 * Pointer to the global plugin struct.
233 */
234 struct Plugin *plugin;
235
236 /**
237 * To whom are we talking to (set to our identity
238 * if we are still waiting for the welcome message)
239 */
240 struct GNUNET_PeerIdentity target;
241
242 /**
243 * Address of the other peer (either based on our 'connect'
244 * call or on our 'accept' call).
245 */
246 void *connect_addr;
247
248 /**
249 * Length of connect_addr.
250 */
251 size_t connect_alen;
252
253 /**
254 * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
255 */
256 int expecting_welcome;
257
258 /**
259 * From which socket do we need to send to this peer?
260 */
261 struct GNUNET_NETWORK_Handle *sock;
262
263 /*
264 * Queue of messages for this peer, in the case that
265 * we have to await a connection...
266 */
267 struct MessageQueue *messages;
268
269};
270
271/**
272 * Information we keep for each of our listen sockets.
273 */
274struct UNIX_Sock_Info
275{
276 /**
277 * The network handle
278 */
279 struct GNUNET_NETWORK_Handle *desc;
280
281 /**
282 * The port we bound to
283 */
284 uint16_t port;
285};
286
287
288/**
289 * Encapsulation of all of the state of the plugin.
290 */
291struct Plugin
292{
293 /**
294 * Our environment.
295 */
296 struct GNUNET_TRANSPORT_PluginEnvironment *env;
297
298 /*
299 * Session of peers with whom we are currently connected
300 */
301 struct PeerSession *sessions;
302
303 /**
304 * ID of task used to update our addresses when one expires.
305 */
306 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
307
308 /**
309 * ID of select task
310 */
311 GNUNET_SCHEDULER_TaskIdentifier select_task;
312
313 /**
314 * Integer to append to unix domain socket.
315 */
316 uint16_t port;
317
318 /**
319 * List of our IP addresses.
320 */
321 struct LocalAddrList *lal_head;
322
323 /**
324 * Tail of our IP address list.
325 */
326 struct LocalAddrList *lal_tail;
327
328 /**
329 * FD Read set
330 */
331 struct GNUNET_NETWORK_FDSet *rs;
332
333 /**
334 * socket that we transmit all data with
335 */
336 struct UNIX_Sock_Info unix_sock;
337
338 /**
339 * Path of our unix domain socket (/tmp/unix-plugin-PORT)
340 */
341 char *unix_socket_path;
342
343};
344
345
346/**
347 * Disconnect from a remote node. Clean up session if we have one for this peer
348 *
349 * @param cls closure for this call (should be handle to Plugin)
350 * @param target the peeridentity of the peer to disconnect
351 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
352 */
353void
354unix_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
355{
356 /** TODO: Implement! */
357 return;
358}
359
360/**
361 * Shutdown the server process (stop receiving inbound traffic). Maybe
362 * restarted later!
363 *
364 * @param cls Handle to the plugin for this transport
365 *
366 * @return returns the number of sockets successfully closed,
367 * should equal the number of sockets successfully opened
368 */
369static int
370unix_transport_server_stop (void *cls)
371{
372 struct Plugin *plugin = cls;
373
374 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
375 {
376 GNUNET_SCHEDULER_cancel (plugin->select_task);
377 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
378 }
379
380 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
381 plugin->unix_sock.desc = NULL;
382
383 return GNUNET_OK;
384}
385
386
387struct PeerSession *
388find_session (struct Plugin *plugin,
389 const struct GNUNET_PeerIdentity *peer)
390{
391 struct PeerSession *pos;
392
393 pos = plugin->sessions;
394 while (pos != NULL)
395 {
396 if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
397 return pos;
398 pos = pos->next;
399 }
400
401 return pos;
402}
403
404/* Forward Declaration */
405static ssize_t
406unix_real_send (void *cls,
407 struct RetrySendContext *incoming_retry_context,
408 struct GNUNET_NETWORK_Handle *send_handle,
409 const struct GNUNET_PeerIdentity *target,
410 const char *msgbuf,
411 size_t msgbuf_size,
412 unsigned int priority,
413 struct GNUNET_TIME_Relative timeout,
414 const void *addr,
415 size_t addrlen,
416 GNUNET_TRANSPORT_TransmitContinuation cont,
417 void *cont_cls);
418
419/**
420 * Retry sending a message.
421 *
422 * @param cls closure a struct RetrySendContext
423 * @param tc context information
424 */
425void retry_send_message (void *cls,
426 const struct GNUNET_SCHEDULER_TaskContext * tc)
427{
428 struct RetrySendContext *retry_ctx = cls;
429
430 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
431 return;
432 unix_real_send (retry_ctx->plugin,
433 retry_ctx,
434 retry_ctx->send_handle,
435 &retry_ctx->target,
436 retry_ctx->msg,
437 retry_ctx->msg_size,
438 retry_ctx->priority,
439 GNUNET_TIME_absolute_get_remaining (retry_ctx->timeout),
440 retry_ctx->addr,
441 retry_ctx->addrlen,
442 retry_ctx->cont,
443 retry_ctx->cont_cls);
444 return;
445}
446
447/**
448 * Actually send out the message, assume we've got the address and
449 * send_handle squared away!
450 *
451 * @param cls closure
452 * @param incoming_retry_context the retry context to use
453 * @param send_handle which handle to send message on
454 * @param target who should receive this message (ignored by UNIX)
455 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
456 * @param msgbuf_size the size of the msgbuf to send
457 * @param priority how important is the message (ignored by UNIX)
458 * @param timeout when should we time out (give up) if we can not transmit?
459 * @param addr the addr to send the message to, needs to be a sockaddr for us
460 * @param addrlen the len of addr
461 * @param cont continuation to call once the message has
462 * been transmitted (or if the transport is ready
463 * for the next transmission call; or if the
464 * peer disconnected...)
465 * @param cont_cls closure for cont
466 *
467 * @return the number of bytes written, -1 on errors
468 */
469static ssize_t
470unix_real_send (void *cls,
471 struct RetrySendContext *incoming_retry_context,
472 struct GNUNET_NETWORK_Handle *send_handle,
473 const struct GNUNET_PeerIdentity *target,
474 const char *msgbuf,
475 size_t msgbuf_size,
476 unsigned int priority,
477 struct GNUNET_TIME_Relative timeout,
478 const void *addr,
479 size_t addrlen,
480 GNUNET_TRANSPORT_TransmitContinuation cont,
481 void *cont_cls)
482{
483 struct Plugin *plugin = cls;
484 struct UNIXMessage *message;
485 struct RetrySendContext *retry_ctx;
486 int ssize;
487 ssize_t sent;
488 const void *sb;
489 size_t sbs;
490 struct sockaddr_un *un;
491 size_t slen;
492
493 if (send_handle == NULL)
494 {
495#if DEBUG_UNIX
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "unix_real_send with send_handle NULL!\n");
498#endif
499 /* failed to open send socket for AF */
500 if (cont != NULL)
501 cont (cont_cls, target, GNUNET_SYSERR);
502 return 0;
503 }
504 if ((addr == NULL) || (addrlen == 0))
505 {
506#if DEBUG_UNIX
507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
508 "unix_real_send called without address, returning!\n");
509#endif
510 if (cont != NULL)
511 cont (cont_cls, target, GNUNET_SYSERR);
512 return 0; /* Can never send if we don't have an address!! */
513 }
514
515 /* Build the message to be sent */
516 message = GNUNET_malloc (sizeof (struct UNIXMessage) + msgbuf_size);
517 ssize = sizeof (struct UNIXMessage) + msgbuf_size;
518
519 message->header.size = htons (ssize);
520 message->header.type = htons (0);
521 memcpy (&message->sender, plugin->env->my_identity,
522 sizeof (struct GNUNET_PeerIdentity));
523 memcpy (&message[1], msgbuf, msgbuf_size);
524
525 un = GNUNET_malloc (sizeof (struct sockaddr_un));
526 un->sun_family = AF_UNIX;
527 slen = strlen (addr) + 1;
528 sent = 0;
529 GNUNET_assert(slen < sizeof(un->sun_path));
530 memcpy (un->sun_path, addr, slen);
531 un->sun_path[slen] = '\0';
532#if LINUX
533 un->sun_path[0] = '\0';
534#endif
535 slen += sizeof (sa_family_t);
536 sb = (struct sockaddr*) un;
537 sbs = slen;
538
539 sent = GNUNET_NETWORK_socket_sendto(send_handle, message, ssize, sb, sbs);
540
541 if (GNUNET_SYSERR == sent)
542 {
543 if (incoming_retry_context == NULL)
544 {
545 retry_ctx = GNUNET_malloc(sizeof(struct RetrySendContext));
546 retry_ctx->addr = GNUNET_malloc(addrlen);
547 retry_ctx->msg = GNUNET_malloc(msgbuf_size);
548 retry_ctx->plugin = plugin;
549 memcpy(retry_ctx->addr, addr, addrlen);
550 memcpy(retry_ctx->msg, msgbuf, msgbuf_size);
551 retry_ctx->msg_size = msgbuf_size;
552 retry_ctx->addrlen = addrlen;
553 retry_ctx->send_handle = send_handle;
554 retry_ctx->cont = cont;
555 retry_ctx->cont_cls = cont_cls;
556 retry_ctx->priority = priority;
557 retry_ctx->timeout = GNUNET_TIME_relative_to_absolute(timeout);
558 memcpy(&retry_ctx->target, target, sizeof(struct GNUNET_PeerIdentity));
559 retry_ctx->delay = GNUNET_TIME_UNIT_MILLISECONDS;
560 }
561 else
562 {
563 retry_ctx = incoming_retry_context;
564 retry_ctx->delay = GNUNET_TIME_relative_multiply(retry_ctx->delay, 2);
565 }
566 retry_ctx->retry_task = GNUNET_SCHEDULER_add_delayed(retry_ctx->delay, &retry_send_message, retry_ctx);
567#if DETAILS
568 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Error when trying to send %d byte message to %s\n", retry_ctx->msg_size, &un->sun_path[1]);
569 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
570 "UNIX transmit %u-byte message to %s (%d: %s)\n",
571 (unsigned int) ssize,
572 GNUNET_a2s (sb, sbs),
573 (int) sent,
574 (sent < 0) ? STRERROR (errno) : "ok");
575#endif
576 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
577 return ssize;
578 }
579 if (incoming_retry_context != NULL)
580 {
581 GNUNET_free(incoming_retry_context->msg);
582 GNUNET_free(incoming_retry_context->addr);
583 GNUNET_free(incoming_retry_context);
584 }
585#if DEBUG_UNIX
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "UNIX transmit %u-byte message to %s (%d: %s)\n",
588 (unsigned int) ssize,
589 GNUNET_a2s (sb, sbs),
590 (int) sent,
591 (sent < 0) ? STRERROR (errno) : "ok");
592#endif
593 if (cont != NULL)
594 {
595 if (sent == GNUNET_SYSERR)
596 cont (cont_cls, target, GNUNET_SYSERR);
597 else
598 {
599 cont (cont_cls, target, GNUNET_OK);
600 }
601 }
602
603 GNUNET_free (message);
604 return sent;
605}
606
607
608/**
609 * Function that can be used by the transport service to transmit
610 * a message using the plugin.
611 *
612 * @param cls closure
613 * @param target who should receive this message (ignored by UNIX)
614 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
615 * @param msgbuf_size the size of the msgbuf to send
616 * @param priority how important is the message (ignored by UNIX)
617 * @param timeout when should we time out (give up) if we can not transmit?
618 * @param session identifier used for this session (can be NULL)
619 * @param addr the addr to send the message to, needs to be a sockaddr for us
620 * @param addrlen the len of addr
621 * @param force_address not used, we had better have an address to send to
622 * because we are stateless!!
623 * @param cont continuation to call once the message has
624 * been transmitted (or if the transport is ready
625 * for the next transmission call; or if the
626 * peer disconnected...)
627 * @param cont_cls closure for cont
628 *
629 * @return the number of bytes written (may return 0 and the message can
630 * still be transmitted later!)
631 */
632static ssize_t
633unix_plugin_send (void *cls,
634 const struct GNUNET_PeerIdentity *target,
635 const char *msgbuf,
636 size_t msgbuf_size,
637 unsigned int priority,
638 struct GNUNET_TIME_Relative timeout,
639 struct Session *session,
640 const void *addr,
641 size_t addrlen,
642 int force_address,
643 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
644{
645 struct Plugin *plugin = cls;
646 ssize_t sent;
647
648 if (force_address == GNUNET_SYSERR)
649 return GNUNET_SYSERR;
650 GNUNET_assert (NULL == session);
651
652#if DEBUG_UNIX
653 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Asked to send message to `%s'\n", (char *)addr);
654#endif
655 sent = unix_real_send(cls,
656 NULL,
657 plugin->unix_sock.desc,
658 target,
659 msgbuf, msgbuf_size,
660 priority, timeout, addr, addrlen,
661 cont, cont_cls);
662#if DEBUG_UNIX
663 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sent %d bytes to `%s'\n", sent, (char *)addr);
664#endif
665 if (sent == GNUNET_SYSERR)
666 return 0;
667 return sent;
668}
669
670
671static void
672add_to_address_list (struct Plugin *plugin,
673 const void *arg,
674 size_t arg_size)
675{
676 struct LocalAddrList *lal;
677
678 lal = plugin->lal_head;
679 while (NULL != lal)
680 {
681 if ( (lal->size == arg_size) &&
682 (0 == memcmp (&lal[1], arg, arg_size)) )
683 return;
684 lal = lal->next;
685 }
686 lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size);
687 lal->size = arg_size;
688 memcpy (&lal[1], arg, arg_size);
689 GNUNET_CONTAINER_DLL_insert (plugin->lal_head,
690 plugin->lal_tail,
691 lal);
692}
693
694
695/**
696 * Demultiplexer for UNIX messages
697 *
698 * @param plugin the main plugin for this transport
699 * @param sender from which peer the message was received
700 * @param currhdr pointer to the header of the message
701 * @param sender_addr the address from which the message was received
702 * @param fromlen the length of the address
703 */
704static void
705unix_demultiplexer(struct Plugin *plugin,
706 struct GNUNET_PeerIdentity *sender,
707 const struct GNUNET_MessageHeader *currhdr,
708 const struct sockaddr_un *un,
709 size_t fromlen)
710{
711 struct GNUNET_TRANSPORT_ATS_Information distance[2];
712
713 distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
714 distance[0].value = htonl (UNIX_DIRECT_DISTANCE);
715 distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
716 distance[1].value = htonl (0);
717
718 GNUNET_assert(fromlen >= sizeof(struct sockaddr_un));
719
720#if DEBUG_UNIX
721 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received message from %s\n", un->sun_path);
722#endif
723 plugin->env->receive (plugin->env->cls, sender, currhdr,
724 (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
725 NULL, un->sun_path, strlen(un->sun_path) + 1);
726}
727
728
729/*
730 * @param cls the plugin handle
731 * @param tc the scheduling context (for rescheduling this function again)
732 *
733 * We have been notified that our writeset has something to read. We don't
734 * know which socket needs to be read, so we have to check each one
735 * Then reschedule this function to be called again once more is available.
736 *
737 */
738static void
739unix_plugin_select (void *cls,
740 const struct GNUNET_SCHEDULER_TaskContext *tc)
741{
742 struct Plugin *plugin = cls;
743 char buf[65536];
744 struct UNIXMessage *msg;
745 struct GNUNET_PeerIdentity sender;
746 //socklen_t fromlen;
747 struct sockaddr_un un;
748 socklen_t addrlen;
749 ssize_t ret;
750 int offset;
751 int tsize;
752 char *msgbuf;
753 const struct GNUNET_MessageHeader *currhdr;
754 uint16_t csize;
755
756 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
757 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
758 return;
759
760 addrlen = sizeof(un);
761 memset(&un, 0, sizeof(un));
762 GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->unix_sock.desc));
763 ret =
764 GNUNET_NETWORK_socket_recvfrom (plugin->unix_sock.desc, buf, sizeof (buf),
765 (struct sockaddr *)&un, &addrlen);
766
767 if (ret == GNUNET_SYSERR)
768 {
769 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
770 plugin->select_task =
771 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
772 GNUNET_SCHEDULER_NO_TASK,
773 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
774 NULL, &unix_plugin_select, plugin);
775 return;
776 }
777 else
778 {
779#if LINUX
780 un.sun_path[0] = '/';
781#endif
782#if DEBUG_UNIX
783 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes from socket %s\n", ret, &un.sun_path[0]);
784#endif
785 }
786
787 GNUNET_assert (AF_UNIX == (un.sun_family));
788
789 msg = (struct UNIXMessage *) buf;
790 csize = ntohs (msg->header.size);
791 if ( (csize < sizeof (struct UNIXMessage)) ||
792 (csize > ret) )
793 {
794 GNUNET_break_op (0);
795 plugin->select_task =
796 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
797 GNUNET_SCHEDULER_NO_TASK,
798 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
799 NULL, &unix_plugin_select, plugin);
800 return;
801 }
802 msgbuf = (char *)&msg[1];
803 memcpy (&sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
804 offset = 0;
805 tsize = csize - sizeof (struct UNIXMessage);
806 while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
807 {
808 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
809 csize = ntohs (currhdr->size);
810 if ( (csize < sizeof (struct GNUNET_MessageHeader)) ||
811 (csize > tsize - offset) )
812 {
813 GNUNET_break_op (0);
814 break;
815 }
816 unix_demultiplexer(plugin, &sender, currhdr,
817 &un, sizeof(un));
818 offset += csize;
819 }
820 plugin->select_task =
821 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
822 GNUNET_SCHEDULER_NO_TASK,
823 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
824 NULL, &unix_plugin_select, plugin);
825}
826
827/**
828 * Create a slew of UNIX sockets. If possible, use IPv6 and IPv4.
829 *
830 * @param cls closure for server start, should be a struct Plugin *
831 * @return number of sockets created or GNUNET_SYSERR on error
832*/
833static int
834unix_transport_server_start (void *cls)
835{
836 struct Plugin *plugin = cls;
837
838 struct sockaddr *serverAddr;
839 socklen_t addrlen;
840 int sockets_created;
841 struct sockaddr_un *un;
842 size_t slen;
843
844 un = GNUNET_malloc (sizeof (struct sockaddr_un));
845 un->sun_family = AF_UNIX;
846 slen = strlen (plugin->unix_socket_path) + 1;
847
848 GNUNET_assert(slen < sizeof(un->sun_path));
849 memcpy (un->sun_path, plugin->unix_socket_path, slen);
850 un->sun_path[slen] = '\0';
851 slen += sizeof (sa_family_t);
852 serverAddr = (struct sockaddr*) un;
853 addrlen = slen;
854 sockets_created = 0;
855#if LINUX
856 un->sun_path[0] = '\0';
857#endif
858
859 plugin->unix_sock.desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
860 if (NULL == plugin->unix_sock.desc)
861 {
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
863 }
864 else
865 {
866 if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen) !=
867 GNUNET_OK)
868 {
869#if DEBUG_UNIX
870 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
871 "UNIX Binding failed!\n");
872#endif
873 }
874 else
875 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", &un->sun_path[0]);
876 if (plugin->unix_sock.desc != NULL)
877 sockets_created++;
878 }
879
880 plugin->rs = GNUNET_NETWORK_fdset_create ();
881 GNUNET_NETWORK_fdset_zero (plugin->rs);
882 GNUNET_NETWORK_fdset_set (plugin->rs,
883 plugin->unix_sock.desc);
884
885 plugin->select_task =
886 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
887 GNUNET_SCHEDULER_NO_TASK,
888 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
889 NULL, &unix_plugin_select, plugin);
890 return sockets_created;
891}
892
893
894/**
895 * Function that will be called to check if a binary address for this
896 * plugin is well-formed and corresponds to an address for THIS peer
897 * (as per our configuration). Naturally, if absolutely necessary,
898 * plugins can be a bit conservative in their answer, but in general
899 * plugins should make sure that the address does not redirect
900 * traffic to a 3rd party that might try to man-in-the-middle our
901 * traffic.
902 *
903 * @param cls closure, should be our handle to the Plugin
904 * @param addr pointer to the address
905 * @param addrlen length of addr
906 * @return GNUNET_OK if this is a plausible address for this peer
907 * and transport, GNUNET_SYSERR if not
908 *
909 */
910static int
911unix_check_address (void *cls,
912 const void *addr,
913 size_t addrlen)
914{
915
916#if DEBUG_UNIX
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
918 "Informing transport service about my address `%s'\n",
919 (char *)addr);
920#endif
921 return GNUNET_OK;
922}
923
924
925/**
926 * Append our port and forward the result.
927 */
928static void
929append_port (void *cls, const char *hostname)
930{
931 struct PrettyPrinterContext *ppc = cls;
932 char *ret;
933
934 if (hostname == NULL)
935 {
936 ppc->asc (ppc->asc_cls, NULL);
937 GNUNET_free (ppc);
938 return;
939 }
940 GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
941 ppc->asc (ppc->asc_cls, ret);
942 GNUNET_free (ret);
943}
944
945
946/**
947 * Convert the transports address to a nice, human-readable
948 * format.
949 *
950 * @param cls closure
951 * @param type name of the transport that generated the address
952 * @param addr one of the addresses of the host, NULL for the last address
953 * the specific address format depends on the transport
954 * @param addrlen length of the address
955 * @param numeric should (IP) addresses be displayed in numeric form?
956 * @param timeout after how long should we give up?
957 * @param asc function to call on each string
958 * @param asc_cls closure for asc
959 */
960static void
961unix_plugin_address_pretty_printer (void *cls,
962 const char *type,
963 const void *addr,
964 size_t addrlen,
965 int numeric,
966 struct GNUNET_TIME_Relative timeout,
967 GNUNET_TRANSPORT_AddressStringCallback asc,
968 void *asc_cls)
969{
970 struct Plugin *plugin = cls;
971 struct PrettyPrinterContext *ppc;
972 const void *sb;
973 size_t sbs;
974 struct sockaddr_in a4;
975 struct sockaddr_in6 a6;
976 const struct IPv4UdpAddress *u4;
977 const struct IPv6UdpAddress *u6;
978 uint16_t port;
979
980 if (addrlen == sizeof (struct IPv6UdpAddress))
981 {
982 u6 = addr;
983 memset (&a6, 0, sizeof (a6));
984 a6.sin6_family = AF_INET6;
985 a6.sin6_port = u6->u6_port;
986 memcpy (&a6.sin6_addr,
987 &u6->ipv6_addr,
988 sizeof (struct in6_addr));
989 port = ntohs (u6->u6_port);
990 sb = &a6;
991 sbs = sizeof (a6);
992 }
993 else if (addrlen == sizeof (struct IPv4UdpAddress))
994 {
995 u4 = addr;
996 memset (&a4, 0, sizeof (a4));
997 a4.sin_family = AF_INET;
998 a4.sin_port = u4->u_port;
999 a4.sin_addr.s_addr = u4->ipv4_addr;
1000 port = ntohs (u4->u_port);
1001 sb = &a4;
1002 sbs = sizeof (a4);
1003 }
1004 else
1005 {
1006 /* invalid address */
1007 GNUNET_break_op (0);
1008 asc (asc_cls, NULL);
1009 return;
1010 }
1011 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1012 ppc->asc = asc;
1013 ppc->asc_cls = asc_cls;
1014 ppc->port = port;
1015 GNUNET_RESOLVER_hostname_get (plugin->env->cfg,
1016 sb,
1017 sbs,
1018 !numeric, timeout, &append_port, ppc);
1019}
1020
1021/**
1022 * Function called for a quick conversion of the binary address to
1023 * a numeric address. Note that the caller must not free the
1024 * address and that the next call to this function is allowed
1025 * to override the address again.
1026 *
1027 * @param cls closure
1028 * @param addr binary address
1029 * @param addrlen length of the address
1030 * @return string representing the same address
1031 */
1032static const char*
1033unix_address_to_string (void *cls,
1034 const void *addr,
1035 size_t addrlen)
1036{
1037 static char rbuf[INET6_ADDRSTRLEN + 10];
1038 char buf[INET6_ADDRSTRLEN];
1039 const void *sb;
1040 struct in_addr a4;
1041 struct in6_addr a6;
1042 const struct IPv4UdpAddress *t4;
1043 const struct IPv6UdpAddress *t6;
1044 int af;
1045 uint16_t port;
1046
1047 if (addrlen == sizeof (struct IPv6UdpAddress))
1048 {
1049 t6 = addr;
1050 af = AF_INET6;
1051 port = ntohs (t6->u6_port);
1052 memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1053 sb = &a6;
1054 }
1055 else if (addrlen == sizeof (struct IPv4UdpAddress))
1056 {
1057 t4 = addr;
1058 af = AF_INET;
1059 port = ntohs (t4->u_port);
1060 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1061 sb = &a4;
1062 }
1063 else
1064 return NULL;
1065 inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1066 GNUNET_snprintf (rbuf,
1067 sizeof (rbuf),
1068 "%s:%u",
1069 buf,
1070 port);
1071 return rbuf;
1072}
1073
1074/**
1075 * The exported method. Makes the core api available via a global and
1076 * returns the unix transport API.
1077 */
1078void *
1079libgnunet_plugin_transport_unix_init (void *cls)
1080{
1081 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1082 unsigned long long port;
1083 struct GNUNET_TRANSPORT_PluginFunctions *api;
1084 struct Plugin *plugin;
1085 int sockets_created;
1086
1087 if (GNUNET_OK !=
1088 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1089 "transport-unix",
1090 "PORT",
1091 &port))
1092 port = UNIX_NAT_DEFAULT_PORT;
1093 else if (port > 65535)
1094 {
1095 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1096 _("Given `%s' option is out of range: %llu > %u\n"),
1097 "PORT",
1098 port,
1099 65535);
1100 return NULL;
1101 }
1102
1103
1104 plugin = GNUNET_malloc (sizeof (struct Plugin));
1105 plugin->port = port;
1106 plugin->env = env;
1107 GNUNET_asprintf(&plugin->unix_socket_path, "/tmp/unix-plugin-sock.%d", plugin->port);
1108
1109 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1110 api->cls = plugin;
1111
1112 api->send = &unix_plugin_send;
1113 api->disconnect = &unix_disconnect;
1114 api->address_pretty_printer = &unix_plugin_address_pretty_printer;
1115 api->address_to_string = &unix_address_to_string;
1116 api->check_address = &unix_check_address;
1117
1118 add_to_address_list (plugin, plugin->unix_socket_path, strlen(plugin->unix_socket_path) + 1);
1119
1120 sockets_created = unix_transport_server_start (plugin);
1121 if (sockets_created == 0)
1122 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1123 _("Failed to open UNIX sockets\n"));
1124
1125 plugin->env->notify_address(plugin->env->cls,
1126 "unix",
1127 plugin->unix_socket_path,
1128 strlen(plugin->unix_socket_path) + 1,
1129 GNUNET_TIME_UNIT_FOREVER_REL);
1130 return api;
1131}
1132
1133void *
1134libgnunet_plugin_transport_unix_done (void *cls)
1135{
1136 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1137 struct Plugin *plugin = api->cls;
1138 struct LocalAddrList *lal;
1139
1140 unix_transport_server_stop (plugin);
1141
1142 GNUNET_NETWORK_fdset_destroy (plugin->rs);
1143 while (NULL != (lal = plugin->lal_head))
1144 {
1145 GNUNET_CONTAINER_DLL_remove (plugin->lal_head,
1146 plugin->lal_tail,
1147 lal);
1148 GNUNET_free (lal);
1149 }
1150 GNUNET_free (plugin);
1151 GNUNET_free (api);
1152 return NULL;
1153}
1154
1155/* end of plugin_transport_unix.c */
diff --git a/src/transport/test_quota_compliance.c b/src/transport/test_quota_compliance.c
index 767ada25e..20a9b1f15 100644
--- a/src/transport/test_quota_compliance.c
+++ b/src/transport/test_quota_compliance.c
@@ -139,6 +139,7 @@ static int is_tcp_nat;
139static int is_http; 139static int is_http;
140static int is_https; 140static int is_https;
141static int is_udp; 141static int is_udp;
142static int is_unix;
142static int is_asymmetric_send_constant; 143static int is_asymmetric_send_constant;
143static int is_asymmetric_recv_constant; 144static int is_asymmetric_recv_constant;
144 145
@@ -731,6 +732,17 @@ run (void *cls,
731 setup_peer (&p1, "test_quota_compliance_udp_peer1.conf"); 732 setup_peer (&p1, "test_quota_compliance_udp_peer1.conf");
732 setup_peer (&p2, "test_quota_compliance_udp_peer2.conf"); 733 setup_peer (&p2, "test_quota_compliance_udp_peer2.conf");
733 } 734 }
735 else if (is_unix)
736 {
737 if (is_asymmetric_recv_constant == GNUNET_YES)
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for UNIX transport plugin\n");
739 else if (is_asymmetric_send_constant == GNUNET_YES)
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for UNIX transport plugin\n");
741 else
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for UNIX transport plugin\n");
743 setup_peer (&p1, "test_quota_compliance_unix_peer1.conf");
744 setup_peer (&p2, "test_quota_compliance_unix_peer2.conf");
745 }
734 else if (is_tcp_nat) 746 else if (is_tcp_nat)
735 { 747 {
736 if (is_asymmetric_recv_constant == GNUNET_YES) 748 if (is_asymmetric_recv_constant == GNUNET_YES)
@@ -777,6 +789,10 @@ main (int argc, char *argv[])
777 { 789 {
778 is_udp = GNUNET_YES; 790 is_udp = GNUNET_YES;
779 } 791 }
792 else if (strstr(argv[0], "unix") != NULL)
793 {
794 is_unix = GNUNET_YES;
795 }
780 796
781 if (strstr(argv[0], "asymmetric_recv") != NULL) 797 if (strstr(argv[0], "asymmetric_recv") != NULL)
782 { 798 {
@@ -810,6 +826,15 @@ main (int argc, char *argv[])
810 else 826 else
811 GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","symmetric"); 827 GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","symmetric");
812 } 828 }
829 else if (is_unix == GNUNET_YES)
830 {
831 if (is_asymmetric_recv_constant == GNUNET_YES)
832 GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_recv_constant");
833 else if (is_asymmetric_send_constant == GNUNET_YES)
834 GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_send_constant");
835 else
836 GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","symmetric");
837 }
813 else if (is_http == GNUNET_YES) 838 else if (is_http == GNUNET_YES)
814 { 839 {
815 if (is_asymmetric_recv_constant == GNUNET_YES) 840 if (is_asymmetric_recv_constant == GNUNET_YES)
diff --git a/src/transport/test_quota_compliance_unix_peer1.conf b/src/transport/test_quota_compliance_unix_peer1.conf
new file mode 100644
index 000000000..ff8ef0537
--- /dev/null
+++ b/src/transport/test_quota_compliance_unix_peer1.conf
@@ -0,0 +1,104 @@
1[PATHS]
2SERVICEHOME = /tmp/test_quota_compliance_peer1/
3DEFAULTCONFIG = test_quota_compliance_unix_peer1.conf
4
5[fs]
6AUTOSTART = NO
7
8[datastore]
9AUTOSTART = NO
10
11[hostlist]
12HTTP-PROXY =
13SERVERS = http://gnunet.org:8080/
14OPTIONS = -b
15BINARY = gnunet-daemon-hostlist
16CONFIG = $DEFAULTCONFIG
17HOME = $SERVICEHOME
18HOSTNAME = localhost
19HTTPPORT = 8080
20
21[topology]
22BINARY = gnunet-daemon-topology
23CONFIG = $DEFAULTCONFIG
24FRIENDS = $SERVICEHOME/friends
25TARGET-CONNECTION-COUNT = 16
26AUTOCONNECT = YES
27FRIENDS-ONLY = NO
28MINIMUM-FRIENDS = 0
29
30[core]
31AUTOSTART = NO
32
33[transport-unix]
34PORT = 4368
35
36
37[transport]
38plugins = unix
39#DEBUG = YES
40PREFIX =
41ACCEPT_FROM6 = ::1;
42ACCEPT_FROM = 127.0.0.1;
43NEIGHBOUR_LIMIT = 50
44BINARY = gnunet-service-transport
45CONFIG = $DEFAULTCONFIG
46HOME = $SERVICEHOME
47HOSTNAME = localhost
48PORT = 4091
49UNIXPATH = /tmp/test_quota_compliance_unix_transport_peer1.sock
50
51[peerinfo]
52TRUST = $SERVICEHOME/data/credit/
53HOSTS = $SERVICEHOME/data/hosts/
54ACCEPT_FROM6 = ::1;
55ACCEPT_FROM = 127.0.0.1;
56BINARY = gnunet-service-peerinfo
57CONFIG = $DEFAULTCONFIG
58HOME = $SERVICEHOME
59HOSTNAME = localhost
60PORT = 4090
61UNIXPATH = /tmp/test_quota_compliance_unix_peerinfo_peer1.sock
62
63[resolver]
64ACCEPT_FROM6 = ::1;
65ACCEPT_FROM = 127.0.0.1;
66BINARY = gnunet-service-resolver
67CONFIG = $DEFAULTCONFIG
68HOME = $SERVICEHOME
69HOSTNAME = localhost
70PORT = 4089
71UNIXPATH = /tmp/test_quota_compliance_unix_resolver_peer1.sock
72
73[statistics]
74ACCEPT_FROM6 = ::1;
75ACCEPT_FROM = 127.0.0.1;
76BINARY = gnunet-service-statistics
77CONFIG = $DEFAULTCONFIG
78HOME = $SERVICEHOME
79HOSTNAME = localhost
80PORT = 4088
81UNIXPATH = /tmp/test_quota_compliance_unix_statistics_peer1.sock
82
83[arm]
84DEFAULTSERVICES =
85ACCEPT_FROM6 = ::1;
86ACCEPT_FROM = 127.0.0.1;
87BINARY = gnunet-service-arm
88CONFIG = $DEFAULTCONFIG
89HOME = $SERVICEHOME
90HOSTNAME = localhost
91PORT = 4087
92UNIXPATH = /tmp/test_quota_compliance_unix_arm_peer1.sock
93
94[TESTING]
95WEAKRANDOM = YES
96
97[gnunetd]
98HOSTKEY = $SERVICEHOME/.hostkey
99
100
101[dht]
102AUTOSTART = NO
103
104
diff --git a/src/transport/test_quota_compliance_unix_peer2.conf b/src/transport/test_quota_compliance_unix_peer2.conf
new file mode 100644
index 000000000..7be68cbbe
--- /dev/null
+++ b/src/transport/test_quota_compliance_unix_peer2.conf
@@ -0,0 +1,102 @@
1[PATHS]
2SERVICEHOME = /tmp/test_quota_compliance_peer2
3DEFAULTCONFIG = test_quota_compliance_unix_peer2.conf
4
5[transport-unix]
6PORT = 3368
7[fs]
8AUTOSTART = NO
9
10[datastore]
11AUTOSTART = NO
12
13[hostlist]
14HTTP-PROXY =
15SERVERS = http://gnunet.org:8080/
16OPTIONS = -b
17BINARY = gnunet-daemon-hostlist
18CONFIG = $DEFAULTCONFIG
19HOME = $SERVICEHOME
20HOSTNAME = localhost
21HTTPPORT = 8080
22
23[topology]
24BINARY = gnunet-daemon-topology
25CONFIG = $DEFAULTCONFIG
26FRIENDS = $SERVICEHOME/friends
27TARGET-CONNECTION-COUNT = 16
28AUTOCONNECT = YES
29FRIENDS-ONLY = NO
30MINIMUM-FRIENDS = 0
31
32[core]
33AUTOSTART = NO
34
35[transport]
36plugins = unix
37#DEBUG = YES
38PREFIX =
39ACCEPT_FROM6 = ::1;
40ACCEPT_FROM = 127.0.0.1;
41NEIGHBOUR_LIMIT = 50
42BINARY = gnunet-service-transport
43CONFIG = $DEFAULTCONFIG
44HOME = $SERVICEHOME
45HOSTNAME = localhost
46PORT = 3091
47UNIXPATH = /tmp/test_quota_compliance_unix_transport_peer2.sock
48
49[peerinfo]
50TRUST = $SERVICEHOME/data/credit/
51HOSTS = $SERVICEHOME/data/hosts/
52ACCEPT_FROM6 = ::1;
53ACCEPT_FROM = 127.0.0.1;
54BINARY = gnunet-service-peerinfo
55CONFIG = $DEFAULTCONFIG
56HOME = $SERVICEHOME
57HOSTNAME = localhost
58PORT = 3090
59UNIXPATH = /tmp/test_quota_compliance_unix_peerinfo_peer2.sock
60
61[resolver]
62ACCEPT_FROM6 = ::1;
63ACCEPT_FROM = 127.0.0.1;
64BINARY = gnunet-service-resolver
65CONFIG = $DEFAULTCONFIG
66HOME = $SERVICEHOME
67HOSTNAME = localhost
68PORT = 3089
69UNIXPATH = /tmp/test_quota_compliance_unix_resolver_peer2.sock
70
71[statistics]
72ACCEPT_FROM6 = ::1;
73ACCEPT_FROM = 127.0.0.1;
74BINARY = gnunet-service-statistics
75CONFIG = $DEFAULTCONFIG
76HOME = $SERVICEHOME
77HOSTNAME = localhost
78PORT = 3088
79UNIXPATH = /tmp/test_quota_compliance_unix_statistics_peer2.sock
80
81[arm]
82DEFAULTSERVICES =
83ACCEPT_FROM6 = ::1;
84ACCEPT_FROM = 127.0.0.1;
85BINARY = gnunet-service-arm
86CONFIG = $DEFAULTCONFIG
87HOME = $SERVICEHOME
88HOSTNAME = localhost
89PORT = 3087
90UNIXPATH = /tmp/test_quota_compliance_unix_arm_peer2.sock
91
92[TESTING]
93WEAKRANDOM = YES
94
95[gnunetd]
96HOSTKEY = $SERVICEHOME/.hostkey
97
98
99[dht]
100AUTOSTART = NO
101
102
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index 3b528d84d..60cb7866f 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -76,6 +76,8 @@ static int is_tcp_nat;
76 76
77static int is_udp; 77static int is_udp;
78 78
79static int is_unix;
80
79static int is_udp_nat; 81static int is_udp_nat;
80 82
81static int is_http; 83static int is_http;
@@ -369,6 +371,12 @@ run (void *cls,
369 setup_peer (&p1, "test_transport_api_udp_peer1.conf"); 371 setup_peer (&p1, "test_transport_api_udp_peer1.conf");
370 setup_peer (&p2, "test_transport_api_udp_peer2.conf"); 372 setup_peer (&p2, "test_transport_api_udp_peer2.conf");
371 } 373 }
374 if (is_unix)
375 {
376 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Using unix domain socket transport\n");
377 setup_peer (&p1, "test_transport_api_unix_peer1.conf");
378 setup_peer (&p2, "test_transport_api_unix_peer2.conf");
379 }
372 if (is_multi_protocol) 380 if (is_multi_protocol)
373 { 381 {
374 setup_peer (&p1, "test_transport_api_multi_peer1.conf"); 382 setup_peer (&p1, "test_transport_api_multi_peer1.conf");
@@ -634,6 +642,10 @@ main (int argc, char *argv[])
634 { 642 {
635 is_udp = GNUNET_YES; 643 is_udp = GNUNET_YES;
636 } 644 }
645 else if (strstr(argv[0], "unix") != NULL)
646 {
647 is_unix = GNUNET_YES;
648 }
637 else if (strstr(argv[0], "https") != NULL) 649 else if (strstr(argv[0], "https") != NULL)
638 { 650 {
639 is_https = GNUNET_YES; 651 is_https = GNUNET_YES;
diff --git a/src/transport/test_transport_api_reliability.c b/src/transport/test_transport_api_reliability.c
index 414a8cdd6..306e88ed8 100644
--- a/src/transport/test_transport_api_reliability.c
+++ b/src/transport/test_transport_api_reliability.c
@@ -34,6 +34,7 @@
34#include "gnunet_scheduler_lib.h" 34#include "gnunet_scheduler_lib.h"
35#include "gnunet_server_lib.h" 35#include "gnunet_server_lib.h"
36#include "gnunet_transport_service.h" 36#include "gnunet_transport_service.h"
37#include "gauger.h"
37#include "transport.h" 38#include "transport.h"
38 39
39#define VERBOSE GNUNET_NO 40#define VERBOSE GNUNET_NO
@@ -82,6 +83,8 @@ static int is_https;
82 83
83static int is_udp; 84static int is_udp;
84 85
86static int is_unix;
87
85static int connected; 88static int connected;
86 89
87static unsigned long long total_bytes; 90static unsigned long long total_bytes;
@@ -95,7 +98,7 @@ static char * cert_file_p1;
95 98
96static char * key_file_p2; 99static char * key_file_p2;
97static char * cert_file_p2; 100static char * cert_file_p2;
98 101static char *test_name;
99static int msg_scheduled; 102static int msg_scheduled;
100static int msg_sent; 103static int msg_sent;
101static int msg_recv_expected; 104static int msg_recv_expected;
@@ -113,6 +116,7 @@ static void
113end () 116end ()
114{ 117{
115 unsigned long long delta; 118 unsigned long long delta;
119 char *value_name;
116 120
117 GNUNET_SCHEDULER_cancel (die_task); 121 GNUNET_SCHEDULER_cancel (die_task);
118 die_task = GNUNET_SCHEDULER_NO_TASK; 122 die_task = GNUNET_SCHEDULER_NO_TASK;
@@ -129,6 +133,9 @@ end ()
129 fprintf (stderr, 133 fprintf (stderr,
130 "\nThroughput was %llu kb/s\n", 134 "\nThroughput was %llu kb/s\n",
131 total_bytes * 1000 / 1024 / delta); 135 total_bytes * 1000 / 1024 / delta);
136 GNUNET_asprintf(&value_name, "reliable_kbs_%s", test_name);
137 GAUGER (value_name, (int)(total_bytes * 1000 / 1024 /delta));
138 GNUNET_free(value_name);
132 ok = 0; 139 ok = 0;
133 140
134} 141}
@@ -665,6 +672,11 @@ run (void *cls,
665 setup_peer (&p1, "test_transport_api_udp_peer1.conf"); 672 setup_peer (&p1, "test_transport_api_udp_peer1.conf");
666 setup_peer (&p2, "test_transport_api_udp_peer2.conf"); 673 setup_peer (&p2, "test_transport_api_udp_peer2.conf");
667 } 674 }
675 else if (is_unix)
676 {
677 setup_peer (&p1, "test_transport_api_unix_peer1.conf");
678 setup_peer (&p2, "test_transport_api_unix_peer2.conf");
679 }
668 else if (is_tcp_nat) 680 else if (is_tcp_nat)
669 { 681 {
670 setup_peer (&p1, "test_transport_api_tcp_nat_peer1.conf"); 682 setup_peer (&p1, "test_transport_api_tcp_nat_peer1.conf");
@@ -768,22 +780,32 @@ main (int argc, char *argv[])
768 if (strstr(argv[0], "tcp_nat") != NULL) 780 if (strstr(argv[0], "tcp_nat") != NULL)
769 { 781 {
770 is_tcp_nat = GNUNET_YES; 782 is_tcp_nat = GNUNET_YES;
783 GNUNET_asprintf(&test_name, "tcp_nat");
771 } 784 }
772 else if (strstr(argv[0], "tcp") != NULL) 785 else if (strstr(argv[0], "tcp") != NULL)
773 { 786 {
774 is_tcp = GNUNET_YES; 787 is_tcp = GNUNET_YES;
788 GNUNET_asprintf(&test_name, "tcp");
775 } 789 }
776 else if (strstr(argv[0], "https") != NULL) 790 else if (strstr(argv[0], "https") != NULL)
777 { 791 {
778 is_https = GNUNET_YES; 792 is_https = GNUNET_YES;
793 GNUNET_asprintf(&test_name, "https");
779 } 794 }
780 else if (strstr(argv[0], "http") != NULL) 795 else if (strstr(argv[0], "http") != NULL)
781 { 796 {
782 is_http = GNUNET_YES; 797 is_http = GNUNET_YES;
798 GNUNET_asprintf(&test_name, "http");
783 } 799 }
784 else if (strstr(argv[0], "udp") != NULL) 800 else if (strstr(argv[0], "udp") != NULL)
785 { 801 {
786 is_udp = GNUNET_YES; 802 is_udp = GNUNET_YES;
803 GNUNET_asprintf(&test_name, "udp");
804 }
805 else if (strstr(argv[0], "unix") != NULL)
806 {
807 is_unix = GNUNET_YES;
808 GNUNET_asprintf(&test_name, "unix");
787 } 809 }
788 GNUNET_log_setup ("test-transport-api-reliability", 810 GNUNET_log_setup ("test-transport-api-reliability",
789#if VERBOSE 811#if VERBOSE
diff --git a/src/transport/test_transport_api_unix_peer1.conf b/src/transport/test_transport_api_unix_peer1.conf
new file mode 100644
index 000000000..e1e5a7f57
--- /dev/null
+++ b/src/transport/test_transport_api_unix_peer1.conf
@@ -0,0 +1,110 @@
1[transport-unix]
2PORT = 12368
3
4[fs]
5AUTOSTART = NO
6
7[datastore]
8AUTOSTART = NO
9
10[core]
11AUTOSTART = NO
12
13[hostlist]
14HTTP-PROXY =
15SERVERS = http://gnunet.org:8080/
16OPTIONS = -b
17BINARY = gnunet-daemon-hostlist
18CONFIG = $DEFAULTCONFIG
19HOME = $SERVICEHOME
20HOSTNAME = localhost
21HTTPPORT = 8080
22
23[topology]
24BINARY = gnunet-daemon-topology
25CONFIG = $DEFAULTCONFIG
26FRIENDS = $SERVICEHOME/friends
27TARGET-CONNECTION-COUNT = 16
28AUTOCONNECT = YES
29FRIENDS-ONLY = NO
30MINIMUM-FRIENDS = 0
31
32[core]
33AUTOSTART = NO
34
35[transport]
36PLUGINS = unix
37#DEBUG = YES
38ACCEPT_FROM6 = ::1;
39ACCEPT_FROM = 127.0.0.1;
40NEIGHBOUR_LIMIT = 50
41BINARY = gnunet-service-transport
42CONFIG = $DEFAULTCONFIG
43HOME = $SERVICEHOME
44HOSTNAME = localhost
45PORT = 12365
46UNIXPATH = /tmp/gnunet-p1-service-transport.sock
47
48
49[peerinfo]
50TRUST = $SERVICEHOME/data/credit/
51HOSTS = $SERVICEHOME/data/hosts/
52ACCEPT_FROM6 = ::1;
53ACCEPT_FROM = 127.0.0.1;
54BINARY = gnunet-service-peerinfo
55CONFIG = $DEFAULTCONFIG
56HOME = $SERVICEHOME
57HOSTNAME = localhost
58PORT = 12369
59UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
60
61[resolver]
62ACCEPT_FROM6 = ::1;
63ACCEPT_FROM = 127.0.0.1;
64BINARY = gnunet-service-resolver
65CONFIG = $DEFAULTCONFIG
66HOME = $SERVICEHOME
67HOSTNAME = localhost
68PORT = 12364
69UNIXPATH = /tmp/gnunet-p1-service-resolver.sock
70
71[statistics]
72ACCEPT_FROM6 = ::1;
73ACCEPT_FROM = 127.0.0.1;
74BINARY = gnunet-service-statistics
75CONFIG = $DEFAULTCONFIG
76HOME = $SERVICEHOME
77HOSTNAME = localhost
78PORT = 12367
79UNIXPATH = /tmp/gnunet-p1-service-statistics.sock
80
81[arm]
82DEFAULTSERVICES =
83ACCEPT_FROM6 = ::1;
84ACCEPT_FROM = 127.0.0.1;
85BINARY = gnunet-service-arm
86CONFIG = $DEFAULTCONFIG
87HOME = $SERVICEHOME
88HOSTNAME = localhost
89PORT = 12366
90UNIXPATH = /tmp/gnunet-p1-service-arm.sock
91
92[transport-tcp]
93TIMEOUT = 300000
94PORT = 12368
95
96[TESTING]
97WEAKRANDOM = YES
98
99[gnunetd]
100HOSTKEY = $SERVICEHOME/.hostkey
101
102[PATHS]
103DEFAULTCONFIG = test_transport_api_unix_peer1.conf
104SERVICEHOME = /tmp/test-gnunetd-transport-peer-1/
105
106
107[dht]
108AUTOSTART = NO
109
110
diff --git a/src/transport/test_transport_api_unix_peer2.conf b/src/transport/test_transport_api_unix_peer2.conf
new file mode 100644
index 000000000..c297ef20e
--- /dev/null
+++ b/src/transport/test_transport_api_unix_peer2.conf
@@ -0,0 +1,108 @@
1[transport-unix]
2PORT = 22368
3
4[fs]
5AUTOSTART = NO
6
7[datastore]
8AUTOSTART = NO
9
10[core]
11AUTOSTART = NO
12
13[hostlist]
14HTTP-PROXY =
15SERVERS = http://gnunet.org:8080/
16OPTIONS = -b
17BINARY = gnunet-daemon-hostlist
18CONFIG = $DEFAULTCONFIG
19HOME = $SERVICEHOME
20HOSTNAME = localhost
21HTTPPORT = 8080
22
23[topology]
24BINARY = gnunet-daemon-topology
25CONFIG = $DEFAULTCONFIG
26FRIENDS = $SERVICEHOME/friends
27TARGET-CONNECTION-COUNT = 16
28AUTOCONNECT = YES
29FRIENDS-ONLY = NO
30MINIMUM-FRIENDS = 0
31
32[transport]
33PLUGINS = unix
34#DEBUG = YES
35PREFIX =
36ACCEPT_FROM6 = ::1;
37ACCEPT_FROM = 127.0.0.1;
38NEIGHBOUR_LIMIT = 50
39BINARY = gnunet-service-transport
40CONFIG = $DEFAULTCONFIG
41HOME = $SERVICEHOME
42HOSTNAME = localhost
43PORT = 22365
44UNIXPATH = /tmp/gnunet-p2-service-transport.sock
45#PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer2.log
46
47[peerinfo]
48TRUST = $SERVICEHOME/data/credit/
49HOSTS = $SERVICEHOME/data/hosts/
50ACCEPT_FROM6 = ::1;
51ACCEPT_FROM = 127.0.0.1;
52BINARY = gnunet-service-peerinfo
53CONFIG = $DEFAULTCONFIG
54HOME = $SERVICEHOME
55HOSTNAME = localhost
56PORT = 22369
57UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
58
59[resolver]
60ACCEPT_FROM6 = ::1;
61ACCEPT_FROM = 127.0.0.1;
62BINARY = gnunet-service-resolver
63CONFIG = $DEFAULTCONFIG
64HOME = $SERVICEHOME
65HOSTNAME = localhost
66PORT = 22364
67UNIXPATH = /tmp/gnunet-p2-service-resolver.sock
68
69[statistics]
70ACCEPT_FROM6 = ::1;
71ACCEPT_FROM = 127.0.0.1;
72BINARY = gnunet-service-statistics
73CONFIG = $DEFAULTCONFIG
74HOME = $SERVICEHOME
75HOSTNAME = localhost
76PORT = 22367
77UNIXPATH = /tmp/gnunet-p2-service-statistics.sock
78
79[arm]
80DEFAULTSERVICES =
81ACCEPT_FROM6 = ::1;
82ACCEPT_FROM = 127.0.0.1;
83BINARY = gnunet-service-arm
84CONFIG = $DEFAULTCONFIG
85HOME = $SERVICEHOME
86HOSTNAME = localhost
87PORT = 22366
88UNIXPATH = /tmp/gnunet-p2-service-arm.sock
89
90[transport-tcp]
91TIMEOUT = 300000
92PORT = 22368
93
94[TESTING]
95WEAKRANDOM = YES
96
97[gnunetd]
98HOSTKEY = $SERVICEHOME/.hostkey
99
100[PATHS]
101DEFAULTCONFIG = test_transport_api_unix_peer2.conf
102SERVICEHOME = /tmp/test-gnunetd-transport-peer-2/
103
104
105[dht]
106AUTOSTART = NO
107
108
diff --git a/src/transport/test_transport_api_unreliability.c b/src/transport/test_transport_api_unreliability.c
new file mode 100644
index 000000000..caafdbc5d
--- /dev/null
+++ b/src/transport/test_transport_api_unreliability.c
@@ -0,0 +1,922 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file transport/test_transport_api_unreliability.c
22 * @brief test case for transports; ensures messages get
23 * through, regardless of order
24 *
25 * This test case serves as a base for unreliable
26 * transport test cases to check that the transports
27 * achieve reliable message delivery.
28 */
29#include "platform.h"
30#include "gnunet_common.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_getopt_lib.h"
33#include "gnunet_os_lib.h"
34#include "gnunet_program_lib.h"
35#include "gnunet_scheduler_lib.h"
36#include "gnunet_server_lib.h"
37#include "gnunet_transport_service.h"
38#include "gauger.h"
39#include "transport.h"
40
41#define VERBOSE GNUNET_NO
42
43#define VERBOSE_ARM GNUNET_NO
44
45#define START_ARM GNUNET_YES
46
47/**
48 * Note that this value must not significantly exceed
49 * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
50 * messages may be dropped even for a reliable transport.
51 */
52#define TOTAL_MSGS (80000 * 3) /* Total messages should be divisible by 8, so we can make a nice bitmap */
53
54/**
55 * How long until we give up on transmitting the message?
56 */
57#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
58
59#define UNRELIABLE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
60
61#define MTYPE 12345
62
63struct PeerContext
64{
65 struct GNUNET_CONFIGURATION_Handle *cfg;
66 struct GNUNET_TRANSPORT_Handle *th;
67 struct GNUNET_PeerIdentity id;
68#if START_ARM
69 struct GNUNET_OS_Process *arm_proc;
70#endif
71};
72
73static struct PeerContext p1;
74
75static struct PeerContext p2;
76
77static int ok;
78
79static int is_tcp;
80
81static int is_tcp_nat;
82
83static int is_http;
84
85static int is_https;
86
87static int is_udp;
88
89static int is_unix;
90
91static int connected;
92
93static unsigned long long total_bytes;
94
95static struct GNUNET_TIME_Absolute start_time;
96
97static GNUNET_SCHEDULER_TaskIdentifier die_task;
98
99static char *key_file_p1;
100static char *cert_file_p1;
101
102static char *key_file_p2;
103static char *cert_file_p2;
104
105static char *test_name;
106
107static char bitmap[TOTAL_MSGS / 8];
108
109static int msg_scheduled;
110static int msg_sent;
111static int msg_recv_expected;
112static int msg_recv;
113static struct GNUNET_TRANSPORT_TransmitHandle * transmit_handle;
114
115#if VERBOSE
116#define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
117#else
118#define OKPP do { ok++; } while (0)
119#endif
120
121/**
122 * Sets a bit active in the bitmap.
123 *
124 * @param bitIdx which bit to set
125 */
126static void
127set_bit (unsigned int bitIdx)
128{
129 size_t arraySlot;
130 unsigned int targetBit;
131 if (bitIdx > sizeof(bitmap) * 8)
132 {
133 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "setting bit %d of %d(!)\n", bitIdx, sizeof(bitmap) * 8);
134 return;
135 }
136 GNUNET_assert(bitIdx < sizeof(bitmap) * 8);
137 arraySlot = bitIdx / 8;
138 targetBit = (1L << (bitIdx % 8));
139 bitmap[arraySlot] |= targetBit;
140}
141
142/**
143 * Obtain a bit from bitmap.
144 * @param map the bitmap
145 * @param bit index from bitmap
146 *
147 * @return Bit \a bit from hashcode \a code
148 */
149int
150get_bit (const char *map, unsigned int bit)
151{
152 if (bit >= TOTAL_MSGS)
153 {
154 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "get bit %d of %d(!?!?)\n", bit, sizeof(bitmap) * 8);
155 return 0;
156 }
157 return ((map)[bit >> 3] & (1 << (bit & 7))) > 0;
158}
159
160static void
161end ()
162{
163 unsigned long long delta;
164 int i;
165 int result;
166 char *value_name;
167
168 result = 0;
169 for (i = 0; i < TOTAL_MSGS; i++)
170 {
171 if (get_bit(bitmap, i) == 0)
172 {
173 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Did not receive message %d\n", i);
174 result = -1;
175 }
176 }
177
178 GNUNET_SCHEDULER_cancel (die_task);
179 die_task = GNUNET_SCHEDULER_NO_TASK;
180#if VERBOSE
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
182#endif
183 GNUNET_TRANSPORT_disconnect (p1.th);
184 GNUNET_TRANSPORT_disconnect (p2.th);
185#if VERBOSE
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "Transports disconnected, returning success!\n");
188#endif
189 delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value;
190 GNUNET_asprintf(&value_name, "unreliable_kbs_%s", test_name);
191 GAUGER (value_name, (int)(total_bytes * 1000 / 1024 /delta));
192 GNUNET_free(value_name);
193 fprintf (stderr,
194 "\nThroughput was %llu kb/s\n",
195 total_bytes * 1000 / 1024 / delta);
196 ok = result;
197
198}
199
200static void
201end_unreliably ()
202{
203 unsigned long long delta;
204 int i;
205 int num_failed;
206 char *value_name;
207 num_failed = 0;
208 for (i = 0; i < TOTAL_MSGS; i++)
209 {
210 if (get_bit(bitmap, i) == 0)
211 {
212 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Did not receive message %d\n", i);
213 num_failed++;
214 }
215 }
216
217 die_task = GNUNET_SCHEDULER_NO_TASK;
218#if VERBOSE
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
220#endif
221 GNUNET_TRANSPORT_disconnect (p1.th);
222 GNUNET_TRANSPORT_disconnect (p2.th);
223#if VERBOSE
224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 "Transports disconnected, returning success!\n");
226#endif
227 delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value;
228 fprintf (stderr,
229 "\nThroughput was %llu kb/s\n",
230 total_bytes * 1000 / 1024 / delta);
231 GNUNET_asprintf(&value_name, "unreliable_kbs_%s", test_name);
232 GAUGER (value_name, (int)(total_bytes * 1000 / 1024 /delta));
233 GNUNET_free(value_name);
234 GNUNET_asprintf(&value_name, "unreliable_failed_%s", test_name);
235 GAUGER (value_name, (int)num_failed);
236 GNUNET_free(value_name);
237 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Had %d failed messages!\n", num_failed);
238 ok = 0;
239
240}
241
242
243
244static void
245stop_arm (struct PeerContext *p)
246{
247#if START_ARM
248 if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
249 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
250 GNUNET_OS_process_wait (p->arm_proc);
251 GNUNET_OS_process_close (p->arm_proc);
252 p->arm_proc = NULL;
253#endif
254 GNUNET_CONFIGURATION_destroy (p->cfg);
255}
256
257
258static void
259end_badly (void *cls,
260 const struct GNUNET_SCHEDULER_TaskContext *tc)
261{
262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
263 "Reliability failed: \nLast message sent %u \nNext message scheduled %u\nLast message received %u\nMessage expected %u \n ", msg_sent, msg_scheduled, msg_recv, msg_recv_expected);
264 GNUNET_break (0);
265 GNUNET_TRANSPORT_disconnect (p1.th);
266 GNUNET_TRANSPORT_disconnect (p2.th);
267 ok = 1;
268}
269
270
271struct TestMessage
272{
273 struct GNUNET_MessageHeader header;
274 uint32_t num;
275};
276
277
278static unsigned int
279get_size (unsigned int iter)
280{
281 unsigned int ret;
282
283 if (iter < 60000)
284 return iter + sizeof (struct TestMessage);
285 ret = (iter * iter * iter);
286 return sizeof (struct TestMessage) + (ret % 60000);
287}
288
289
290static void
291notify_receive (void *cls,
292 const struct GNUNET_PeerIdentity *peer,
293 const struct GNUNET_MessageHeader *message,
294 const struct GNUNET_TRANSPORT_ATS_Information *ats,
295 uint32_t ats_count)
296{
297 static int n;
298 unsigned int s;
299 char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
300 const struct TestMessage *hdr;
301
302 hdr = (const struct TestMessage*) message;
303
304 if (MTYPE != ntohs (message->type))
305 return;
306 msg_recv_expected = n;
307 msg_recv = ntohl(hdr->num);
308 s = get_size (ntohl(hdr->num));
309
310 if (ntohs (message->size) != s)
311 {
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
313 "Expected message %u of size %u, got %u bytes of message %u\n",
314 ntohl(hdr->num), s,
315 ntohs (message->size),
316 ntohl (hdr->num));
317 GNUNET_SCHEDULER_cancel (die_task);
318 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
319 return;
320 }
321
322 memset (cbuf, ntohl(hdr->num), s - sizeof (struct TestMessage));
323 if (0 != memcmp (cbuf,
324 &hdr[1],
325 s - sizeof (struct TestMessage)))
326 {
327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
328 "Expected message %u with bits %u, but body did not match\n",
329 ntohl(hdr->num), (unsigned char) n);
330 GNUNET_SCHEDULER_cancel (die_task);
331 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
332 return;
333 }
334#if VERBOSE
335 if (ntohl(hdr->num) % 5 == 0)
336 {
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Got message %u of size %u\n",
339 ntohl (hdr->num),
340 ntohs (message->size));
341 }
342#endif
343 n++;
344 set_bit(ntohl(hdr->num));
345 if (0 == (n % (5000)))
346 {
347 fprintf (stderr, ".");
348 GNUNET_SCHEDULER_cancel (die_task);
349 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
350 &end_badly,
351 NULL);
352 }
353 if (n == TOTAL_MSGS)
354 end ();
355}
356
357
358static size_t
359notify_ready (void *cls, size_t size, void *buf)
360{
361 static int n;
362 char *cbuf = buf;
363 struct TestMessage hdr;
364 unsigned int s;
365 unsigned int ret;
366
367 if (buf == NULL)
368 {
369 GNUNET_break (0);
370 ok = 42;
371 return 0;
372 }
373 ret = 0;
374 s = get_size (n);
375 GNUNET_assert (size >= s);
376 GNUNET_assert (buf != NULL);
377 cbuf = buf;
378 do
379 {
380 hdr.header.size = htons (s);
381 hdr.header.type = htons (MTYPE);
382 hdr.num = htonl (n);
383 msg_sent = n;
384 memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
385 ret += sizeof (struct TestMessage);
386 memset (&cbuf[ret], n, s - sizeof (struct TestMessage));
387 ret += s - sizeof (struct TestMessage);
388#if VERBOSE
389 if (n % 5000 == 0)
390 {
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
392 "Sending message %u of size %u\n",
393 n,
394 s);
395 }
396#endif
397 n++;
398 s = get_size (n);
399 if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
400 break; /* sometimes pack buffer full, sometimes not */
401 }
402 while (size - ret >= s);
403 if (n < TOTAL_MSGS)
404 {
405 GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
406 &p1.id,
407 s, 0, TIMEOUT,
408 &notify_ready,
409 NULL);
410 msg_scheduled = n;
411 }
412 else
413 {
414 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "All messages scheduled to be sent!!\n");
415 GNUNET_SCHEDULER_cancel(die_task);
416 die_task = GNUNET_SCHEDULER_add_delayed (UNRELIABLE_TIMEOUT, &end_unreliably, NULL);
417 }
418 if (n % 5000 == 0)
419 {
420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
421 "Returning total message block of size %u\n",
422 ret);
423 }
424 total_bytes += ret;
425 return ret;
426}
427
428
429static void
430notify_connect (void *cls,
431 const struct GNUNET_PeerIdentity *peer,
432 const struct GNUNET_TRANSPORT_ATS_Information *ats,
433 uint32_t ats_count)
434{
435 if (cls == &p1)
436 {
437 GNUNET_TRANSPORT_set_quota (p1.th,
438 &p2.id,
439 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
440 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
441 GNUNET_TIME_UNIT_FOREVER_REL,
442 NULL, NULL);
443 start_time = GNUNET_TIME_absolute_get ();
444 connected++;
445 }
446 else
447 {
448 GNUNET_TRANSPORT_set_quota (p2.th,
449 &p1.id,
450 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
451 GNUNET_BANDWIDTH_value_init (1024 * 1024 * 1024),
452 GNUNET_TIME_UNIT_FOREVER_REL,
453 NULL, NULL);
454 connected++;
455 }
456
457 if (connected == 2)
458 {
459
460 if ((transmit_handle!=NULL) && (cls == NULL))
461 GNUNET_TRANSPORT_notify_transmit_ready_cancel(transmit_handle);
462 if ((transmit_handle!=NULL) && (cls == &transmit_handle))
463 transmit_handle=NULL;
464 GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
465 &p1.id,
466 get_size (0), 0, TIMEOUT,
467 &notify_ready,
468 NULL);
469 }
470#if VERBOSE
471 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
472 "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls);
473#endif
474}
475
476
477static void
478notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
479{
480#if VERBOSE
481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
482 "Peer `%4s' disconnected (%p)!\n",
483 GNUNET_i2s (peer), cls);
484#endif
485}
486
487
488static void
489setup_peer (struct PeerContext *p, const char *cfgname)
490{
491 p->cfg = GNUNET_CONFIGURATION_create ();
492#if START_ARM
493 p->arm_proc = GNUNET_OS_start_process (NULL, NULL,
494 "gnunet-service-arm",
495 "gnunet-service-arm",
496#if VERBOSE_ARM
497 "-L", "DEBUG",
498#endif
499 "-c", cfgname, NULL);
500#endif
501 GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
502
503 if (is_https)
504 {
505 struct stat sbuf;
506 if (p==&p1)
507 {
508 if (GNUNET_CONFIGURATION_have_value (p->cfg,
509 "transport-https", "KEY_FILE"))
510 GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "KEY_FILE", &key_file_p1);
511 if (key_file_p1 == NULL)
512 GNUNET_asprintf(&key_file_p1,"https_p1.key");
513 if (0 == stat (key_file_p1, &sbuf ))
514 {
515 if (0 == remove(key_file_p1))
516 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Successfully removed existing private key file `%s'\n",key_file_p1);
517 else
518 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove private key file `%s'\n",key_file_p1);
519 }
520 if (GNUNET_CONFIGURATION_have_value (p->cfg,"transport-https", "CERT_FILE"))
521 GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "CERT_FILE", &cert_file_p1);
522 if (cert_file_p1 == NULL)
523 GNUNET_asprintf(&cert_file_p1,"https_p1.cert");
524 if (0 == stat (cert_file_p1, &sbuf ))
525 {
526 if (0 == remove(cert_file_p1))
527 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Successfully removed existing certificate file `%s'\n",cert_file_p1);
528 else
529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove existing certificate file `%s'\n",cert_file_p1);
530 }
531 }
532 else if (p==&p2)
533 {
534 if (GNUNET_CONFIGURATION_have_value (p->cfg,
535 "transport-https", "KEY_FILE"))
536 GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "KEY_FILE", &key_file_p2);
537 if (key_file_p2 == NULL)
538 GNUNET_asprintf(&key_file_p2,"https_p2.key");
539 if (0 == stat (key_file_p2, &sbuf ))
540 {
541 if (0 == remove(key_file_p2))
542 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Successfully removed existing private key file `%s'\n",key_file_p2);
543 else
544 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove private key file `%s'\n",key_file_p2);
545 }
546 if (GNUNET_CONFIGURATION_have_value (p->cfg,"transport-https", "CERT_FILE"))
547 GNUNET_CONFIGURATION_get_value_string (p->cfg, "transport-https", "CERT_FILE", &cert_file_p2);
548 if (cert_file_p2 == NULL)
549 GNUNET_asprintf(&cert_file_p2,"https_p2.cert");
550 if (0 == stat (cert_file_p2, &sbuf ))
551 {
552 if (0 == remove(cert_file_p2))
553 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Successfully removed existing certificate file `%s'\n",cert_file_p2);
554 else
555 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove existing certificate file `%s'\n",cert_file_p2);
556 }
557 }
558 }
559
560 p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL,
561 p,
562 &notify_receive,
563 &notify_connect,
564 &notify_disconnect);
565 GNUNET_assert (p->th != NULL);
566}
567
568static size_t
569notify_ready_connect (void *cls, size_t size, void *buf)
570{
571 return 0;
572}
573
574static void
575exchange_hello_last (void *cls,
576 const struct GNUNET_MessageHeader *message)
577{
578 struct PeerContext *me = cls;
579 transmit_handle = NULL;
580 GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, me);
581#if VERBOSE
582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
583 "Exchanging HELLO with peer (%p)!\n", cls);
584#endif
585 GNUNET_assert (ok >= 3);
586 OKPP;
587 GNUNET_assert (message != NULL);
588 GNUNET_assert (GNUNET_OK ==
589 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
590 message, &me->id));
591
592 GNUNET_assert(NULL != (transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
593 &p1.id,
594 sizeof (struct GNUNET_MessageHeader), 0,
595 TIMEOUT,
596 &notify_ready_connect,
597 &transmit_handle)));
598
599 /* both HELLOs exchanged, get ready to test transmission! */
600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
601 "Finished exchanging HELLOs, now waiting for transmission!\n");
602}
603
604
605static void
606exchange_hello (void *cls,
607 const struct GNUNET_MessageHeader *message)
608{
609 struct PeerContext *me = cls;
610
611 GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, me);
612#if VERBOSE
613 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
614 "Exchanging HELLO with peer (%p)!\n", cls);
615#endif
616 GNUNET_assert (ok >= 2);
617 OKPP;
618 GNUNET_assert (message != NULL);
619 GNUNET_assert (GNUNET_OK ==
620 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
621 message, &me->id));
622
623#if VERBOSE
624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
625 "Received HELLO size %d\n",
626 GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
627#endif
628 GNUNET_TRANSPORT_offer_hello (p2.th, message);
629 GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
630}
631
632/**
633 * Return the actual path to a file found in the current
634 * PATH environment variable.
635 *
636 * @param binary the name of the file to find
637 */
638static char *
639get_path_from_PATH (char *binary)
640{
641 char *path;
642 char *pos;
643 char *end;
644 char *buf;
645 const char *p;
646
647 p = getenv ("PATH");
648 if (p == NULL)
649 {
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
651 _("PATH environment variable is unset.\n"));
652 return NULL;
653 }
654 path = GNUNET_strdup (p); /* because we write on it */
655 buf = GNUNET_malloc (strlen (path) + 20);
656 pos = path;
657
658 while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
659 {
660 *end = '\0';
661 sprintf (buf, "%s/%s", pos, binary);
662 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
663 {
664 GNUNET_free (path);
665 return buf;
666 }
667 pos = end + 1;
668 }
669 sprintf (buf, "%s/%s", pos, binary);
670 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
671 {
672 GNUNET_free (path);
673 return buf;
674 }
675 GNUNET_free (buf);
676 GNUNET_free (path);
677 return NULL;
678}
679
680/**
681 * Check whether the suid bit is set on a file.
682 * Attempts to find the file using the current
683 * PATH environment variable as a search path.
684 *
685 * @param binary the name of the file to check
686 *
687 * @return GNUNET_YES if the binary is found and
688 * can be run properly, GNUNET_NO otherwise
689 */
690static int
691check_gnunet_nat_binary(char *binary)
692{
693 struct stat statbuf;
694 char *p;
695#ifdef MINGW
696 SOCKET rawsock;
697#endif
698
699#ifdef MINGW
700 char *binaryexe;
701 GNUNET_asprintf (&binaryexe, "%s.exe", binary);
702 p = get_path_from_PATH (binaryexe);
703 free (binaryexe);
704#else
705 p = get_path_from_PATH (binary);
706#endif
707 if (p == NULL)
708 {
709 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
710 _("Could not find binary `%s' in PATH!\n"),
711 binary);
712 return GNUNET_NO;
713 }
714 if (0 != STAT (p, &statbuf))
715 {
716 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
717 _("stat (%s) failed: %s\n"),
718 p,
719 STRERROR (errno));
720 GNUNET_free (p);
721 return GNUNET_SYSERR;
722 }
723 GNUNET_free (p);
724#ifndef MINGW
725 if ( (0 != (statbuf.st_mode & S_ISUID)) &&
726 (statbuf.st_uid == 0) )
727 return GNUNET_YES;
728 return GNUNET_NO;
729#else
730 rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
731 if (INVALID_SOCKET == rawsock)
732 {
733 DWORD err = GetLastError ();
734 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
735 "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) have failed! GLE = %d\n", err);
736 return GNUNET_NO; /* not running as administrator */
737 }
738 closesocket (rawsock);
739 return GNUNET_YES;
740#endif
741}
742
743static void
744run (void *cls,
745 char *const *args,
746 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
747{
748 GNUNET_assert (ok == 1);
749 OKPP;
750 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
751 &end_badly,
752 NULL);
753 if (is_tcp)
754 {
755 setup_peer (&p1, "test_transport_api_tcp_peer1.conf");
756 setup_peer (&p2, "test_transport_api_tcp_peer2.conf");
757 }
758 else if (is_http)
759 {
760 setup_peer (&p1, "test_transport_api_rel_http_peer1.conf");
761 setup_peer (&p2, "test_transport_api_rel_http_peer2.conf");
762 }
763 else if (is_https)
764 {
765 setup_peer (&p1, "test_transport_api_rel_https_peer1.conf");
766 setup_peer (&p2, "test_transport_api_rel_https_peer2.conf");
767 }
768 else if (is_udp)
769 {
770 setup_peer (&p1, "test_transport_api_udp_peer1.conf");
771 setup_peer (&p2, "test_transport_api_udp_peer2.conf");
772 }
773 else if (is_unix)
774 {
775 setup_peer (&p1, "test_transport_api_unix_peer1.conf");
776 setup_peer (&p2, "test_transport_api_unix_peer2.conf");
777 }
778 else if (is_tcp_nat)
779 {
780 setup_peer (&p1, "test_transport_api_tcp_nat_peer1.conf");
781 setup_peer (&p2, "test_transport_api_tcp_nat_peer2.conf");
782 }
783 else
784 GNUNET_assert (0);
785 GNUNET_assert(p1.th != NULL);
786 GNUNET_assert(p2.th != NULL);
787 GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
788}
789
790
791static int
792check ()
793{
794 char *const argv[] = { "test-transport-api-reliability",
795 "-c",
796 "test_transport_api_data.conf",
797#if VERBOSE
798 "-L", "DEBUG",
799#endif
800 NULL
801 };
802 struct GNUNET_GETOPT_CommandLineOption options[] = {
803 GNUNET_GETOPT_OPTION_END
804 };
805
806#if WRITECONFIG
807 setTransportOptions("test_transport_api_data.conf");
808#endif
809 ok = 1;
810
811 if ((GNUNET_YES == is_tcp_nat) && (check_gnunet_nat_binary("gnunet-nat-server") != GNUNET_YES))
812 {
813 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Not running NAT test case, binaries not properly installed.\n");
814 return 0;
815 }
816
817 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
818 argv, "test-transport-api-reliability", "nohelp",
819 options, &run, &ok);
820 stop_arm (&p1);
821 stop_arm (&p2);
822
823 if (is_https)
824 {
825 struct stat sbuf;
826 if (0 == stat (cert_file_p1, &sbuf ))
827 {
828 if (0 == remove(cert_file_p1))
829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully removed existing certificate file `%s'\n",cert_file_p1);
830 else
831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove certfile `%s'\n",cert_file_p1);
832 }
833
834 if (0 == stat (key_file_p1, &sbuf ))
835 {
836 if (0 == remove(key_file_p1))
837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully removed private key file `%s'\n",key_file_p1);
838 else
839 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to private key file `%s'\n",key_file_p1);
840 }
841
842 if (0 == stat (cert_file_p2, &sbuf ))
843 {
844 if (0 == remove(cert_file_p2))
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully removed existing certificate file `%s'\n",cert_file_p2);
846 else
847 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove certfile `%s'\n",cert_file_p2);
848 }
849
850 if (0 == stat (key_file_p2, &sbuf ))
851 {
852 if (0 == remove(key_file_p2))
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully removed private key file `%s'\n",key_file_p2);
854 else
855 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to private key file `%s'\n",key_file_p2);
856 }
857 GNUNET_free(key_file_p1);
858 GNUNET_free(key_file_p2);
859 GNUNET_free(cert_file_p1);
860 GNUNET_free(cert_file_p2);
861 }
862
863 return ok;
864}
865
866
867int
868main (int argc, char *argv[])
869{
870 int ret;
871#ifdef MINGW
872 return GNUNET_SYSERR;
873#endif
874
875 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1");
876 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2");
877
878 if (strstr(argv[0], "tcp_nat") != NULL)
879 {
880 is_tcp_nat = GNUNET_YES;
881 GNUNET_asprintf(&test_name, "tcp_nat");
882 }
883 else if (strstr(argv[0], "tcp") != NULL)
884 {
885 is_tcp = GNUNET_YES;
886 GNUNET_asprintf(&test_name, "tcp");
887 }
888 else if (strstr(argv[0], "https") != NULL)
889 {
890 is_https = GNUNET_YES;
891 GNUNET_asprintf(&test_name, "https");
892 }
893 else if (strstr(argv[0], "http") != NULL)
894 {
895 is_http = GNUNET_YES;
896 GNUNET_asprintf(&test_name, "http");
897 }
898 else if (strstr(argv[0], "udp") != NULL)
899 {
900 is_udp = GNUNET_YES;
901 GNUNET_asprintf(&test_name, "udp");
902 }
903 else if (strstr(argv[0], "unix") != NULL)
904 {
905 is_unix = GNUNET_YES;
906 GNUNET_asprintf(&test_name, "unix");
907 }
908 GNUNET_log_setup ("test-transport-api-reliability",
909#if VERBOSE
910 "DEBUG",
911#else
912 "WARNING",
913#endif
914 NULL);
915 ret = check ();
916 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1");
917 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2");
918 GNUNET_free_non_null(test_name);
919 return ret;
920}
921
922/* end of test_transport_api_reliability.c */