glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / transport / plugin_transport_tcp.c
1 /*
2   This file is part of GNUnet
3   Copyright (C) 2002--2015 GNUnet e.V.
4
5   GNUnet is free software: you can redistribute it and/or modify it
6   under the terms of the GNU Affero General Public License as published
7   by the Free Software Foundation, either version 3 of the License,
8   or (at your option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Affero General Public License for more details.
14  */
15 /**
16  * @file transport/plugin_transport_tcp.c
17  * @brief Implementation of the TCP transport service
18  * @author Christian Grothoff
19  */
20 #include "platform.h"
21 #include "gnunet_hello_lib.h"
22 #include "gnunet_constants.h"
23 #include "gnunet_util_lib.h"
24 #include "gnunet_nat_service.h"
25 #include "gnunet_protocols.h"
26 #include "gnunet_resolver_service.h"
27 #include "gnunet_signatures.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet_transport_service.h"
30 #include "gnunet_transport_plugin.h"
31 #include "transport.h"
32
33 #define LOG(kind,...) GNUNET_log_from (kind, "transport-tcp",__VA_ARGS__)
34
35 #define PLUGIN_NAME "tcp"
36
37 /**
38  * How long until we give up on establishing an NAT connection?
39  * Must be > 4 RTT
40  */
41 #define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
42
43 /**
44  * Opaque handle that can be used to cancel
45  * a transmit-ready notification.
46  */
47 struct GNUNET_CONNECTION_TransmitHandle;
48
49 /**
50  * @brief handle for a server
51  */
52 struct GNUNET_SERVER_Handle;
53
54 /**
55  * @brief opaque handle for a client of the server
56  */
57 struct GNUNET_SERVER_Client;
58
59 /**
60  * @brief opaque handle server returns for aborting transmission to a client.
61  */
62 struct GNUNET_SERVER_TransmitHandle;
63
64 /**
65  * @brief handle for a network connection
66  */
67 struct GNUNET_CONNECTION_Handle;
68
69 /**
70  * @brief handle for a network service
71  */
72 struct LEGACY_SERVICE_Context;
73
74
75 /**
76  * Stops a service that was started with #GNUNET_SERVICE_start().
77  *
78  * @param srv service to stop
79  */
80 void
81 LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *srv);
82
83
84
85 /**
86  * Function called to notify a client about the connection begin ready
87  * to queue more data.  @a buf will be NULL and @a size zero if the
88  * connection was closed for writing in the meantime.
89  *
90  * @param cls closure
91  * @param size number of bytes available in @a buf
92  * @param buf where the callee should write the message
93  * @return number of bytes written to @a buf
94  */
95 typedef size_t
96 (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
97                                           size_t size,
98                                           void *buf);
99
100 /**
101  * Credentials for UNIX domain sockets.
102  */
103 struct GNUNET_CONNECTION_Credentials
104 {
105   /**
106    * UID of the other end of the connection.
107    */
108   uid_t uid;
109
110   /**
111    * GID of the other end of the connection.
112    */
113   gid_t gid;
114 };
115
116
117 /**
118  * Functions with this signature are called whenever a client
119  * is disconnected on the network level.
120  *
121  * @param cls closure
122  * @param client identification of the client; NULL
123  *        for the last call when the server is destroyed
124  */
125 typedef void
126 (*GNUNET_SERVER_DisconnectCallback) (void *cls,
127                                      struct GNUNET_SERVER_Client *client);
128
129
130 /**
131  * Functions with this signature are called whenever a client
132  * is connected on the network level.
133  *
134  * @param cls closure
135  * @param client identification of the client
136  */
137 typedef void
138 (*GNUNET_SERVER_ConnectCallback) (void *cls,
139                                   struct GNUNET_SERVER_Client *client);
140
141
142
143
144 /**
145  * Function to call for access control checks.
146  *
147  * @param cls closure
148  * @param ucred credentials, if available, otherwise NULL
149  * @param addr address
150  * @param addrlen length of address
151  * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
152  *   for unknown address family (will be denied).
153  */
154 typedef int
155 (*GNUNET_CONNECTION_AccessCheck) (void *cls,
156                                   const struct
157                                   GNUNET_CONNECTION_Credentials *
158                                   ucred,
159                                   const struct sockaddr * addr,
160                                   socklen_t addrlen);
161
162 /**
163  * Callback function for data received from the network.  Note that
164  * both "available" and "err" would be 0 if the read simply timed out.
165  *
166  * @param cls closure
167  * @param buf pointer to received data
168  * @param available number of bytes availabe in "buf",
169  *        possibly 0 (on errors)
170  * @param addr address of the sender
171  * @param addrlen size of addr
172  * @param errCode value of errno (on errors receiving)
173  */
174 typedef void
175 (*GNUNET_CONNECTION_Receiver) (void *cls, const void *buf,
176                                size_t available,
177                                const struct sockaddr * addr,
178                                socklen_t addrlen, int errCode);
179
180
181
182 /**
183  * Close the connection and free associated resources.  There must
184  * not be any pending requests for reading or writing to the
185  * connection at this time.
186  *
187  * @param connection connection to destroy
188  */
189 void
190 GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection);
191
192
193 /**
194  * Signature of a function to create a custom tokenizer.
195  *
196  * @param cls closure from #GNUNET_SERVER_set_callbacks
197  * @param client handle to client the tokenzier will be used for
198  * @return handle to custom tokenizer ('mst')
199  */
200 typedef void*
201 (*GNUNET_SERVER_MstCreateCallback) (void *cls,
202                                     struct GNUNET_SERVER_Client *client);
203
204
205 /**
206  * Signature of a function to destroy a custom tokenizer.
207  *
208  * @param cls closure from #GNUNET_SERVER_set_callbacks
209  * @param mst custom tokenizer handle
210  */
211 typedef void
212 (*GNUNET_SERVER_MstDestroyCallback) (void *cls,
213                                      void *mst);
214
215 /**
216  * Signature of a function to receive data for a custom tokenizer.
217  *
218  * @param cls closure from #GNUNET_SERVER_set_callbacks
219  * @param mst custom tokenizer handle
220  * @param client_identity ID of client for which this is a buffer,
221  *        can be NULL (will be passed back to 'cb')
222  * @param buf input data to add
223  * @param size number of bytes in @a buf
224  * @param purge should any excess bytes in the buffer be discarded
225  *       (i.e. for packet-based services like UDP)
226  * @param one_shot only call callback once, keep rest of message in buffer
227  * @return #GNUNET_OK if we are done processing (need more data)
228  *         #GNUNET_NO if one_shot was set and we have another message ready
229  *         #GNUNET_SYSERR if the data stream is corrupt
230  */
231 typedef int
232 (*GNUNET_SERVER_MstReceiveCallback) (void *cls, void *mst,
233                                      struct GNUNET_SERVER_Client *client,
234                                      const char *buf,
235                                      size_t size,
236                                      int purge,
237                                      int one_shot);
238 /**
239  * Functions with this signature are called whenever a message is
240  * received.
241  *
242  * @param cls closure
243  * @param client identification of the client
244  * @param message the actual message
245  */
246 typedef void
247 (*GNUNET_SERVER_MessageCallback) (void *cls,
248                                   struct GNUNET_SERVER_Client *client,
249                                   const struct GNUNET_MessageHeader *message);
250
251 /**
252  * Message handler.  Each struct specifies how to handle on particular
253  * type of message received.
254  */
255 struct GNUNET_SERVER_MessageHandler
256 {
257   /**
258    * Function to call for messages of "type".
259    */
260   GNUNET_SERVER_MessageCallback callback;
261
262   /**
263    * Closure argument for @e callback.
264    */
265   void *callback_cls;
266
267   /**
268    * Type of the message this handler covers.
269    */
270   uint16_t type;
271
272   /**
273    * Expected size of messages of this type.  Use 0 for
274    * variable-size.  If non-zero, messages of the given
275    * type will be discarded (and the connection closed)
276    * if they do not have the right size.
277    */
278   uint16_t expected_size;
279
280 };
281
282
283 /**
284  * Options for the service (bitmask).
285  */
286 enum LEGACY_SERVICE_Options
287 {
288   /**
289    * Use defaults.  Terminates all client connections and the listen
290    * sockets immediately upon receiving the shutdown signal.
291    */
292   LEGACY_SERVICE_OPTION_NONE = 0,
293
294   /**
295    * Do not trigger server shutdown on signal at all; instead, allow
296    * for the user to terminate the server explicitly when needed
297    * by calling #LEGACY_SERVICE_shutdown().
298    */
299   LEGACY_SERVICE_OPTION_MANUAL_SHUTDOWN = 1,
300
301   /**
302    * Trigger a SOFT server shutdown on signals, allowing active
303    * non-monitor clients to complete their transactions.
304    */
305   LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN = 2
306 };
307
308
309
310 /**
311  * Ask the server to disconnect from the given client.  This is the
312  * same as passing #GNUNET_SYSERR to #GNUNET_SERVER_receive_done,
313  * except that it allows dropping of a client even when not handling a
314  * message from that client.
315  *
316  * @param client the client to disconnect from
317  */
318 void
319 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client);
320
321 /**
322  * Return user context associated with the given client.
323  * Note: you should probably use the macro (call without the underscore).
324  *
325  * @param client client to query
326  * @param size number of bytes in user context struct (for verification only)
327  * @return pointer to user context
328  */
329 void *
330 GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client,
331                                         size_t size);
332
333
334 /**
335  * Functions with this signature are called whenever a
336  * complete message is received by the tokenizer.
337  *
338  * Do not call #GNUNET_SERVER_mst_destroy from within
339  * the scope of this callback.
340  *
341  * @param cls closure
342  * @param client identification of the client
343  * @param message the actual message
344  * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
345  */
346 typedef int
347 (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls,
348                                            void *client,
349                                            const struct GNUNET_MessageHeader *message);
350
351
352 /**
353  * Create a message stream tokenizer.
354  *
355  * @param cb function to call on completed messages
356  * @param cb_cls closure for @a cb
357  * @return handle to tokenizer
358  */
359 struct GNUNET_SERVER_MessageStreamTokenizer *
360 GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
361                           void *cb_cls);
362
363 /**
364  * Add incoming data to the receive buffer and call the
365  * callback for all complete messages.
366  *
367  * @param mst tokenizer to use
368  * @param client_identity ID of client for which this is a buffer,
369  *        can be NULL (will be passed back to 'cb')
370  * @param buf input data to add
371  * @param size number of bytes in @a buf
372  * @param purge should any excess bytes in the buffer be discarded
373  *       (i.e. for packet-based services like UDP)
374  * @param one_shot only call callback once, keep rest of message in buffer
375  * @return #GNUNET_OK if we are done processing (need more data)
376  *         #GNUNET_NO if one_shot was set and we have another message ready
377  *         #GNUNET_SYSERR if the data stream is corrupt
378  */
379 int
380 GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
381                            void *client_identity,
382                            const char *buf, size_t size,
383                            int purge, int one_shot);
384
385
386
387 /**
388  * Destroys a tokenizer.
389  *
390  * @param mst tokenizer to destroy
391  */
392 void
393 GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst);
394
395
396 /**
397  * Set user context to be associated with the given client.
398  * Note: you should probably use the macro (call without the underscore).
399  *
400  * @param client client to query
401  * @param ptr pointer to user context
402  * @param size number of bytes in user context struct (for verification only)
403  */
404 void
405 GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client,
406                                         void *ptr,
407                                         size_t size);
408 /**
409  * Return user context associated with the given client.
410  *
411  * @param client client to query
412  * @param type expected return type (i.e. 'struct Foo')
413  * @return pointer to user context of type 'type *'.
414  */
415 #define GNUNET_SERVER_client_get_user_context(client,type)              \
416   (type *) GNUNET_SERVER_client_get_user_context_ (client, sizeof (type))
417
418 /**
419  * Set user context to be associated with the given client.
420  *
421  * @param client client to query
422  * @param value pointer to user context
423  */
424 #define GNUNET_SERVER_client_set_user_context(client,value)             \
425   GNUNET_SERVER_client_set_user_context_ (client, value, sizeof (*value))
426
427
428
429 /**
430  * Notify us when the server has enough space to transmit
431  * a message of the given size to the given client.
432  *
433  * @param client client to transmit message to
434  * @param size requested amount of buffer space
435  * @param timeout after how long should we give up (and call
436  *        notify with buf NULL and size 0)?
437  * @param callback function to call when space is available
438  * @param callback_cls closure for @a callback
439  * @return non-NULL if the notify callback was queued; can be used
440  *           to cancel the request using
441  *           #GNUNET_SERVER_notify_transmit_ready_cancel.
442  *         NULL if we are already going to notify someone else (busy)
443  */
444 struct GNUNET_SERVER_TransmitHandle *
445 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
446                                      size_t size,
447                                      struct GNUNET_TIME_Relative timeout,
448                                      GNUNET_CONNECTION_TransmitReadyNotify callback,
449                                      void *callback_cls);
450
451 /**
452  * Abort transmission request.
453  *
454  * @param th request to abort
455  */
456 void
457 GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th);
458
459
460
461
462 /**
463  * Notify the server that the given client handle should
464  * be kept (keeps the connection up if possible, increments
465  * the internal reference counter).
466  *
467  * @param client the client to keep
468  */
469 void
470 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client);
471
472
473 /**
474  * Notify the server that the given client handle is no
475  * longer required.  Decrements the reference counter.  If
476  * that counter reaches zero an inactive connection maybe
477  * closed.
478  *
479  * @param client the client to drop
480  */
481 void
482 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client);
483
484
485 /**
486  * Function called by the service's run
487  * method to run service-specific setup code.
488  *
489  * @param cls closure
490  * @param server the initialized server
491  * @param cfg configuration to use
492  */
493 typedef void
494 (*LEGACY_SERVICE_Main) (void *cls,
495                         struct GNUNET_SERVER_Handle *server,
496                         const struct GNUNET_CONFIGURATION_Handle *cfg);
497
498
499
500 /**
501  * Suspend accepting connections from the listen socket temporarily.
502  * Resume activity using #GNUNET_SERVER_resume.
503  *
504  * @param server server to stop accepting connections.
505  */
506 void
507 GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server);
508
509 /**
510  * Notify us when the server has enough space to transmit
511  * a message of the given size to the given client.
512  *
513  * @param client client to transmit message to
514  * @param size requested amount of buffer space
515  * @param timeout after how long should we give up (and call
516  *        notify with buf NULL and size 0)?
517  * @param callback function to call when space is available
518  * @param callback_cls closure for @a callback
519  * @return non-NULL if the notify callback was queued; can be used
520  *           to cancel the request using
521  *           #GNUNET_SERVER_notify_transmit_ready_cancel.
522  *         NULL if we are already going to notify someone else (busy)
523  */
524 struct GNUNET_SERVER_TransmitHandle *
525 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
526                                      size_t size,
527                                      struct GNUNET_TIME_Relative timeout,
528                                      GNUNET_CONNECTION_TransmitReadyNotify callback,
529                                      void *callback_cls);
530
531
532 /**
533  * Add a TCP socket-based connection to the set of handles managed by
534  * this server.  Use this function for outgoing (P2P) connections that
535  * we initiated (and where this server should process incoming
536  * messages).
537  *
538  * @param server the server to use
539  * @param connection the connection to manage (client must
540  *        stop using this connection from now on)
541  * @return the client handle
542  */
543 struct GNUNET_SERVER_Client *
544 GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
545                               struct GNUNET_CONNECTION_Handle *connection);
546
547
548 /**
549  * Resume accepting connections from the listen socket.
550  *
551  * @param server server to resume accepting connections.
552  */
553 void
554 GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server);
555
556 /**
557  * Free resources held by this server.
558  *
559  * @param server server to destroy
560  */
561 void
562 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server);
563
564
565
566
567 #include "tcp_connection_legacy.c"
568 #include "tcp_server_mst_legacy.c"
569 #include "tcp_server_legacy.c"
570 #include "tcp_service_legacy.c"
571
572 GNUNET_NETWORK_STRUCT_BEGIN
573
574 /**
575  * Initial handshake message for a session.
576  */
577 struct WelcomeMessage
578 {
579   /**
580    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
581    */
582   struct GNUNET_MessageHeader header;
583
584   /**
585    * Identity of the node connecting (TCP client)
586    */
587   struct GNUNET_PeerIdentity clientIdentity;
588
589 };
590
591 /**
592  * Basically a WELCOME message, but with the purpose
593  * of giving the waiting peer a client handle to use
594  */
595 struct TCP_NAT_ProbeMessage
596 {
597   /**
598    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
599    */
600   struct GNUNET_MessageHeader header;
601
602   /**
603    * Identity of the sender of the message.
604    */
605   struct GNUNET_PeerIdentity clientIdentity;
606
607 };
608 GNUNET_NETWORK_STRUCT_END
609
610 /**
611  * Context for sending a NAT probe via TCP.
612  */
613 struct TCPProbeContext
614 {
615
616   /**
617    * Active probes are kept in a DLL.
618    */
619   struct TCPProbeContext *next;
620
621   /**
622    * Active probes are kept in a DLL.
623    */
624   struct TCPProbeContext *prev;
625
626   /**
627    * Probe connection.
628    */
629   struct GNUNET_CONNECTION_Handle *sock;
630
631   /**
632    * Message to be sent.
633    */
634   struct TCP_NAT_ProbeMessage message;
635
636   /**
637    * Handle to the transmission.
638    */
639   struct GNUNET_CONNECTION_TransmitHandle *transmit_handle;
640
641   /**
642    * Transport plugin handle.
643    */
644   struct Plugin *plugin;
645 };
646
647 /**
648  * Bits in the `options` field of TCP addresses.
649  */
650 enum TcpAddressOptions
651 {
652
653   /**
654    * No bits set.
655    */
656   TCP_OPTIONS_NONE = 0,
657
658   /**
659    * See #HTTP_OPTIONS_VERIFY_CERTIFICATE.
660    */
661   TCP_OPTIONS_RESERVED = 1,
662
663   /**
664    * Enable TCP Stealth-style port knocking.
665    */
666   TCP_OPTIONS_TCP_STEALTH = 2
667 };
668
669 GNUNET_NETWORK_STRUCT_BEGIN
670
671 /**
672  * Network format for IPv4 addresses.
673  */
674 struct IPv4TcpAddress
675 {
676   /**
677    * Optional options and flags for this address,
678    * see `enum TcpAddressOptions`
679    */
680   uint32_t options GNUNET_PACKED;
681
682   /**
683    * IPv4 address, in network byte order.
684    */
685   uint32_t ipv4_addr GNUNET_PACKED;
686
687   /**
688    * Port number, in network byte order.
689    */
690   uint16_t t4_port GNUNET_PACKED;
691
692 };
693
694 /**
695  * Network format for IPv6 addresses.
696  */
697 struct IPv6TcpAddress
698 {
699   /**
700    * Optional flags for this address
701    * see `enum TcpAddressOptions`
702    */
703   uint32_t options GNUNET_PACKED;
704
705   /**
706    * IPv6 address.
707    */
708   struct in6_addr ipv6_addr GNUNET_PACKED;
709
710   /**
711    * Port number, in network byte order.
712    */
713   uint16_t t6_port GNUNET_PACKED;
714
715 };
716 GNUNET_NETWORK_STRUCT_END
717
718 /**
719  * Encapsulation of all of the state of the plugin.
720  */
721 struct Plugin;
722
723 /**
724  * Information kept for each message that is yet to
725  * be transmitted.
726  */
727 struct PendingMessage
728 {
729
730   /**
731    * This is a doubly-linked list.
732    */
733   struct PendingMessage *next;
734
735   /**
736    * This is a doubly-linked list.
737    */
738   struct PendingMessage *prev;
739
740   /**
741    * The pending message
742    */
743   const char *msg;
744
745   /**
746    * Continuation function to call once the message
747    * has been sent.  Can be NULL if there is no
748    * continuation to call.
749    */
750   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
751
752   /**
753    * Closure for @e transmit_cont.
754    */
755   void *transmit_cont_cls;
756
757   /**
758    * Timeout value for the pending message.
759    */
760   struct GNUNET_TIME_Absolute timeout;
761
762   /**
763    * So that the gnunet-service-transport can group messages together,
764    * these pending messages need to accept a message buffer and size
765    * instead of just a `struct GNUNET_MessageHeader`.
766    */
767   size_t message_size;
768
769 };
770
771 /**
772  * Session handle for TCP connections.
773  */
774 struct GNUNET_ATS_Session
775 {
776   /**
777    * To whom are we talking to (set to our identity
778    * if we are still waiting for the welcome message)
779    */
780   struct GNUNET_PeerIdentity target;
781
782   /**
783    * Pointer to the global plugin struct.
784    */
785   struct Plugin *plugin;
786
787   /**
788    * The client (used to identify this connection)
789    */
790   struct GNUNET_SERVER_Client *client;
791
792   /**
793    * Task cleaning up a NAT client connection establishment attempt;
794    */
795   struct GNUNET_SCHEDULER_Task *nat_connection_timeout;
796
797   /**
798    * Messages currently pending for transmission
799    * to this peer, if any.
800    */
801   struct PendingMessage *pending_messages_head;
802
803   /**
804    * Messages currently pending for transmission
805    * to this peer, if any.
806    */
807   struct PendingMessage *pending_messages_tail;
808
809   /**
810    * Handle for pending transmission request.
811    */
812   struct GNUNET_SERVER_TransmitHandle *transmit_handle;
813
814   /**
815    * Address of the other peer.
816    */
817   struct GNUNET_HELLO_Address *address;
818
819   /**
820    * ID of task used to delay receiving more to throttle sender.
821    */
822   struct GNUNET_SCHEDULER_Task *receive_delay_task;
823
824   /**
825    * Session timeout task
826    */
827   struct GNUNET_SCHEDULER_Task *timeout_task;
828
829   /**
830    * When will this session time out?
831    */
832   struct GNUNET_TIME_Absolute timeout;
833
834   /**
835    * When will we continue to read from the socket?
836    * (used to enforce inbound quota).
837    */
838   struct GNUNET_TIME_Absolute receive_delay;
839
840   /**
841    * Last activity on this connection.  Used to select preferred
842    * connection.
843    */
844   struct GNUNET_TIME_Absolute last_activity;
845
846   /**
847    * Number of bytes waiting for transmission to this peer.
848    */
849   unsigned long long bytes_in_queue;
850
851   /**
852    * Number of messages waiting for transmission to this peer.
853    */
854   unsigned int msgs_in_queue;
855
856   /**
857    * Network type of the address.
858    */
859   enum GNUNET_ATS_Network_Type scope;
860
861   /**
862    * Are we still expecting the welcome message? (#GNUNET_YES/#GNUNET_NO)
863    */
864   int expecting_welcome;
865
866   /**
867    * Was this session created using NAT traversal?
868    */
869   int is_nat;
870
871 };
872
873
874 /**
875  * Context for address to string conversion, closure
876  * for #append_port().
877  */
878 struct PrettyPrinterContext
879 {
880   /**
881    * DLL
882    */
883   struct PrettyPrinterContext *next;
884
885   /**
886    * DLL
887    */
888   struct PrettyPrinterContext *prev;
889
890   /**
891    * Our plugin.
892    */
893   struct Plugin *plugin;
894
895   /**
896    * Timeout task
897    */
898   struct GNUNET_SCHEDULER_Task *timeout_task;
899
900   /**
901    * Resolver handle
902    */
903   struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
904
905   /**
906    * Function to call with the result.
907    */
908   GNUNET_TRANSPORT_AddressStringCallback asc;
909
910   /**
911    * Clsoure for @e asc.
912    */
913   void *asc_cls;
914
915   /**
916    * IPv6 address
917    */
918   int ipv6;
919
920   /**
921    * Options
922    */
923   uint32_t options;
924
925   /**
926    * Port to add after the IP address.
927    */
928   uint16_t port;
929 };
930
931
932 /**
933  * Encapsulation of all of the state of the plugin.
934  */
935 struct Plugin
936 {
937   /**
938    * Our environment.
939    */
940   struct GNUNET_TRANSPORT_PluginEnvironment *env;
941
942   /**
943    * The listen socket.
944    */
945   struct GNUNET_CONNECTION_Handle *lsock;
946
947   /**
948    * Our handle to the NAT module.
949    */
950   struct GNUNET_NAT_Handle *nat;
951
952   /**
953    * Map from peer identities to sessions for the given peer.
954    */
955   struct GNUNET_CONTAINER_MultiPeerMap *sessionmap;
956
957   /**
958    * Handle to the network service.
959    */
960   struct LEGACY_SERVICE_Context *service;
961
962   /**
963    * Handle to the server for this service.
964    */
965   struct GNUNET_SERVER_Handle *server;
966
967   /**
968    * Copy of the handler array where the closures are
969    * set to this struct's instance.
970    */
971   struct GNUNET_SERVER_MessageHandler *handlers;
972
973   /**
974    * Map of peers we have tried to contact behind a NAT
975    */
976   struct GNUNET_CONTAINER_MultiPeerMap *nat_wait_conns;
977
978   /**
979    * List of active TCP probes.
980    */
981   struct TCPProbeContext *probe_head;
982
983   /**
984    * List of active TCP probes.
985    */
986   struct TCPProbeContext *probe_tail;
987
988   /**
989    * Function to call about session status changes.
990    */
991   GNUNET_TRANSPORT_SessionInfoCallback sic;
992
993   /**
994    * Closure for @e sic.
995    */
996   void *sic_cls;
997
998   /**
999    * ID of task used to update our addresses when one expires.
1000    */
1001   struct GNUNET_SCHEDULER_Task *address_update_task;
1002
1003   /**
1004    * Running pretty printers: head
1005    */
1006   struct PrettyPrinterContext *ppc_dll_head;
1007
1008   /**
1009    * Running pretty printers: tail
1010    */
1011   struct PrettyPrinterContext *ppc_dll_tail;
1012
1013   /**
1014    * Welcome message used by this peer.
1015    */
1016   struct WelcomeMessage my_welcome;
1017
1018   /**
1019    * How many more TCP sessions are we allowed to open right now?
1020    */
1021   unsigned long long max_connections;
1022
1023   /**
1024    * How many more TCP sessions do we have right now?
1025    */
1026   unsigned long long cur_connections;
1027
1028   /**
1029    * Address options
1030    */
1031   uint32_t myoptions;
1032
1033   /**
1034    * Port that we are actually listening on.
1035    */
1036   uint16_t open_port;
1037
1038   /**
1039    * Port that the user said we would have visible to the
1040    * rest of the world.
1041    */
1042   uint16_t adv_port;
1043
1044 };
1045
1046
1047 /**
1048  * Get the list of addresses that a server for the given service
1049  * should bind to.
1050  *
1051  * @param service_name name of the service
1052  * @param cfg configuration (which specifies the addresses)
1053  * @param addrs set (call by reference) to an array of pointers to the
1054  *              addresses the server should bind to and listen on; the
1055  *              array will be NULL-terminated (on success)
1056  * @param addr_lens set (call by reference) to an array of the lengths
1057  *              of the respective `struct sockaddr` struct in the @a addrs
1058  *              array (on success)
1059  * @return number of addresses found on success,
1060  *              #GNUNET_SYSERR if the configuration
1061  *              did not specify reasonable finding information or
1062  *              if it specified a hostname that could not be resolved;
1063  *              #GNUNET_NO if the number of addresses configured is
1064  *              zero (in this case, `*addrs` and `*addr_lens` will be
1065  *              set to NULL).
1066  */
1067 static int
1068 get_server_addresses (const char *service_name,
1069                       const struct GNUNET_CONFIGURATION_Handle *cfg,
1070                       struct sockaddr ***addrs,
1071                       socklen_t ** addr_lens)
1072 {
1073   int disablev6;
1074   struct GNUNET_NETWORK_Handle *desc;
1075   unsigned long long port;
1076   char *unixpath;
1077   struct addrinfo hints;
1078   struct addrinfo *res;
1079   struct addrinfo *pos;
1080   struct addrinfo *next;
1081   unsigned int i;
1082   int resi;
1083   int ret;
1084   int abstract;
1085   struct sockaddr **saddrs;
1086   socklen_t *saddrlens;
1087   char *hostname;
1088
1089   *addrs = NULL;
1090   *addr_lens = NULL;
1091   desc = NULL;
1092   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
1093   {
1094     if (GNUNET_SYSERR ==
1095         (disablev6 =
1096          GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
1097       return GNUNET_SYSERR;
1098   }
1099   else
1100     disablev6 = GNUNET_NO;
1101
1102   if (! disablev6)
1103   {
1104     /* probe IPv6 support */
1105     desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1106     if (NULL == desc)
1107     {
1108       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1109           (EACCES == errno))
1110       {
1111         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1112         return GNUNET_SYSERR;
1113       }
1114       LOG (GNUNET_ERROR_TYPE_INFO,
1115            _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
1116            service_name, STRERROR (errno));
1117       disablev6 = GNUNET_YES;
1118     }
1119     else
1120     {
1121       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1122       desc = NULL;
1123     }
1124   }
1125
1126   port = 0;
1127   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
1128   {
1129     if (GNUNET_OK !=
1130         GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
1131                                                "PORT", &port))
1132     {
1133       LOG (GNUNET_ERROR_TYPE_ERROR,
1134            _("Require valid port number for service `%s' in configuration!\n"),
1135            service_name);
1136     }
1137     if (port > 65535)
1138     {
1139       LOG (GNUNET_ERROR_TYPE_ERROR,
1140            _("Require valid port number for service `%s' in configuration!\n"),
1141            service_name);
1142       return GNUNET_SYSERR;
1143     }
1144   }
1145
1146   if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
1147   {
1148     GNUNET_break (GNUNET_OK ==
1149                   GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
1150                                                          "BINDTO", &hostname));
1151   }
1152   else
1153     hostname = NULL;
1154
1155   unixpath = NULL;
1156   abstract = GNUNET_NO;
1157 #ifdef AF_UNIX
1158   if ((GNUNET_YES ==
1159        GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
1160       (GNUNET_OK ==
1161        GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
1162                                               &unixpath)) &&
1163       (0 < strlen (unixpath)))
1164   {
1165     /* probe UNIX support */
1166     struct sockaddr_un s_un;
1167
1168     if (strlen (unixpath) >= sizeof (s_un.sun_path))
1169     {
1170       LOG (GNUNET_ERROR_TYPE_WARNING,
1171            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
1172            (unsigned long long) sizeof (s_un.sun_path));
1173       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1174       LOG (GNUNET_ERROR_TYPE_INFO,
1175            _("Using `%s' instead\n"),
1176            unixpath);
1177     }
1178 #ifdef LINUX
1179     abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1180                                                      "TESTING",
1181                                                      "USE_ABSTRACT_SOCKETS");
1182     if (GNUNET_SYSERR == abstract)
1183       abstract = GNUNET_NO;
1184 #endif
1185     if ((GNUNET_YES != abstract)
1186         && (GNUNET_OK !=
1187             GNUNET_DISK_directory_create_for_file (unixpath)))
1188       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
1189                                 "mkdir",
1190                                 unixpath);
1191   }
1192   if (NULL != unixpath)
1193   {
1194     desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1195     if (NULL == desc)
1196     {
1197       if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1198           (EACCES == errno))
1199       {
1200         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
1201         GNUNET_free_non_null (hostname);
1202         GNUNET_free (unixpath);
1203         return GNUNET_SYSERR;
1204       }
1205       LOG (GNUNET_ERROR_TYPE_INFO,
1206            _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1207            service_name,
1208            STRERROR (errno));
1209       GNUNET_free (unixpath);
1210       unixpath = NULL;
1211     }
1212     else
1213     {
1214       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
1215       desc = NULL;
1216     }
1217   }
1218 #endif
1219
1220   if ((0 == port) && (NULL == unixpath))
1221   {
1222     LOG (GNUNET_ERROR_TYPE_ERROR,
1223          _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1224          service_name);
1225     GNUNET_free_non_null (hostname);
1226     return GNUNET_SYSERR;
1227   }
1228   if (0 == port)
1229   {
1230     saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
1231     saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
1232     add_unixpath (saddrs, saddrlens, unixpath, abstract);
1233     GNUNET_free_non_null (unixpath);
1234     GNUNET_free_non_null (hostname);
1235     *addrs = saddrs;
1236     *addr_lens = saddrlens;
1237     return 1;
1238   }
1239
1240   if (NULL != hostname)
1241   {
1242     LOG (GNUNET_ERROR_TYPE_DEBUG,
1243          "Resolving `%s' since that is where `%s' will bind to.\n",
1244          hostname,
1245          service_name);
1246     memset (&hints, 0, sizeof (struct addrinfo));
1247     if (disablev6)
1248       hints.ai_family = AF_INET;
1249     hints.ai_protocol = IPPROTO_TCP;
1250     if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1251         (NULL == res))
1252     {
1253       LOG (GNUNET_ERROR_TYPE_ERROR,
1254            _("Failed to resolve `%s': %s\n"),
1255            hostname,
1256            gai_strerror (ret));
1257       GNUNET_free (hostname);
1258       GNUNET_free_non_null (unixpath);
1259       return GNUNET_SYSERR;
1260     }
1261     next = res;
1262     i = 0;
1263     while (NULL != (pos = next))
1264     {
1265       next = pos->ai_next;
1266       if ((disablev6) && (pos->ai_family == AF_INET6))
1267         continue;
1268       i++;
1269     }
1270     if (0 == i)
1271     {
1272       LOG (GNUNET_ERROR_TYPE_ERROR,
1273            _("Failed to find %saddress for `%s'.\n"),
1274            disablev6 ? "IPv4 " : "",
1275            hostname);
1276       freeaddrinfo (res);
1277       GNUNET_free (hostname);
1278       GNUNET_free_non_null (unixpath);
1279       return GNUNET_SYSERR;
1280     }
1281     resi = i;
1282     if (NULL != unixpath)
1283       resi++;
1284     saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1285     saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1286     i = 0;
1287     if (NULL != unixpath)
1288     {
1289       add_unixpath (saddrs, saddrlens, unixpath, abstract);
1290       i++;
1291     }
1292     next = res;
1293     while (NULL != (pos = next))
1294     {
1295       next = pos->ai_next;
1296       if ((disablev6) && (AF_INET6 == pos->ai_family))
1297         continue;
1298       if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1299         continue;               /* not TCP */
1300       if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1301         continue;               /* huh? */
1302       LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
1303            service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1304       if (AF_INET == pos->ai_family)
1305       {
1306         GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
1307         saddrlens[i] = pos->ai_addrlen;
1308         saddrs[i] = GNUNET_malloc (saddrlens[i]);
1309         GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1310         ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1311       }
1312       else
1313       {
1314         GNUNET_assert (AF_INET6 == pos->ai_family);
1315         GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
1316         saddrlens[i] = pos->ai_addrlen;
1317         saddrs[i] = GNUNET_malloc (saddrlens[i]);
1318         GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1319         ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1320       }
1321       i++;
1322     }
1323     GNUNET_free (hostname);
1324     freeaddrinfo (res);
1325     resi = i;
1326   }
1327   else
1328   {
1329     /* will bind against everything, just set port */
1330     if (disablev6)
1331     {
1332       /* V4-only */
1333       resi = 1;
1334       if (NULL != unixpath)
1335         resi++;
1336       i = 0;
1337       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1338       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1339       if (NULL != unixpath)
1340       {
1341         add_unixpath (saddrs, saddrlens, unixpath, abstract);
1342         i++;
1343       }
1344       saddrlens[i] = sizeof (struct sockaddr_in);
1345       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1346 #if HAVE_SOCKADDR_IN_SIN_LEN
1347       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1348 #endif
1349       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1350       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1351     }
1352     else
1353     {
1354       /* dual stack */
1355       resi = 2;
1356       if (NULL != unixpath)
1357         resi++;
1358       saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
1359       saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
1360       i = 0;
1361       if (NULL != unixpath)
1362       {
1363         add_unixpath (saddrs, saddrlens, unixpath, abstract);
1364         i++;
1365       }
1366       saddrlens[i] = sizeof (struct sockaddr_in6);
1367       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1368 #if HAVE_SOCKADDR_IN_SIN_LEN
1369       ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1370 #endif
1371       ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1372       ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1373       i++;
1374       saddrlens[i] = sizeof (struct sockaddr_in);
1375       saddrs[i] = GNUNET_malloc (saddrlens[i]);
1376 #if HAVE_SOCKADDR_IN_SIN_LEN
1377       ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1378 #endif
1379       ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1380       ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1381     }
1382   }
1383   GNUNET_free_non_null (unixpath);
1384   *addrs = saddrs;
1385   *addr_lens = saddrlens;
1386   return resi;
1387 }
1388 /* end ancient copy-and-paste */
1389
1390
1391 /**
1392  * If a session monitor is attached, notify it about the new
1393  * session state.
1394  *
1395  * @param plugin our plugin
1396  * @param session session that changed state
1397  * @param state new state of the session
1398  */
1399 static void
1400 notify_session_monitor (struct Plugin *plugin,
1401                         struct GNUNET_ATS_Session *session,
1402                         enum GNUNET_TRANSPORT_SessionState state)
1403 {
1404   struct GNUNET_TRANSPORT_SessionInfo info;
1405
1406   if (NULL == plugin->sic)
1407     return;
1408   memset (&info, 0, sizeof (info));
1409   info.state = state;
1410   info.is_inbound = GNUNET_HELLO_address_check_option (session->address,
1411                                          GNUNET_HELLO_ADDRESS_INFO_INBOUND);
1412   info.num_msg_pending = session->msgs_in_queue;
1413   info.num_bytes_pending = session->bytes_in_queue;
1414   if (NULL != session->receive_delay_task)
1415     info.receive_delay = session->receive_delay;
1416   info.session_timeout = session->timeout;
1417   info.address = session->address;
1418   plugin->sic (plugin->sic_cls,
1419                session,
1420                &info);
1421 }
1422
1423
1424 /**
1425  * Our external IP address/port mapping has changed.
1426  *
1427  * @param cls closure, the `struct Plugin`
1428  * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
1429  *     the previous (now invalid) one
1430  * @param ac address class the address belongs to
1431  * @param addr either the previous or the new public IP address
1432  * @param addrlen actual length of @a addr
1433  */
1434 static void
1435 tcp_nat_port_map_callback (void *cls,
1436                            int add_remove,
1437                            enum GNUNET_NAT_AddressClass ac,
1438                            const struct sockaddr *addr,
1439                            socklen_t addrlen)
1440 {
1441   struct Plugin *plugin = cls;
1442   struct GNUNET_HELLO_Address *address;
1443   struct IPv4TcpAddress t4;
1444   struct IPv6TcpAddress t6;
1445   void *arg;
1446   size_t args;
1447
1448   LOG (GNUNET_ERROR_TYPE_INFO,
1449        "NAT notification to %s address `%s'\n",
1450        (GNUNET_YES == add_remove) ? "add" : "remove",
1451        GNUNET_a2s (addr, addrlen));
1452   /* convert 'addr' to our internal format */
1453   switch (addr->sa_family)
1454   {
1455   case AF_INET:
1456     GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
1457     memset (&t4, 0, sizeof(t4));
1458     t4.options = htonl (plugin->myoptions);
1459     t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1460     t4.t4_port = ((struct sockaddr_in *) addr)->sin_port;
1461     arg = &t4;
1462     args = sizeof (t4);
1463     break;
1464   case AF_INET6:
1465     GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
1466     memset (&t6, 0, sizeof(t6));
1467     GNUNET_memcpy (&t6.ipv6_addr,
1468                    &((struct sockaddr_in6 *) addr)->sin6_addr,
1469                    sizeof(struct in6_addr));
1470     t6.options = htonl (plugin->myoptions);
1471     t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1472     arg = &t6;
1473     args = sizeof (t6);
1474     break;
1475   default:
1476     GNUNET_break(0);
1477     return;
1478   }
1479   /* modify our published address list */
1480   GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
1481                  (args == sizeof (struct IPv6TcpAddress)));
1482   /* TODO: use 'ac' here in the future... */
1483   address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1484                                            PLUGIN_NAME,
1485                                            arg,
1486                                            args,
1487                                            GNUNET_HELLO_ADDRESS_INFO_NONE);
1488   plugin->env->notify_address (plugin->env->cls,
1489                                add_remove,
1490                                address);
1491   GNUNET_HELLO_address_free (address);
1492 }
1493
1494
1495 /**
1496  * Function called for a quick conversion of the binary address to
1497  * a numeric address.  Note that the caller must not free the
1498  * address and that the next call to this function is allowed
1499  * to override the address again.
1500  *
1501  * @param cls closure (`struct Plugin*`)
1502  * @param addr binary address
1503  * @param addrlen length of @a addr
1504  * @return string representing the same address
1505  */
1506 static const char *
1507 tcp_plugin_address_to_string (void *cls,
1508                               const void *addr,
1509                               size_t addrlen)
1510 {
1511   static char rbuf[INET6_ADDRSTRLEN + 12];
1512   char buf[INET6_ADDRSTRLEN];
1513   const void *sb;
1514   struct in_addr a4;
1515   struct in6_addr a6;
1516   const struct IPv4TcpAddress *t4;
1517   const struct IPv6TcpAddress *t6;
1518   int af;
1519   uint16_t port;
1520   uint32_t options;
1521
1522   switch (addrlen)
1523   {
1524   case sizeof(struct IPv6TcpAddress):
1525     t6 = addr;
1526     af = AF_INET6;
1527     port = ntohs (t6->t6_port);
1528     options = ntohl (t6->options);
1529     GNUNET_memcpy (&a6, &t6->ipv6_addr, sizeof(a6));
1530     sb = &a6;
1531     break;
1532   case sizeof(struct IPv4TcpAddress):
1533     t4 = addr;
1534     af = AF_INET;
1535     port = ntohs (t4->t4_port);
1536     options = ntohl (t4->options);
1537     GNUNET_memcpy (&a4, &t4->ipv4_addr, sizeof(a4));
1538     sb = &a4;
1539     break;
1540   default:
1541     LOG (GNUNET_ERROR_TYPE_WARNING,
1542          _("Unexpected address length: %u bytes\n"),
1543          (unsigned int) addrlen);
1544     return NULL ;
1545   }
1546   if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN))
1547   {
1548     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1549                          "inet_ntop");
1550     return NULL ;
1551   }
1552   GNUNET_snprintf (rbuf, sizeof(rbuf),
1553                    (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
1554                    PLUGIN_NAME,
1555                    options,
1556                    buf,
1557                    port);
1558   return rbuf;
1559 }
1560
1561
1562 /**
1563  * Function called to convert a string address to
1564  * a binary address.
1565  *
1566  * @param cls closure (`struct Plugin*`)
1567  * @param addr string address
1568  * @param addrlen length of the address
1569  * @param buf location to store the buffer
1570  * @param added location to store the number of bytes in the buffer.
1571  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
1572  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1573  */
1574 static int
1575 tcp_plugin_string_to_address (void *cls,
1576                               const char *addr,
1577                               uint16_t addrlen,
1578                               void **buf,
1579                               size_t *added)
1580 {
1581   struct sockaddr_storage socket_address;
1582   char *address;
1583   char *plugin;
1584   char *optionstr;
1585   uint32_t options;
1586
1587   /* Format tcp.options.address:port */
1588   address = NULL;
1589   plugin = NULL;
1590   optionstr = NULL;
1591   if ((NULL == addr) || (0 == addrlen))
1592   {
1593     GNUNET_break(0);
1594     return GNUNET_SYSERR;
1595   }
1596   if ('\0' != addr[addrlen - 1])
1597   {
1598     GNUNET_break(0);
1599     return GNUNET_SYSERR;
1600   }
1601   if (strlen (addr) != addrlen - 1)
1602   {
1603     GNUNET_break(0);
1604     return GNUNET_SYSERR;
1605   }
1606   plugin = GNUNET_strdup (addr);
1607   optionstr = strchr (plugin, '.');
1608   if (NULL == optionstr)
1609   {
1610     GNUNET_break(0);
1611     GNUNET_free(plugin);
1612     return GNUNET_SYSERR;
1613   }
1614   optionstr[0] = '\0';
1615   optionstr++;
1616   options = atol (optionstr);
1617   address = strchr (optionstr, '.');
1618   if (NULL == address)
1619   {
1620     GNUNET_break(0);
1621     GNUNET_free(plugin);
1622     return GNUNET_SYSERR;
1623   }
1624   address[0] = '\0';
1625   address++;
1626
1627   if (GNUNET_OK !=
1628       GNUNET_STRINGS_to_address_ip (address,
1629                                     strlen (address),
1630                                     &socket_address))
1631   {
1632     GNUNET_break(0);
1633     GNUNET_free(plugin);
1634     return GNUNET_SYSERR;
1635   }
1636
1637   GNUNET_free(plugin);
1638   switch (socket_address.ss_family)
1639   {
1640   case AF_INET:
1641   {
1642     struct IPv4TcpAddress *t4;
1643     struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
1644     t4 = GNUNET_new (struct IPv4TcpAddress);
1645     t4->options = htonl (options);
1646     t4->ipv4_addr = in4->sin_addr.s_addr;
1647     t4->t4_port = in4->sin_port;
1648     *buf = t4;
1649     *added = sizeof(struct IPv4TcpAddress);
1650     return GNUNET_OK;
1651   }
1652   case AF_INET6:
1653   {
1654     struct IPv6TcpAddress *t6;
1655     struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
1656     t6 = GNUNET_new (struct IPv6TcpAddress);
1657     t6->options = htonl (options);
1658     t6->ipv6_addr = in6->sin6_addr;
1659     t6->t6_port = in6->sin6_port;
1660     *buf = t6;
1661     *added = sizeof(struct IPv6TcpAddress);
1662     return GNUNET_OK;
1663   }
1664   default:
1665     return GNUNET_SYSERR;
1666   }
1667 }
1668
1669
1670 /**
1671  * Find the session handle for the given client.
1672  * Currently uses both the hashmap and the client
1673  * context, as the client context is new and the
1674  * logic still needs to be tested.
1675  *
1676  * @param plugin the plugin
1677  * @param client which client to find the session handle for
1678  * @return NULL if no matching session exists
1679  */
1680 static struct GNUNET_ATS_Session *
1681 lookup_session_by_client (struct Plugin *plugin,
1682                           struct GNUNET_SERVER_Client *client)
1683 {
1684   return GNUNET_SERVER_client_get_user_context (client,
1685                                                 struct GNUNET_ATS_Session);
1686 }
1687
1688
1689 /**
1690  * Functions with this signature are called whenever we need
1691  * to close a session due to a disconnect or failure to
1692  * establish a connection.
1693  *
1694  * @param cls the `struct Plugin`
1695  * @param session session to close down
1696  * @return #GNUNET_OK on success
1697  */
1698 static int
1699 tcp_plugin_disconnect_session (void *cls,
1700                                struct GNUNET_ATS_Session *session)
1701 {
1702   struct Plugin *plugin = cls;
1703   struct PendingMessage *pm;
1704
1705   LOG (GNUNET_ERROR_TYPE_DEBUG,
1706        "Disconnecting session of peer `%s' address `%s'\n",
1707        GNUNET_i2s (&session->target),
1708        tcp_plugin_address_to_string (session->plugin,
1709                                      session->address->address,
1710                                      session->address->address_length));
1711
1712   if (NULL != session->timeout_task)
1713   {
1714     GNUNET_SCHEDULER_cancel (session->timeout_task);
1715     session->timeout_task = NULL;
1716     session->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
1717   }
1718
1719   if (GNUNET_YES ==
1720       GNUNET_CONTAINER_multipeermap_remove (plugin->sessionmap,
1721                                             &session->target,
1722                                             session))
1723   {
1724     GNUNET_STATISTICS_update (session->plugin->env->stats,
1725                               gettext_noop ("# TCP sessions active"),
1726                               -1,
1727                               GNUNET_NO);
1728   }
1729   else
1730   {
1731     GNUNET_assert (GNUNET_YES ==
1732                    GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
1733                                                          &session->target,
1734                                                          session));
1735   }
1736   if (NULL != session->client)
1737     GNUNET_SERVER_client_set_user_context (session->client,
1738                                            NULL);
1739
1740   /* clean up state */
1741   if (NULL != session->transmit_handle)
1742   {
1743     GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle);
1744     session->transmit_handle = NULL;
1745   }
1746   session->plugin->env->session_end (session->plugin->env->cls,
1747                                      session->address,
1748                                      session);
1749
1750   if (NULL != session->nat_connection_timeout)
1751   {
1752     GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
1753     session->nat_connection_timeout = NULL;
1754   }
1755
1756   while (NULL != (pm = session->pending_messages_head))
1757   {
1758     LOG (GNUNET_ERROR_TYPE_DEBUG,
1759          (NULL != pm->transmit_cont)
1760          ? "Could not deliver message to `%s' at %s.\n"
1761          : "Could not deliver message to `%s' at %s, notifying.\n",
1762          GNUNET_i2s (&session->target),
1763          tcp_plugin_address_to_string (session->plugin,
1764                                        session->address->address,
1765                                        session->address->address_length));
1766     GNUNET_STATISTICS_update (session->plugin->env->stats,
1767                               gettext_noop ("# bytes currently in TCP buffers"),
1768                               -(int64_t) pm->message_size, GNUNET_NO);
1769     GNUNET_STATISTICS_update (session->plugin->env->stats,
1770                               gettext_noop ("# bytes discarded by TCP (disconnect)"),
1771                               pm->message_size,
1772                               GNUNET_NO);
1773     GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
1774                                  session->pending_messages_tail,
1775                                  pm);
1776     GNUNET_assert (0 < session->msgs_in_queue);
1777     session->msgs_in_queue--;
1778     GNUNET_assert (pm->message_size <= session->bytes_in_queue);
1779     session->bytes_in_queue -= pm->message_size;
1780     if (NULL != pm->transmit_cont)
1781       pm->transmit_cont (pm->transmit_cont_cls,
1782                          &session->target,
1783                          GNUNET_SYSERR,
1784                          pm->message_size,
1785                          0);
1786     GNUNET_free (pm);
1787   }
1788   GNUNET_assert (0 == session->msgs_in_queue);
1789   GNUNET_assert (0 == session->bytes_in_queue);
1790   notify_session_monitor (session->plugin,
1791                           session,
1792                           GNUNET_TRANSPORT_SS_DONE);
1793
1794   if (NULL != session->receive_delay_task)
1795   {
1796     GNUNET_SCHEDULER_cancel (session->receive_delay_task);
1797     session->receive_delay_task = NULL;
1798   }
1799   if (NULL != session->client)
1800   {
1801     GNUNET_SERVER_client_disconnect (session->client);
1802     session->client = NULL;
1803   }
1804   GNUNET_HELLO_address_free (session->address);
1805   GNUNET_assert (NULL == session->transmit_handle);
1806   GNUNET_free (session);
1807   return GNUNET_OK;
1808 }
1809
1810
1811 /**
1812  * Function that is called to get the keepalive factor.
1813  * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
1814  * calculate the interval between keepalive packets.
1815  *
1816  * @param cls closure with the `struct Plugin`
1817  * @return keepalive factor
1818  */
1819 static unsigned int
1820 tcp_plugin_query_keepalive_factor (void *cls)
1821 {
1822   return 3;
1823 }
1824
1825
1826 /**
1827  * Session was idle for too long, so disconnect it
1828  *
1829  * @param cls the `struct GNUNET_ATS_Session` of the idle session
1830  */
1831 static void
1832 session_timeout (void *cls)
1833 {
1834   struct GNUNET_ATS_Session *s = cls;
1835   struct GNUNET_TIME_Relative left;
1836
1837   s->timeout_task = NULL;
1838   left = GNUNET_TIME_absolute_get_remaining (s->timeout);
1839   if (0 != left.rel_value_us)
1840   {
1841     /* not actually our turn yet, but let's at least update
1842        the monitor, it may think we're about to die ... */
1843     notify_session_monitor (s->plugin,
1844                             s,
1845                             GNUNET_TRANSPORT_SS_UPDATE);
1846     s->timeout_task = GNUNET_SCHEDULER_add_delayed (left,
1847                                                     &session_timeout,
1848                                                     s);
1849     return;
1850   }
1851   LOG (GNUNET_ERROR_TYPE_DEBUG,
1852        "Session %p was idle for %s, disconnecting\n",
1853        s,
1854        GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1855                                                GNUNET_YES));
1856   /* call session destroy function */
1857   tcp_plugin_disconnect_session (s->plugin,
1858                                  s);
1859 }
1860
1861
1862 /**
1863  * Increment session timeout due to activity.
1864  *
1865  * @param s session to increment timeout for
1866  */
1867 static void
1868 reschedule_session_timeout (struct GNUNET_ATS_Session *s)
1869 {
1870   GNUNET_assert (NULL != s->timeout_task);
1871   s->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1872 }
1873
1874
1875 /**
1876  * Create a new session.  Also queues a welcome message.
1877  *
1878  * @param plugin the plugin
1879  * @param address the address to create the session for
1880  * @param scope network scope the address is from
1881  * @param client client to use, reference counter must have already been increased
1882  * @param is_nat this a NAT session, we should wait for a client to
1883  *               connect to us from an address, then assign that to
1884  *               the session
1885  * @return new session object
1886  */
1887 static struct GNUNET_ATS_Session *
1888 create_session (struct Plugin *plugin,
1889                 const struct GNUNET_HELLO_Address *address,
1890                 enum GNUNET_ATS_Network_Type scope,
1891                 struct GNUNET_SERVER_Client *client,
1892                 int is_nat)
1893 {
1894   struct GNUNET_ATS_Session *session;
1895   struct PendingMessage *pm;
1896
1897   if (GNUNET_YES != is_nat)
1898     GNUNET_assert (NULL != client);
1899   else
1900     GNUNET_assert (NULL == client);
1901
1902   LOG (GNUNET_ERROR_TYPE_DEBUG,
1903        "Creating new session for peer `%s' at address %s\n",
1904        GNUNET_i2s (&address->peer),
1905        tcp_plugin_address_to_string (plugin,
1906                                      address->address,
1907                                      address->address_length));
1908   session = GNUNET_new (struct GNUNET_ATS_Session);
1909   session->last_activity = GNUNET_TIME_absolute_get ();
1910   session->plugin = plugin;
1911   session->is_nat = is_nat;
1912   if (NULL != client)
1913   {
1914     session->client = client;
1915     GNUNET_SERVER_client_set_user_context (client,
1916                                            session);
1917   }
1918   session->address = GNUNET_HELLO_address_copy (address);
1919   session->target = address->peer;
1920   session->expecting_welcome = GNUNET_YES;
1921   session->scope = scope;
1922   pm = GNUNET_malloc (sizeof (struct PendingMessage) +
1923                       sizeof (struct WelcomeMessage));
1924   pm->msg = (const char *) &pm[1];
1925   pm->message_size = sizeof(struct WelcomeMessage);
1926   GNUNET_memcpy (&pm[1],
1927           &plugin->my_welcome,
1928           sizeof(struct WelcomeMessage));
1929   pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1930   GNUNET_STATISTICS_update (plugin->env->stats,
1931                             gettext_noop ("# bytes currently in TCP buffers"),
1932                             pm->message_size,
1933                             GNUNET_NO);
1934   GNUNET_CONTAINER_DLL_insert (session->pending_messages_head,
1935                                session->pending_messages_tail,
1936                                pm);
1937   session->msgs_in_queue++;
1938   session->bytes_in_queue += pm->message_size;
1939   session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1940   session->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1941                                                         &session_timeout,
1942                                                         session);
1943   notify_session_monitor (session->plugin,
1944                           session,
1945                           GNUNET_TRANSPORT_SS_INIT);
1946   if (GNUNET_YES != is_nat)
1947   {
1948     GNUNET_STATISTICS_update (plugin->env->stats,
1949                               gettext_noop ("# TCP sessions active"),
1950                               1,
1951                               GNUNET_NO);
1952     notify_session_monitor (session->plugin,
1953                             session,
1954                             GNUNET_TRANSPORT_SS_UP);
1955   }
1956   else
1957   {
1958     notify_session_monitor (session->plugin,
1959                             session,
1960                             GNUNET_TRANSPORT_SS_HANDSHAKE);
1961   }
1962   return session;
1963 }
1964
1965
1966 /**
1967  * If we have pending messages, ask the server to
1968  * transmit them (schedule the respective tasks, etc.)
1969  *
1970  * @param session for which session should we do this
1971  */
1972 static void
1973 process_pending_messages (struct GNUNET_ATS_Session *session);
1974
1975
1976 /**
1977  * Function called to notify a client about the socket
1978  * being ready to queue more data.  "buf" will be
1979  * NULL and "size" zero if the socket was closed for
1980  * writing in the meantime.
1981  *
1982  * @param cls closure
1983  * @param size number of bytes available in @a buf
1984  * @param buf where the callee should write the message
1985  * @return number of bytes written to @a buf
1986  */
1987 static size_t
1988 do_transmit (void *cls,
1989              size_t size,
1990              void *buf)
1991 {
1992   struct GNUNET_ATS_Session *session = cls;
1993   struct GNUNET_PeerIdentity pid;
1994   struct Plugin *plugin;
1995   struct PendingMessage *pos;
1996   struct PendingMessage *hd;
1997   struct PendingMessage *tl;
1998   struct GNUNET_TIME_Absolute now;
1999   char *cbuf;
2000   size_t ret;
2001
2002   session->transmit_handle = NULL;
2003   plugin = session->plugin;
2004   if (NULL == buf)
2005   {
2006     LOG (GNUNET_ERROR_TYPE_DEBUG,
2007          "Timeout trying to transmit to peer `%s', discarding message queue.\n",
2008          GNUNET_i2s (&session->target));
2009     /* timeout; cancel all messages that have already expired */
2010     hd = NULL;
2011     tl = NULL;
2012     ret = 0;
2013     now = GNUNET_TIME_absolute_get ();
2014     while ( (NULL != (pos = session->pending_messages_head)) &&
2015             (pos->timeout.abs_value_us <= now.abs_value_us) )
2016     {
2017       GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
2018                                    session->pending_messages_tail,
2019                                    pos);
2020       GNUNET_assert (0 < session->msgs_in_queue);
2021       session->msgs_in_queue--;
2022       GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2023       session->bytes_in_queue -= pos->message_size;
2024       LOG (GNUNET_ERROR_TYPE_DEBUG,
2025            "Failed to transmit %u byte message to `%s'.\n",
2026            pos->message_size,
2027            GNUNET_i2s (&session->target));
2028       ret += pos->message_size;
2029       GNUNET_CONTAINER_DLL_insert_after (hd,
2030                                          tl,
2031                                          tl,
2032                                          pos);
2033     }
2034     /* do this call before callbacks (so that if callbacks destroy
2035      * session, they have a chance to cancel actions done by this
2036      * call) */
2037     process_pending_messages (session);
2038     pid = session->target;
2039     /* no do callbacks and do not use session again since
2040      * the callbacks may abort the session */
2041     while (NULL != (pos = hd))
2042     {
2043       GNUNET_CONTAINER_DLL_remove (hd,
2044                                    tl,
2045                                    pos);
2046       if (NULL != pos->transmit_cont)
2047         pos->transmit_cont (pos->transmit_cont_cls,
2048                             &pid,
2049                             GNUNET_SYSERR,
2050                             pos->message_size,
2051                             0);
2052       GNUNET_free (pos);
2053     }
2054     GNUNET_STATISTICS_update (plugin->env->stats,
2055                               gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret,
2056                               GNUNET_NO);
2057     GNUNET_STATISTICS_update (plugin->env->stats,
2058                               gettext_noop ("# bytes discarded by TCP (timeout)"),
2059                               ret,
2060                               GNUNET_NO);
2061     if (0 < ret)
2062       notify_session_monitor (session->plugin,
2063                               session,
2064                               GNUNET_TRANSPORT_SS_UPDATE);
2065     return 0;
2066   }
2067   /* copy all pending messages that would fit */
2068   ret = 0;
2069   cbuf = buf;
2070   hd = NULL;
2071   tl = NULL;
2072   while (NULL != (pos = session->pending_messages_head))
2073   {
2074     if (ret + pos->message_size > size)
2075       break;
2076     GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
2077                                  session->pending_messages_tail,
2078                                  pos);
2079     GNUNET_assert (0 < session->msgs_in_queue);
2080     session->msgs_in_queue--;
2081     GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2082     session->bytes_in_queue -= pos->message_size;
2083     GNUNET_assert(size >= pos->message_size);
2084     LOG (GNUNET_ERROR_TYPE_DEBUG,
2085          "Transmitting message of type %u size %u to peer %s at %s\n",
2086          ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type),
2087          pos->message_size,
2088          GNUNET_i2s (&session->target),
2089          tcp_plugin_address_to_string (session->plugin,
2090                                        session->address->address,
2091                                        session->address->address_length));
2092     /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
2093     GNUNET_memcpy (cbuf,
2094             pos->msg,
2095             pos->message_size);
2096     cbuf += pos->message_size;
2097     ret += pos->message_size;
2098     size -= pos->message_size;
2099     GNUNET_CONTAINER_DLL_insert_tail (hd,
2100                                       tl,
2101                                       pos);
2102   }
2103   notify_session_monitor (session->plugin,
2104                           session,
2105                           GNUNET_TRANSPORT_SS_UPDATE);
2106   /* schedule 'continuation' before callbacks so that callbacks that
2107    * cancel everything don't cause us to use a session that no longer
2108    * exists... */
2109   process_pending_messages (session);
2110   session->last_activity = GNUNET_TIME_absolute_get ();
2111   pid = session->target;
2112   /* we'll now call callbacks that may cancel the session; hence
2113    * we should not use 'session' after this point */
2114   while (NULL != (pos = hd))
2115   {
2116     GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
2117     if (NULL != pos->transmit_cont)
2118       pos->transmit_cont (pos->transmit_cont_cls,
2119                           &pid,
2120                           GNUNET_OK,
2121                           pos->message_size,
2122                           pos->message_size); /* FIXME: include TCP overhead */
2123     GNUNET_free (pos);
2124   }
2125   GNUNET_assert (NULL == hd);
2126   GNUNET_assert (NULL == tl);
2127   GNUNET_STATISTICS_update (plugin->env->stats,
2128                             gettext_noop ("# bytes currently in TCP buffers"),
2129                             - (int64_t) ret,
2130                             GNUNET_NO);
2131   GNUNET_STATISTICS_update (plugin->env->stats,
2132                             gettext_noop ("# bytes transmitted via TCP"),
2133                             ret,
2134                             GNUNET_NO);
2135   return ret;
2136 }
2137
2138
2139 /**
2140  * If we have pending messages, ask the server to
2141  * transmit them (schedule the respective tasks, etc.)
2142  *
2143  * @param session for which session should we do this
2144  */
2145 static void
2146 process_pending_messages (struct GNUNET_ATS_Session *session)
2147 {
2148   struct PendingMessage *pm;
2149
2150   GNUNET_assert (NULL != session->client);
2151   if (NULL != session->transmit_handle)
2152     return;
2153   if (NULL == (pm = session->pending_messages_head))
2154     return;
2155
2156   session->transmit_handle
2157     = GNUNET_SERVER_notify_transmit_ready (session->client,
2158                                            pm->message_size,
2159                                            GNUNET_TIME_absolute_get_remaining (pm->timeout),
2160                                            &do_transmit,
2161                                            session);
2162 }
2163
2164
2165 /**
2166  * Function that can be used by the transport service to transmit
2167  * a message using the plugin.   Note that in the case of a
2168  * peer disconnecting, the continuation MUST be called
2169  * prior to the disconnect notification itself.  This function
2170  * will be called with this peer's HELLO message to initiate
2171  * a fresh connection to another peer.
2172  *
2173  * @param cls closure
2174  * @param session which session must be used
2175  * @param msgbuf the message to transmit
2176  * @param msgbuf_size number of bytes in @a msgbuf
2177  * @param priority how important is the message (most plugins will
2178  *                 ignore message priority and just FIFO)
2179  * @param to how long to wait at most for the transmission (does not
2180  *                require plugins to discard the message after the timeout,
2181  *                just advisory for the desired delay; most plugins will ignore
2182  *                this as well)
2183  * @param cont continuation to call once the message has
2184  *        been transmitted (or if the transport is ready
2185  *        for the next transmission call; or if the
2186  *        peer disconnected...); can be NULL
2187  * @param cont_cls closure for @a cont
2188  * @return number of bytes used (on the physical network, with overheads);
2189  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
2190  *         and does NOT mean that the message was not transmitted (DV)
2191  */
2192 static ssize_t
2193 tcp_plugin_send (void *cls,
2194                  struct GNUNET_ATS_Session *session,
2195                  const char *msgbuf,
2196                  size_t msgbuf_size,
2197                  unsigned int priority,
2198                  struct GNUNET_TIME_Relative to,
2199                  GNUNET_TRANSPORT_TransmitContinuation cont,
2200                  void *cont_cls)
2201 {
2202   struct Plugin * plugin = cls;
2203   struct PendingMessage *pm;
2204
2205   /* create new message entry */
2206   pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
2207   pm->msg = (const char *) &pm[1];
2208   GNUNET_memcpy (&pm[1], msgbuf, msgbuf_size);
2209   pm->message_size = msgbuf_size;
2210   pm->timeout = GNUNET_TIME_relative_to_absolute (to);
2211   pm->transmit_cont = cont;
2212   pm->transmit_cont_cls = cont_cls;
2213
2214   LOG (GNUNET_ERROR_TYPE_DEBUG,
2215        "Asked to transmit %u bytes to `%s', added message to list.\n",
2216        msgbuf_size,
2217        GNUNET_i2s (&session->target));
2218
2219   if (GNUNET_YES ==
2220       GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
2221                                                     &session->target,
2222                                                     session))
2223   {
2224     GNUNET_assert (NULL != session->client);
2225     GNUNET_SERVER_client_set_timeout (session->client,
2226                                       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2227     GNUNET_STATISTICS_update (plugin->env->stats,
2228                               gettext_noop ("# bytes currently in TCP buffers"),
2229                               msgbuf_size,
2230                               GNUNET_NO);
2231
2232     /* append pm to pending_messages list */
2233     GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
2234                                       session->pending_messages_tail,
2235                                       pm);
2236     notify_session_monitor (session->plugin,
2237                             session,
2238                             GNUNET_TRANSPORT_SS_UPDATE);
2239     session->msgs_in_queue++;
2240     session->bytes_in_queue += pm->message_size;
2241     process_pending_messages (session);
2242     return msgbuf_size;
2243   }
2244   if (GNUNET_YES ==
2245       GNUNET_CONTAINER_multipeermap_contains_value (plugin->nat_wait_conns,
2246                                                     &session->target,
2247                                                     session))
2248   {
2249     LOG (GNUNET_ERROR_TYPE_DEBUG,
2250          "This NAT WAIT session for peer `%s' is not yet ready!\n",
2251          GNUNET_i2s (&session->target));
2252     GNUNET_STATISTICS_update (plugin->env->stats,
2253                               gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size,
2254                               GNUNET_NO);
2255     /* append pm to pending_messages list */
2256     GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
2257                                       session->pending_messages_tail,
2258                                       pm);
2259     session->msgs_in_queue++;
2260     session->bytes_in_queue += pm->message_size;
2261     notify_session_monitor (session->plugin,
2262                             session,
2263                             GNUNET_TRANSPORT_SS_HANDSHAKE);
2264     return msgbuf_size;
2265   }
2266   LOG (GNUNET_ERROR_TYPE_ERROR,
2267        "Invalid session %p\n",
2268        session);
2269   if (NULL != cont)
2270     cont (cont_cls,
2271           &session->target,
2272           GNUNET_SYSERR,
2273           pm->message_size,
2274           0);
2275   GNUNET_break (0);
2276   GNUNET_free (pm);
2277   return GNUNET_SYSERR; /* session does not exist here */
2278 }
2279
2280
2281 /**
2282  * Closure for #session_lookup_it().
2283  */
2284 struct GNUNET_ATS_SessionItCtx
2285 {
2286   /**
2287    * Address we are looking for.
2288    */
2289   const struct GNUNET_HELLO_Address *address;
2290
2291   /**
2292    * Where to store the session (if we found it).
2293    */
2294   struct GNUNET_ATS_Session *result;
2295
2296 };
2297
2298
2299 /**
2300  * Look for a session by address.
2301  *
2302  * @param cls the `struct GNUNET_ATS_SessionItCtx`
2303  * @param key unused
2304  * @param value a `struct GNUNET_ATS_Session`
2305  * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the session
2306  */
2307 static int
2308 session_lookup_it (void *cls,
2309                    const struct GNUNET_PeerIdentity *key,
2310                    void *value)
2311 {
2312   struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
2313   struct GNUNET_ATS_Session *session = value;
2314
2315   if (0 !=
2316       GNUNET_HELLO_address_cmp (si_ctx->address,
2317                                 session->address))
2318     return GNUNET_YES;
2319   si_ctx->result = session;
2320   return GNUNET_NO;
2321 }
2322
2323
2324 /**
2325  * Task cleaning up a NAT connection attempt after timeout
2326  *
2327  * @param cls the `struct GNUNET_ATS_Session`
2328  */
2329 static void
2330 nat_connect_timeout (void *cls)
2331 {
2332   struct GNUNET_ATS_Session *session = cls;
2333
2334   session->nat_connection_timeout = NULL;
2335   LOG (GNUNET_ERROR_TYPE_DEBUG,
2336        "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
2337        GNUNET_i2s (&session->target),
2338        tcp_plugin_address_to_string (session->plugin,
2339                                      session->address->address,
2340                                      session->address->address_length));
2341   tcp_plugin_disconnect_session (session->plugin,
2342                                  session);
2343 }
2344
2345
2346 /**
2347  * Function that will be called whenever the transport service wants to
2348  * notify the plugin that a session is still active and in use and
2349  * therefore the session timeout for this session has to be updated
2350  *
2351  * @param cls closure
2352  * @param peer which peer was the session for
2353  * @param session which session is being updated
2354  */
2355 static void
2356 tcp_plugin_update_session_timeout (void *cls,
2357                                    const struct GNUNET_PeerIdentity *peer,
2358                                    struct GNUNET_ATS_Session *session)
2359 {
2360   reschedule_session_timeout (session);
2361 }
2362
2363
2364 /**
2365  * Task to signal the server that we can continue
2366  * receiving from the TCP client now.
2367  *
2368  * @param cls the `struct GNUNET_ATS_Session *`
2369  */
2370 static void
2371 delayed_done (void *cls)
2372 {
2373   struct GNUNET_ATS_Session *session = cls;
2374
2375   session->receive_delay_task = NULL;
2376   reschedule_session_timeout (session);
2377   GNUNET_SERVER_receive_done (session->client,
2378                               GNUNET_OK);
2379 }
2380
2381
2382 /**
2383  * Function that will be called whenever the transport service wants to
2384  * notify the plugin that the inbound quota changed and that the plugin
2385  * should update it's delay for the next receive value
2386  *
2387  * @param cls closure
2388  * @param peer which peer was the session for
2389  * @param session which session is being updated
2390  * @param delay new delay to use for receiving
2391  */
2392 static void
2393 tcp_plugin_update_inbound_delay (void *cls,
2394                                  const struct GNUNET_PeerIdentity *peer,
2395                                  struct GNUNET_ATS_Session *session,
2396                                  struct GNUNET_TIME_Relative delay)
2397 {
2398   if (NULL == session->receive_delay_task)
2399     return;
2400   LOG (GNUNET_ERROR_TYPE_DEBUG,
2401        "New inbound delay %s\n",
2402        GNUNET_STRINGS_relative_time_to_string (delay,
2403                                                GNUNET_NO));
2404   session->receive_delay = GNUNET_TIME_relative_to_absolute (delay);
2405   GNUNET_SCHEDULER_cancel (session->receive_delay_task);
2406   session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
2407                                                               &delayed_done,
2408                                                               session);
2409 }
2410
2411
2412 /**
2413  * Create a new session to transmit data to the target
2414  * This session will used to send data to this peer and the plugin will
2415  * notify us by calling the env->session_end function
2416  *
2417  * @param cls closure
2418  * @param address the address to use
2419  * @return the session if the address is valid, NULL otherwise
2420  */
2421 static struct GNUNET_ATS_Session *
2422 tcp_plugin_get_session (void *cls,
2423                         const struct GNUNET_HELLO_Address *address)
2424 {
2425   struct Plugin *plugin = cls;
2426   struct GNUNET_ATS_Session *session = NULL;
2427   int af;
2428   const void *sb;
2429   size_t sbs;
2430   struct GNUNET_CONNECTION_Handle *sa;
2431   struct sockaddr_in a4;
2432   struct sockaddr_in6 a6;
2433   const struct IPv4TcpAddress *t4;
2434   const struct IPv6TcpAddress *t6;
2435   unsigned int options;
2436   enum GNUNET_ATS_Network_Type net_type;
2437   unsigned int is_natd = GNUNET_NO;
2438   size_t addrlen;
2439 #ifdef TCP_STEALTH
2440   struct GNUNET_NETWORK_Handle *s;
2441 #endif
2442
2443   addrlen = address->address_length;
2444   LOG (GNUNET_ERROR_TYPE_DEBUG,
2445        "Trying to get session for `%s' address of peer `%s'\n",
2446        tcp_plugin_address_to_string (plugin,
2447                                      address->address,
2448                                      address->address_length),
2449        GNUNET_i2s (&address->peer));
2450
2451   if (GNUNET_HELLO_address_check_option (address,
2452                                          GNUNET_HELLO_ADDRESS_INFO_INBOUND))
2453   {
2454     GNUNET_break (0);
2455     return NULL;
2456   }
2457
2458   /* look for existing session */
2459   if (GNUNET_YES ==
2460       GNUNET_CONTAINER_multipeermap_contains (plugin->sessionmap,
2461                                               &address->peer))
2462   {
2463     struct GNUNET_ATS_SessionItCtx si_ctx;
2464
2465     si_ctx.address = address;
2466     si_ctx.result = NULL;
2467     GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
2468                                                 &address->peer,
2469                                                 &session_lookup_it,
2470                                                 &si_ctx);
2471     if (NULL != si_ctx.result)
2472     {
2473       session = si_ctx.result;
2474       LOG (GNUNET_ERROR_TYPE_DEBUG,
2475            "Found existing session for `%s' address `%s'\n",
2476            GNUNET_i2s (&address->peer),
2477            tcp_plugin_address_to_string (plugin,
2478                                          address->address,
2479                                          address->address_length));
2480       return session;
2481     }
2482     /* This is a bit of a hack, limiting TCP to never allow more than
2483        one TCP connection to any given peer at the same time.
2484        Without this, peers sometimes disagree about which of the TCP
2485        connections they should use, causing one side to believe that
2486        they transmit successfully, while the other receives nothing. */
2487     return NULL; /* Refuse to have more than one TCP connection per
2488                     peer pair at the same time. */
2489   }
2490
2491   if (addrlen == sizeof(struct IPv6TcpAddress))
2492   {
2493     GNUNET_assert (NULL != address->address); /* make static analysis happy */
2494     t6 = address->address;
2495     options = t6->options;
2496     af = AF_INET6;
2497     memset (&a6, 0, sizeof(a6));
2498 #if HAVE_SOCKADDR_IN_SIN_LEN
2499     a6.sin6_len = sizeof (a6);
2500 #endif
2501     a6.sin6_family = AF_INET6;
2502     a6.sin6_port = t6->t6_port;
2503     if (t6->t6_port == 0)
2504       is_natd = GNUNET_YES;
2505     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2506     sb = &a6;
2507     sbs = sizeof(a6);
2508   }
2509   else if (addrlen == sizeof(struct IPv4TcpAddress))
2510   {
2511     GNUNET_assert(NULL != address->address); /* make static analysis happy */
2512     t4 = address->address;
2513     options = t4->options;
2514     af = AF_INET;
2515     memset (&a4, 0, sizeof(a4));
2516 #if HAVE_SOCKADDR_IN_SIN_LEN
2517     a4.sin_len = sizeof (a4);
2518 #endif
2519     a4.sin_family = AF_INET;
2520     a4.sin_port = t4->t4_port;
2521     if (t4->t4_port == 0)
2522       is_natd = GNUNET_YES;
2523     a4.sin_addr.s_addr = t4->ipv4_addr;
2524     sb = &a4;
2525     sbs = sizeof(a4);
2526   }
2527   else
2528   {
2529     GNUNET_STATISTICS_update (plugin->env->stats,
2530                               gettext_noop ("# requests to create session with invalid address"),
2531                               1,
2532                               GNUNET_NO);
2533     return NULL;
2534   }
2535
2536   net_type = plugin->env->get_address_type (plugin->env->cls,
2537                                             sb,
2538                                             sbs);
2539   GNUNET_break (net_type != GNUNET_ATS_NET_UNSPECIFIED);
2540
2541   if ( (is_natd == GNUNET_YES) &&
2542        (addrlen == sizeof(struct IPv6TcpAddress)) )
2543   {
2544     /* NAT client only works with IPv4 addresses */
2545     return NULL;
2546   }
2547
2548   if (plugin->cur_connections >= plugin->max_connections)
2549   {
2550     /* saturated */
2551     return NULL;
2552   }
2553
2554   if ( (is_natd == GNUNET_YES) &&
2555        (GNUNET_YES ==
2556         GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
2557                                                 &address->peer)))
2558   {
2559     /* Only do one NAT punch attempt per peer identity */
2560     return NULL;
2561   }
2562
2563   if ( (is_natd == GNUNET_YES) &&
2564        (NULL != plugin->nat) &&
2565        (GNUNET_NO ==
2566         GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
2567                                                 &address->peer)))
2568   {
2569     struct sockaddr_in local_sa;
2570
2571     LOG (GNUNET_ERROR_TYPE_DEBUG,
2572          "Found valid IPv4 NAT address (creating session)!\n");
2573     session = create_session (plugin,
2574                               address,
2575                               net_type,
2576                               NULL,
2577                               GNUNET_YES);
2578     session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT,
2579                                                                     &nat_connect_timeout,
2580                                                                     session);
2581     GNUNET_assert (GNUNET_OK ==
2582                    GNUNET_CONTAINER_multipeermap_put (plugin->nat_wait_conns,
2583                                                       &session->target,
2584                                                       session,
2585                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2586
2587     LOG (GNUNET_ERROR_TYPE_DEBUG,
2588          "Created NAT WAIT connection to `%s' at `%s'\n",
2589          GNUNET_i2s (&session->target),
2590          GNUNET_a2s (sb, sbs));
2591     memset (&local_sa,
2592             0,
2593             sizeof (local_sa));
2594     local_sa.sin_family = AF_INET;
2595     local_sa.sin_port = htons (plugin->open_port);
2596     /* We leave sin_address at 0, let the kernel figure it out,
2597        even if our bind() is more specific.  (May want to reconsider
2598        later.) */
2599     if (GNUNET_OK ==
2600         GNUNET_NAT_request_reversal (plugin->nat,
2601                                      &local_sa,
2602                                      &a4))
2603       return session;
2604     LOG (GNUNET_ERROR_TYPE_DEBUG,
2605          "Running NAT client for `%s' at `%s' failed\n",
2606          GNUNET_i2s (&session->target),
2607          GNUNET_a2s (sb, sbs));
2608     tcp_plugin_disconnect_session (plugin,
2609                                    session);
2610     return NULL;
2611   }
2612
2613   /* create new outbound session */
2614   if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
2615   {
2616 #ifdef TCP_STEALTH
2617     s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
2618     if (NULL == s)
2619     {
2620       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
2621                            "socket");
2622       sa = NULL;
2623     }
2624     else
2625     {
2626       if ( (GNUNET_OK !=
2627             GNUNET_NETWORK_socket_setsockopt (s,
2628                                               IPPROTO_TCP,
2629                                               TCP_STEALTH,
2630                                               &session->target,
2631                                               sizeof (struct GNUNET_PeerIdentity))) ||
2632            (GNUNET_OK !=
2633             GNUNET_NETWORK_socket_setsockopt (s,
2634                                               IPPROTO_TCP,
2635                                               TCP_STEALTH_INTEGRITY,
2636                                               &plugin->my_welcome,
2637                                               sizeof (struct WelcomeMessage))) )
2638       {
2639         /* TCP STEALTH not supported by kernel */
2640         GNUNET_break (GNUNET_OK ==
2641                       GNUNET_NETWORK_socket_close (s));
2642         sa = NULL;
2643       }
2644       else
2645       {
2646         sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
2647       }
2648     }
2649 #else
2650     sa = NULL;
2651 #endif
2652   }
2653   else
2654   {
2655     sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
2656   }
2657   if (NULL == sa)
2658   {
2659     LOG (GNUNET_ERROR_TYPE_DEBUG,
2660          "Failed to create connection to `%s' at `%s'\n",
2661          GNUNET_i2s (&address->peer),
2662          GNUNET_a2s (sb, sbs));
2663     return NULL;
2664   }
2665   LOG (GNUNET_ERROR_TYPE_DEBUG,
2666        "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
2667        GNUNET_i2s (&address->peer),
2668        GNUNET_a2s (sb, sbs));
2669
2670   session = create_session (plugin,
2671                             address,
2672                             net_type,
2673                             GNUNET_SERVER_connect_socket (plugin->server,
2674                                                           sa),
2675                             GNUNET_NO);
2676   (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
2677                                             &session->target,
2678                                             session,
2679                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2680   /* Send TCP Welcome */
2681   process_pending_messages (session);
2682
2683   return session;
2684 }
2685
2686
2687 /**
2688  * We have been asked to destroy all connections to a particular peer.
2689  * This function is called on each applicable session and must tear it
2690  * down.
2691  *
2692  * @param cls the `struct Plugin *`
2693  * @param key the peer which the session belongs to (unused)
2694  * @param value the `struct GNUNET_ATS_Session`
2695  * @return #GNUNET_YES (continue to iterate)
2696  */
2697 static int
2698 session_disconnect_it (void *cls,
2699                        const struct GNUNET_PeerIdentity *key,
2700                        void *value)
2701 {
2702   struct Plugin *plugin = cls;
2703   struct GNUNET_ATS_Session *session = value;
2704
2705   GNUNET_STATISTICS_update (session->plugin->env->stats,
2706                             gettext_noop ("# transport-service disconnect requests for TCP"),
2707                             1,
2708                             GNUNET_NO);
2709   tcp_plugin_disconnect_session (plugin,
2710                                  session);
2711   return GNUNET_YES;
2712 }
2713
2714
2715 /**
2716  * Function that can be called to force a disconnect from the
2717  * specified neighbour.  This should also cancel all previously
2718  * scheduled transmissions.  Obviously the transmission may have been
2719  * partially completed already, which is OK.  The plugin is supposed
2720  * to close the connection (if applicable) and no longer call the
2721  * transmit continuation(s).
2722  *
2723  * Finally, plugin MUST NOT call the services's receive function to
2724  * notify the service that the connection to the specified target was
2725  * closed after a getting this call.
2726  *
2727  * @param cls closure
2728  * @param target peer for which the last transmission is
2729  *        to be cancelled
2730  */
2731 static void
2732 tcp_plugin_disconnect (void *cls,
2733                        const struct GNUNET_PeerIdentity *target)
2734 {
2735   struct Plugin *plugin = cls;
2736
2737   LOG (GNUNET_ERROR_TYPE_DEBUG,
2738        "Disconnecting peer `%s'\n",
2739        GNUNET_i2s (target));
2740   GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
2741                                               target,
2742                                               &session_disconnect_it,
2743                                               plugin);
2744   GNUNET_CONTAINER_multipeermap_get_multiple (plugin->nat_wait_conns,
2745                                               target,
2746                                               &session_disconnect_it,
2747                                               plugin);
2748 }
2749
2750
2751 /**
2752  * We are processing an address pretty printing request and finished
2753  * the IP resolution (if applicable).  Append our port and forward the
2754  * result.  If called with @a hostname NULL, we are done and should
2755  * clean up the pretty printer (otherwise, there might be multiple
2756  * hostnames for the IP address and we might receive more).
2757  *
2758  * @param cls the `struct PrettyPrinterContext *`
2759  * @param hostname hostname part of the address
2760  */
2761 static void
2762 append_port (void *cls,
2763              const char *hostname)
2764 {
2765   struct PrettyPrinterContext *ppc = cls;
2766   struct Plugin *plugin = ppc->plugin;
2767   char *ret;
2768
2769   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2770               "append_port called with hostname `%s'\n",
2771               hostname);
2772   if (NULL == hostname)
2773   {
2774     /* Final call, done */
2775     ppc->resolver_handle = NULL;
2776     GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
2777                                  plugin->ppc_dll_tail,
2778                                  ppc);
2779     ppc->asc (ppc->asc_cls,
2780               NULL,
2781               GNUNET_OK);
2782     GNUNET_free (ppc);
2783     return;
2784   }
2785   if (GNUNET_YES == ppc->ipv6)
2786     GNUNET_asprintf (&ret,
2787                      "%s.%u.[%s]:%d",
2788                      PLUGIN_NAME,
2789                      ppc->options,
2790                      hostname,
2791                      ppc->port);
2792   else
2793     GNUNET_asprintf (&ret,
2794                      "%s.%u.%s:%d",
2795                      PLUGIN_NAME,
2796                      ppc->options,
2797                      hostname,
2798                      ppc->port);
2799   ppc->asc (ppc->asc_cls,
2800             ret,
2801             GNUNET_OK);
2802   GNUNET_free (ret);
2803 }
2804
2805
2806 /**
2807  * Convert the transports address to a nice, human-readable format.
2808  *
2809  * @param cls closure with the `struct Plugin`
2810  * @param type name of the transport that generated the address
2811  * @param addr one of the addresses of the host, NULL for the last address
2812  *        the specific address format depends on the transport
2813  * @param addrlen length of the @a addr
2814  * @param numeric should (IP) addresses be displayed in numeric form?
2815  * @param timeout after how long should we give up?
2816  * @param asc function to call on each string
2817  * @param asc_cls closure for @a asc
2818  */
2819 static void
2820 tcp_plugin_address_pretty_printer (void *cls,
2821                                    const char *type,
2822                                    const void *addr,
2823                                    size_t addrlen,
2824                                    int numeric,
2825                                    struct GNUNET_TIME_Relative timeout,
2826                                    GNUNET_TRANSPORT_AddressStringCallback asc,
2827                                    void *asc_cls)
2828 {
2829   struct Plugin *plugin = cls;
2830   struct PrettyPrinterContext *ppc;
2831   const void *sb;
2832   size_t sbs;
2833   struct sockaddr_in a4;
2834   struct sockaddr_in6 a6;
2835   const struct IPv4TcpAddress *t4;
2836   const struct IPv6TcpAddress *t6;
2837   uint16_t port;
2838   uint32_t options;
2839
2840   if (sizeof(struct IPv6TcpAddress) == addrlen)
2841   {
2842     t6 = addr;
2843     memset (&a6, 0, sizeof(a6));
2844     a6.sin6_family = AF_INET6;
2845     a6.sin6_port = t6->t6_port;
2846     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2847     port = ntohs (t6->t6_port);
2848     options = ntohl (t6->options);
2849     sb = &a6;
2850     sbs = sizeof(a6);
2851   }
2852   else if (sizeof(struct IPv4TcpAddress) == addrlen)
2853   {
2854     t4 = addr;
2855     memset (&a4, 0, sizeof(a4));
2856     a4.sin_family = AF_INET;
2857     a4.sin_port = t4->t4_port;
2858     a4.sin_addr.s_addr = t4->ipv4_addr;
2859     port = ntohs (t4->t4_port);
2860     options = ntohl (t4->options);
2861     sb = &a4;
2862     sbs = sizeof(a4);
2863   }
2864   else
2865   {
2866     /* invalid address */
2867     LOG (GNUNET_ERROR_TYPE_WARNING,
2868          _("Unexpected address length: %u bytes\n"),
2869          (unsigned int) addrlen);
2870     asc (asc_cls, NULL, GNUNET_SYSERR);
2871     asc (asc_cls, NULL, GNUNET_OK);
2872     return;
2873   }
2874   ppc = GNUNET_new (struct PrettyPrinterContext);
2875   ppc->plugin = plugin;
2876   if (addrlen == sizeof(struct IPv6TcpAddress))
2877     ppc->ipv6 = GNUNET_YES;
2878   else
2879     ppc->ipv6 = GNUNET_NO;
2880   ppc->asc = asc;
2881   ppc->asc_cls = asc_cls;
2882   ppc->port = port;
2883   ppc->options = options;
2884   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2885               "Starting DNS reverse lookup\n");
2886   ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb,
2887                                                        sbs,
2888                                                        ! numeric,
2889                                                        timeout,
2890                                                        &append_port,
2891                                                        ppc);
2892   if (NULL == ppc->resolver_handle)
2893   {
2894     GNUNET_break (0);
2895     GNUNET_free (ppc);
2896     return;
2897   }
2898   GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head,
2899                                plugin->ppc_dll_tail,
2900                                ppc);
2901 }
2902
2903
2904 /**
2905  * Function that will be called to check if a binary address for this
2906  * plugin is well-formed and corresponds to an address for THIS peer
2907  * (as per our configuration).  Naturally, if absolutely necessary,
2908  * plugins can be a bit conservative in their answer, but in general
2909  * plugins should make sure that the address does not redirect
2910  * traffic to a 3rd party that might try to man-in-the-middle our
2911  * traffic.
2912  *
2913  * @param cls closure, our `struct Plugin *`
2914  * @param addr pointer to the address
2915  * @param addrlen length of @a addr
2916  * @return #GNUNET_OK if this is a plausible address for this peer
2917  *         and transport, #GNUNET_SYSERR if not
2918  */
2919 static int
2920 tcp_plugin_check_address (void *cls,
2921                           const void *addr,
2922                           size_t addrlen)
2923 {
2924   struct Plugin *plugin = cls;
2925   const struct IPv4TcpAddress *v4;
2926   const struct IPv6TcpAddress *v6;
2927
2928   if ( (addrlen != sizeof(struct IPv4TcpAddress)) &&
2929        (addrlen != sizeof(struct IPv6TcpAddress)) )
2930   {
2931     GNUNET_break_op (0);
2932     return GNUNET_SYSERR;
2933   }
2934
2935   if (addrlen == sizeof(struct IPv4TcpAddress))
2936   {
2937     struct sockaddr_in s4;
2938
2939     v4 = (const struct IPv4TcpAddress *) addr;
2940     if (0 != memcmp (&v4->options,
2941                      &plugin->myoptions,
2942                      sizeof(uint32_t)))
2943     {
2944       GNUNET_break (0);
2945       return GNUNET_SYSERR;
2946     }
2947     memset (&s4, 0, sizeof (s4));
2948     s4.sin_family = AF_INET;
2949 #if HAVE_SOCKADDR_IN_SIN_LEN
2950     s4.sin_len = sizeof (s4);
2951 #endif
2952     s4.sin_port = v4->t4_port;
2953     s4.sin_addr.s_addr = v4->ipv4_addr;
2954
2955     if (GNUNET_OK !=
2956         GNUNET_NAT_test_address (plugin->nat,
2957                                  &s4,
2958                                  sizeof (struct sockaddr_in)))
2959       return GNUNET_SYSERR;
2960   }
2961   else
2962   {
2963     struct sockaddr_in6 s6;
2964
2965     v6 = (const struct IPv6TcpAddress *) addr;
2966     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2967     {
2968       GNUNET_break_op (0);
2969       return GNUNET_SYSERR;
2970     }
2971     if (0 != memcmp (&v6->options,
2972                      &plugin->myoptions,
2973                      sizeof (uint32_t)))
2974     {
2975       GNUNET_break (0);
2976       return GNUNET_SYSERR;
2977     }
2978     memset (&s6, 0, sizeof (s6));
2979     s6.sin6_family = AF_INET6;
2980 #if HAVE_SOCKADDR_IN_SIN_LEN
2981     s6.sin6_len = sizeof (s6);
2982 #endif
2983     s6.sin6_port = v6->t6_port;
2984     s6.sin6_addr = v6->ipv6_addr;
2985
2986     if (GNUNET_OK !=
2987         GNUNET_NAT_test_address (plugin->nat,
2988                                  &s6,
2989                                  sizeof(struct sockaddr_in6)))
2990       return GNUNET_SYSERR;
2991   }
2992   return GNUNET_OK;
2993 }
2994
2995
2996 /**
2997  * We've received a nat probe from this peer via TCP.  Finish
2998  * creating the client session and resume sending of queued
2999  * messages.
3000  *
3001  * @param cls closure
3002  * @param client identification of the client
3003  * @param message the actual message
3004  */
3005 static void
3006 handle_tcp_nat_probe (void *cls,
3007                       struct GNUNET_SERVER_Client *client,
3008                       const struct GNUNET_MessageHeader *message)
3009 {
3010   struct Plugin *plugin = cls;
3011   struct GNUNET_ATS_Session *session;
3012   const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
3013   size_t alen;
3014   void *vaddr;
3015   struct IPv4TcpAddress *t4;
3016   struct IPv6TcpAddress *t6;
3017   const struct sockaddr_in *s4;
3018   const struct sockaddr_in6 *s6;
3019
3020   LOG (GNUNET_ERROR_TYPE_DEBUG,
3021        "Received NAT probe\n");
3022   /* We have received a TCP NAT probe, meaning we (hopefully) initiated
3023    * a connection to this peer by running gnunet-nat-client.  This peer
3024    * received the punch message and now wants us to use the new connection
3025    * as the default for that peer.  Do so and then send a WELCOME message
3026    * so we can really be connected!
3027    */
3028   if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage))
3029   {
3030     GNUNET_break_op(0);
3031     GNUNET_SERVER_receive_done (client,
3032                                 GNUNET_SYSERR);
3033     return;
3034   }
3035
3036   tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message;
3037   if (0 == memcmp (&tcp_nat_probe->clientIdentity, plugin->env->my_identity,
3038           sizeof(struct GNUNET_PeerIdentity)))
3039   {
3040     /* refuse connections from ourselves */
3041     GNUNET_SERVER_receive_done (client,
3042                                 GNUNET_SYSERR);
3043     return;
3044   }
3045
3046   session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns,
3047                                                &tcp_nat_probe->clientIdentity);
3048   if (NULL == session)
3049   {
3050     LOG (GNUNET_ERROR_TYPE_DEBUG,
3051          "Did NOT find session for NAT probe!\n");
3052     GNUNET_SERVER_receive_done (client,
3053                                 GNUNET_OK);
3054     return;
3055   }
3056   LOG (GNUNET_ERROR_TYPE_DEBUG,
3057        "Found session for NAT probe!\n");
3058
3059   if (NULL != session->nat_connection_timeout)
3060   {
3061     GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
3062     session->nat_connection_timeout = NULL;
3063   }
3064
3065   if (GNUNET_OK !=
3066       GNUNET_SERVER_client_get_address (client,
3067                                         &vaddr,
3068                                         &alen))
3069   {
3070     GNUNET_break(0);
3071     GNUNET_SERVER_receive_done (client,
3072                                 GNUNET_SYSERR);
3073     tcp_plugin_disconnect_session (plugin,
3074                                    session);
3075     return;
3076   }
3077   GNUNET_assert (GNUNET_YES ==
3078                  GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
3079                                                        &tcp_nat_probe->clientIdentity,
3080                                                        session));
3081   GNUNET_SERVER_client_set_user_context (client,
3082                                          session);
3083   (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
3084                                             &session->target,
3085                                             session,
3086                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3087   session->last_activity = GNUNET_TIME_absolute_get ();
3088   LOG (GNUNET_ERROR_TYPE_DEBUG,
3089        "Found address `%s' for incoming connection\n",
3090        GNUNET_a2s (vaddr, alen));
3091   switch (((const struct sockaddr *) vaddr)->sa_family)
3092   {
3093   case AF_INET:
3094     s4 = vaddr;
3095     t4 = GNUNET_new (struct IPv4TcpAddress);
3096     t4->options = htonl (TCP_OPTIONS_NONE);
3097     t4->t4_port = s4->sin_port;
3098     t4->ipv4_addr = s4->sin_addr.s_addr;
3099     session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3100                                                       PLUGIN_NAME,
3101                                                       &t4,
3102                                                       sizeof(struct IPv4TcpAddress),
3103                                                       GNUNET_HELLO_ADDRESS_INFO_NONE);
3104     break;
3105   case AF_INET6:
3106     s6 = vaddr;
3107     t6 = GNUNET_new (struct IPv6TcpAddress);
3108     t6->options = htonl (TCP_OPTIONS_NONE);
3109     t6->t6_port = s6->sin6_port;
3110     GNUNET_memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3111     session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3112                                                       PLUGIN_NAME,
3113                                                       &t6,
3114                                                       sizeof(struct IPv6TcpAddress),
3115                                                       GNUNET_HELLO_ADDRESS_INFO_NONE);
3116     break;
3117   default:
3118     GNUNET_break_op(0);
3119     LOG(GNUNET_ERROR_TYPE_DEBUG,
3120         "Bad address for incoming connection!\n");
3121     GNUNET_free(vaddr);
3122     GNUNET_SERVER_receive_done (client,
3123                                 GNUNET_SYSERR);
3124     tcp_plugin_disconnect_session (plugin,
3125                                    session);
3126     return;
3127   }
3128   GNUNET_free (vaddr);
3129   GNUNET_break (NULL == session->client);
3130   session->client = client;
3131   GNUNET_STATISTICS_update (plugin->env->stats,
3132                             gettext_noop ("# TCP sessions active"),
3133                             1,
3134                             GNUNET_NO);
3135   process_pending_messages (session);
3136   GNUNET_SERVER_receive_done (client,
3137                               GNUNET_OK);
3138 }
3139
3140
3141 /**
3142  * We've received a welcome from this peer via TCP.  Possibly create a
3143  * fresh client record and send back our welcome.
3144  *
3145  * @param cls closure
3146  * @param client identification of the client
3147  * @param message the actual message
3148  */
3149 static void
3150 handle_tcp_welcome (void *cls,
3151                     struct GNUNET_SERVER_Client *client,
3152                     const struct GNUNET_MessageHeader *message)
3153 {
3154   struct Plugin *plugin = cls;
3155   const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message;
3156   struct GNUNET_HELLO_Address *address;
3157   struct GNUNET_ATS_Session *session;
3158   size_t alen;
3159   void *vaddr;
3160   struct IPv4TcpAddress t4;
3161   struct IPv6TcpAddress t6;
3162   const struct sockaddr_in *s4;
3163   const struct sockaddr_in6 *s6;
3164
3165   if (0 == memcmp (&wm->clientIdentity,
3166                    plugin->env->my_identity,
3167                    sizeof(struct GNUNET_PeerIdentity)))
3168   {
3169     /* refuse connections from ourselves */
3170     if (GNUNET_OK ==
3171         GNUNET_SERVER_client_get_address (client,
3172                                           &vaddr,
3173                                           &alen))
3174     {
3175       LOG (GNUNET_ERROR_TYPE_INFO,
3176            "Received WELCOME message from my own identity `%s' on address `%s'\n",
3177            GNUNET_i2s (&wm->clientIdentity),
3178            GNUNET_a2s (vaddr, alen));
3179       GNUNET_free (vaddr);
3180     }
3181     GNUNET_SERVER_receive_done (client,
3182                                 GNUNET_SYSERR);
3183     return;
3184   }
3185
3186   if (GNUNET_OK ==
3187       GNUNET_SERVER_client_get_address (client,
3188                                         &vaddr,
3189                                         &alen))
3190   {
3191     LOG(GNUNET_ERROR_TYPE_DEBUG,
3192         "Received WELCOME message from `%s' on address `%s'\n",
3193         GNUNET_i2s (&wm->clientIdentity),
3194         GNUNET_a2s (vaddr, alen));
3195     GNUNET_free (vaddr);
3196   }
3197   GNUNET_STATISTICS_update (plugin->env->stats,
3198                             gettext_noop ("# TCP WELCOME messages received"),
3199                             1,
3200                             GNUNET_NO);
3201   session = lookup_session_by_client (plugin,
3202                                       client);
3203   if (NULL != session)
3204   {
3205     if (GNUNET_OK ==
3206         GNUNET_SERVER_client_get_address (client,
3207                                           &vaddr,
3208                                           &alen))
3209     {
3210       LOG (GNUNET_ERROR_TYPE_DEBUG,
3211            "Found existing session %p for peer `%s'\n",
3212            session,
3213            GNUNET_a2s (vaddr, alen));
3214       GNUNET_free (vaddr);
3215     }
3216   }
3217   else
3218   {
3219     if (GNUNET_OK ==
3220         GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3221     {
3222       if (alen == sizeof(struct sockaddr_in))
3223       {
3224         s4 = vaddr;
3225         memset (&t4, '\0', sizeof (t4));
3226         t4.options = htonl (TCP_OPTIONS_NONE);
3227         t4.t4_port = s4->sin_port;
3228         t4.ipv4_addr = s4->sin_addr.s_addr;
3229         address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
3230                                                  PLUGIN_NAME,
3231                                                  &t4,
3232                                                  sizeof(t4),
3233                                                  GNUNET_HELLO_ADDRESS_INFO_INBOUND);
3234       }
3235       else if (alen == sizeof(struct sockaddr_in6))
3236       {
3237         s6 = vaddr;
3238         memset (&t6, '\0', sizeof (t6));
3239         t6.options = htonl (TCP_OPTIONS_NONE);
3240         t6.t6_port = s6->sin6_port;
3241         GNUNET_memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3242         address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
3243                                                  PLUGIN_NAME,
3244                                                  &t6,
3245                                                  sizeof (t6),
3246                                                  GNUNET_HELLO_ADDRESS_INFO_INBOUND);
3247       }
3248       else
3249       {
3250         GNUNET_break (0);
3251         GNUNET_free_non_null (vaddr);
3252         GNUNET_SERVER_receive_done (client,
3253                                     GNUNET_SYSERR);
3254         return;
3255       }
3256       session = create_session (plugin,
3257                                 address,
3258                                 plugin->env->get_address_type (plugin->env->cls,
3259                                                                vaddr,
3260                                                                alen),
3261                                 client,
3262                                 GNUNET_NO);
3263       GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != session->scope);
3264       GNUNET_HELLO_address_free (address);
3265       LOG (GNUNET_ERROR_TYPE_DEBUG,
3266            "Creating new%s session %p for peer `%s' client %p\n",
3267            GNUNET_HELLO_address_check_option (session->address,
3268                                               GNUNET_HELLO_ADDRESS_INFO_INBOUND)
3269            ? " inbound" : "",
3270            session,
3271            tcp_plugin_address_to_string (plugin,
3272                                          session->address->address,
3273                                          session->address->address_length),
3274            client);
3275       GNUNET_free (vaddr);
3276       (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
3277                                                 &session->target,
3278                                                 session,
3279                                                 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3280       /* Notify transport and ATS about new session */
3281       plugin->env->session_start (plugin->env->cls,
3282                                   session->address,
3283                                   session,
3284                                   session->scope);
3285     }
3286     else
3287     {
3288       LOG(GNUNET_ERROR_TYPE_DEBUG,
3289           "Did not obtain TCP socket address for incoming connection\n");
3290       GNUNET_break(0);
3291       GNUNET_SERVER_receive_done (client,
3292                                   GNUNET_SYSERR);
3293       return;
3294     }
3295   }
3296
3297   if (GNUNET_YES != session->expecting_welcome)
3298   {
3299     GNUNET_break_op (0);
3300     GNUNET_SERVER_receive_done (client,
3301                                 GNUNET_SYSERR);
3302     return;
3303   }
3304   session->last_activity = GNUNET_TIME_absolute_get ();
3305   session->expecting_welcome = GNUNET_NO;
3306
3307   process_pending_messages (session);
3308   GNUNET_SERVER_client_set_timeout (client,
3309                                     GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
3310   GNUNET_SERVER_receive_done (client,
3311                               GNUNET_OK);
3312 }
3313
3314
3315 /**
3316  * We've received data for this peer via TCP.  Unbox,
3317  * compute latency and forward.
3318  *
3319  * @param cls closure
3320  * @param client identification of the client
3321  * @param message the actual message
3322  */
3323 static void
3324 handle_tcp_data (void *cls,
3325                  struct GNUNET_SERVER_Client *client,
3326                  const struct GNUNET_MessageHeader *message)
3327 {
3328   struct Plugin *plugin = cls;
3329   struct GNUNET_ATS_Session *session;
3330   struct GNUNET_TIME_Relative delay;
3331   uint16_t type;
3332
3333   type = ntohs (message->type);
3334   if ( (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == type) ||
3335        (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE == type) )
3336   {
3337     /* We don't want to propagate WELCOME and NAT Probe messages up! */
3338     GNUNET_SERVER_receive_done (client,
3339                                 GNUNET_OK);
3340     return;
3341   }
3342   session = lookup_session_by_client (plugin, client);
3343   if (NULL == session)
3344   {
3345     /* No inbound session found */
3346     void *vaddr = NULL;
3347     size_t alen;
3348
3349     GNUNET_assert (GNUNET_OK ==
3350                    GNUNET_SERVER_client_get_address (client,
3351                                                      &vaddr,
3352                                                      &alen));
3353     LOG (GNUNET_ERROR_TYPE_ERROR,
3354          "Received unexpected %u bytes of type %u from `%s'\n",
3355          (unsigned int) ntohs (message->size),
3356          (unsigned int) ntohs (message->type),
3357          GNUNET_a2s (vaddr,
3358                      alen));
3359     GNUNET_break_op(0);
3360     GNUNET_SERVER_receive_done (client,
3361                                 GNUNET_SYSERR);
3362     GNUNET_free_non_null (vaddr);
3363     return;
3364   }
3365   if (GNUNET_YES == session->expecting_welcome)
3366   {
3367     /* Session is expecting WELCOME message */
3368     void *vaddr = NULL;
3369     size_t alen;
3370
3371     GNUNET_SERVER_client_get_address (client,
3372                                       &vaddr,
3373                                       &alen);
3374     LOG (GNUNET_ERROR_TYPE_ERROR,
3375          "Received unexpected %u bytes of type %u from `%s'\n",
3376          (unsigned int) ntohs (message->size),
3377          (unsigned int) ntohs (message->type),
3378          GNUNET_a2s (vaddr, alen));
3379     GNUNET_break_op(0);
3380     GNUNET_SERVER_receive_done (client,
3381                                 GNUNET_SYSERR);
3382     GNUNET_free_non_null (vaddr);
3383     return;
3384   }
3385
3386   session->last_activity = GNUNET_TIME_absolute_get ();
3387   {
3388     void *vaddr = NULL;
3389     size_t alen;
3390
3391     GNUNET_SERVER_client_get_address (client,
3392                                       &vaddr,
3393                                       &alen);
3394     LOG (GNUNET_ERROR_TYPE_DEBUG,
3395          "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
3396          (unsigned int) ntohs (message->size),
3397          (unsigned int) ntohs (message->type),
3398          GNUNET_i2s (&session->target),
3399          GNUNET_a2s (vaddr, alen));
3400     GNUNET_free_non_null (vaddr);
3401   }
3402
3403   GNUNET_STATISTICS_update (plugin->env->stats,
3404                             gettext_noop ("# bytes received via TCP"),
3405                             ntohs (message->size),
3406                             GNUNET_NO);
3407
3408   GNUNET_assert (GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
3409                                                                &session->target,
3410                                                                session));
3411   delay = plugin->env->receive (plugin->env->cls,
3412                                 session->address,
3413                                 session,
3414                                 message);
3415   reschedule_session_timeout (session);
3416   if (0 == delay.rel_value_us)
3417   {
3418     GNUNET_SERVER_receive_done (client,
3419                                 GNUNET_OK);
3420   }
3421   else
3422   {
3423     LOG (GNUNET_ERROR_TYPE_DEBUG,
3424          "Throttling receiving from `%s' for %s\n",
3425          GNUNET_i2s (&session->target),
3426          GNUNET_STRINGS_relative_time_to_string (delay,
3427                                                  GNUNET_YES));
3428     GNUNET_SERVER_disable_receive_done_warning (client);
3429     GNUNET_assert (NULL == session->receive_delay_task);
3430     session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
3431                                                                 &delayed_done,
3432                                                                 session);
3433   }
3434 }
3435
3436
3437 /**
3438  * Function called whenever a peer is connected on the "SERVER" level.
3439  * Increments number of active connections and suspends server if we
3440  * have reached the limit.
3441  *
3442  * @param cls closure
3443  * @param client identification of the client
3444  */
3445 static void
3446 connect_notify (void *cls,
3447                 struct GNUNET_SERVER_Client *client)
3448 {
3449   struct Plugin *plugin = cls;
3450
3451   if (NULL == client)
3452     return;
3453   plugin->cur_connections++;
3454   GNUNET_STATISTICS_set (plugin->env->stats,
3455                          gettext_noop ("# TCP server connections active"),
3456                          plugin->cur_connections,
3457                          GNUNET_NO);
3458   GNUNET_STATISTICS_update (plugin->env->stats,
3459                             gettext_noop ("# TCP server connect events"),
3460                             1,
3461                             GNUNET_NO);
3462   if (plugin->cur_connections != plugin->max_connections)
3463     return;
3464   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3465               _("TCP connection limit reached, suspending server\n"));
3466   GNUNET_STATISTICS_update (plugin->env->stats,
3467                             gettext_noop ("# TCP service suspended"),
3468                             1,
3469                             GNUNET_NO);
3470   GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
3471 }
3472
3473
3474 /**
3475  * Function called whenever a peer is disconnected on the "SERVER"
3476  * level.  Cleans up the connection, decrements number of active
3477  * connections and if applicable resumes listening.
3478  *
3479  * @param cls closure
3480  * @param client identification of the client
3481  */
3482 static void
3483 disconnect_notify (void *cls,
3484                    struct GNUNET_SERVER_Client *client)
3485 {
3486   struct Plugin *plugin = cls;
3487   struct GNUNET_ATS_Session *session;
3488
3489   if (NULL == client)
3490     return;
3491   GNUNET_assert (plugin->cur_connections >= 1);
3492   plugin->cur_connections--;
3493   session = lookup_session_by_client (plugin,
3494                                       client);
3495   if (NULL == session)
3496     return; /* unknown, nothing to do */
3497   LOG (GNUNET_ERROR_TYPE_DEBUG,
3498        "Destroying session of `%s' with %s due to network-level disconnect.\n",
3499        GNUNET_i2s (&session->target),
3500        tcp_plugin_address_to_string (session->plugin,
3501                                      session->address->address,
3502                                      session->address->address_length));
3503
3504   if (plugin->cur_connections == plugin->max_connections)
3505   {
3506     GNUNET_STATISTICS_update (session->plugin->env->stats,
3507                               gettext_noop ("# TCP service resumed"),
3508                               1,
3509                               GNUNET_NO);
3510     GNUNET_SERVER_resume (plugin->server); /* Resume server  */
3511   }
3512   GNUNET_STATISTICS_set (plugin->env->stats,
3513                          gettext_noop ("# TCP server connections active"),
3514                          plugin->cur_connections,
3515                          GNUNET_NO);
3516   GNUNET_STATISTICS_update (session->plugin->env->stats,
3517                             gettext_noop ("# network-level TCP disconnect events"),
3518                             1,
3519                             GNUNET_NO);
3520   tcp_plugin_disconnect_session (plugin,
3521                                  session);
3522 }
3523
3524
3525 /**
3526  * We can now send a probe message, copy into buffer to really send.
3527  *
3528  * @param cls closure, a `struct TCPProbeContext`
3529  * @param size max size to copy
3530  * @param buf buffer to copy message to
3531  * @return number of bytes copied into @a buf
3532  */
3533 static size_t
3534 notify_send_probe (void *cls,
3535                    size_t size,
3536                    void *buf)
3537 {
3538   struct TCPProbeContext *tcp_probe_ctx = cls;
3539   struct Plugin *plugin = tcp_probe_ctx->plugin;
3540   size_t ret;
3541
3542   tcp_probe_ctx->transmit_handle = NULL;
3543   GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
3544                                plugin->probe_tail,
3545                                tcp_probe_ctx);
3546   if (NULL == buf)
3547   {
3548     GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
3549     GNUNET_free(tcp_probe_ctx);
3550     return 0;
3551   }
3552   GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
3553   GNUNET_memcpy (buf,
3554           &tcp_probe_ctx->message,
3555           sizeof(tcp_probe_ctx->message));
3556   GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
3557                                 tcp_probe_ctx->sock);
3558   ret = sizeof(tcp_probe_ctx->message);
3559   GNUNET_free (tcp_probe_ctx);
3560   return ret;
3561 }
3562
3563
3564 /**
3565  * Function called by the NAT subsystem suggesting another peer wants
3566  * to connect to us via connection reversal.  Try to connect back to the
3567  * given IP.
3568  *
3569  * @param cls closure
3570  * @param addr address to try
3571  * @param addrlen number of bytes in @a addr
3572  */
3573 static void
3574 try_connection_reversal (void *cls,
3575                          const struct sockaddr *addr,
3576                          socklen_t addrlen)
3577 {
3578   struct Plugin *plugin = cls;
3579   struct GNUNET_CONNECTION_Handle *sock;
3580   struct TCPProbeContext *tcp_probe_ctx;
3581
3582   /**
3583    * We have received an ICMP response, ostensibly from a peer
3584    * that wants to connect to us! Send a message to establish a connection.
3585    */
3586   sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET,
3587                                                  addr,
3588                                                  addrlen);
3589   if (NULL == sock)
3590   {
3591     /* failed for some odd reason (out of sockets?); ignore attempt */
3592     return;
3593   }
3594
3595   tcp_probe_ctx = GNUNET_new (struct TCPProbeContext);
3596   tcp_probe_ctx->message.header.size
3597     = htons (sizeof (struct TCP_NAT_ProbeMessage));
3598   tcp_probe_ctx->message.header.type
3599     = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3600   tcp_probe_ctx->message.clientIdentity
3601     = *plugin->env->my_identity;
3602   tcp_probe_ctx->plugin = plugin;
3603   tcp_probe_ctx->sock = sock;
3604   GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
3605                                plugin->probe_tail,
3606                                tcp_probe_ctx);
3607   tcp_probe_ctx->transmit_handle
3608     = GNUNET_CONNECTION_notify_transmit_ready (sock,
3609                                                ntohs (tcp_probe_ctx->message.header.size),
3610                                                GNUNET_TIME_UNIT_FOREVER_REL,
3611                                                &notify_send_probe,
3612                                                tcp_probe_ctx);
3613 }
3614
3615
3616 /**
3617  * Function obtain the network type for a session
3618  *
3619  * @param cls closure (`struct Plugin *`)
3620  * @param session the session
3621  * @return the network type in HBO or #GNUNET_SYSERR
3622  */
3623 static enum GNUNET_ATS_Network_Type
3624 tcp_plugin_get_network (void *cls,
3625                         struct GNUNET_ATS_Session *session)
3626 {
3627   return session->scope;
3628 }
3629
3630
3631 /**
3632  * Function obtain the network type for an address.
3633  *
3634  * @param cls closure (`struct Plugin *`)
3635  * @param address the address
3636  * @return the network type
3637  */
3638 static enum GNUNET_ATS_Network_Type
3639 tcp_plugin_get_network_for_address (void *cls,
3640                                     const struct GNUNET_HELLO_Address *address)
3641 {
3642   struct Plugin *plugin = cls;
3643   size_t addrlen;
3644   struct sockaddr_in a4;
3645   struct sockaddr_in6 a6;
3646   const struct IPv4TcpAddress *t4;
3647   const struct IPv6TcpAddress *t6;
3648   const void *sb;
3649   size_t sbs;
3650
3651   addrlen = address->address_length;
3652   if (addrlen == sizeof(struct IPv6TcpAddress))
3653   {
3654     GNUNET_assert (NULL != address->address); /* make static analysis happy */
3655     t6 = address->address;
3656     memset (&a6, 0, sizeof(a6));
3657 #if HAVE_SOCKADDR_IN_SIN_LEN
3658     a6.sin6_len = sizeof (a6);
3659 #endif
3660     a6.sin6_family = AF_INET6;
3661     a6.sin6_port = t6->t6_port;
3662     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
3663     sb = &a6;
3664     sbs = sizeof(a6);
3665   }
3666   else if (addrlen == sizeof(struct IPv4TcpAddress))
3667   {
3668     GNUNET_assert (NULL != address->address); /* make static analysis happy */
3669     t4 = address->address;
3670     memset (&a4, 0, sizeof(a4));
3671 #if HAVE_SOCKADDR_IN_SIN_LEN
3672     a4.sin_len = sizeof (a4);
3673 #endif
3674     a4.sin_family = AF_INET;
3675     a4.sin_port = t4->t4_port;
3676     a4.sin_addr.s_addr = t4->ipv4_addr;
3677     sb = &a4;
3678     sbs = sizeof(a4);
3679   }
3680   else
3681   {
3682     GNUNET_break (0);
3683     return GNUNET_ATS_NET_UNSPECIFIED;
3684   }
3685   return plugin->env->get_address_type (plugin->env->cls,
3686                                         sb,
3687                                         sbs);
3688 }
3689
3690
3691 /**
3692  * Return information about the given session to the
3693  * monitor callback.
3694  *
3695  * @param cls the `struct Plugin` with the monitor callback (`sic`)
3696  * @param peer peer we send information about
3697  * @param value our `struct GNUNET_ATS_Session` to send information about
3698  * @return #GNUNET_OK (continue to iterate)
3699  */
3700 static int
3701 send_session_info_iter (void *cls,
3702                         const struct GNUNET_PeerIdentity *peer,
3703                         void *value)
3704 {
3705   struct Plugin *plugin = cls;
3706   struct GNUNET_ATS_Session *session = value;
3707
3708   notify_session_monitor (plugin,
3709                           session,
3710                           GNUNET_TRANSPORT_SS_INIT);
3711   /* FIXME: cannot tell if this is up or not from current
3712      session state... */
3713   notify_session_monitor (plugin,
3714                           session,
3715                           GNUNET_TRANSPORT_SS_UP);
3716   return GNUNET_OK;
3717 }
3718
3719
3720 /**
3721  * Begin monitoring sessions of a plugin.  There can only
3722  * be one active monitor per plugin (i.e. if there are
3723  * multiple monitors, the transport service needs to
3724  * multiplex the generated events over all of them).
3725  *
3726  * @param cls closure of the plugin
3727  * @param sic callback to invoke, NULL to disable monitor;
3728  *            plugin will being by iterating over all active
3729  *            sessions immediately and then enter monitor mode
3730  * @param sic_cls closure for @a sic
3731  */
3732 static void
3733 tcp_plugin_setup_monitor (void *cls,
3734                           GNUNET_TRANSPORT_SessionInfoCallback sic,
3735                           void *sic_cls)
3736 {
3737   struct Plugin *plugin = cls;
3738
3739   plugin->sic = sic;
3740   plugin->sic_cls = sic_cls;
3741   if (NULL != sic)
3742   {
3743     GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
3744                                            &send_session_info_iter,
3745                                            plugin);
3746     /* signal end of first iteration */
3747     sic (sic_cls, NULL, NULL);
3748   }
3749 }
3750
3751
3752 /**
3753  * Entry point for the plugin.
3754  *
3755  * @param cls closure, the `struct GNUNET_TRANSPORT_PluginEnvironment *`
3756  * @return the `struct GNUNET_TRANSPORT_PluginFunctions *` or NULL on error
3757  */
3758 void *
3759 libgnunet_plugin_transport_tcp_init (void *cls)
3760 {
3761   static const struct GNUNET_SERVER_MessageHandler my_handlers[] = {
3762     { &handle_tcp_welcome, NULL,
3763       GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME,
3764       sizeof(struct WelcomeMessage) },
3765     { &handle_tcp_nat_probe, NULL,
3766       GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE,
3767       sizeof(struct TCP_NAT_ProbeMessage) },
3768     { &handle_tcp_data, NULL,
3769       GNUNET_MESSAGE_TYPE_ALL, 0 },
3770     { NULL, NULL, 0, 0 }
3771   };
3772   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3773   struct GNUNET_TRANSPORT_PluginFunctions *api;
3774   struct Plugin *plugin;
3775   struct LEGACY_SERVICE_Context *service;
3776   unsigned long long aport;
3777   unsigned long long bport;
3778   unsigned long long max_connections;
3779   unsigned int i;
3780   struct GNUNET_TIME_Relative idle_timeout;
3781 #ifdef TCP_STEALTH
3782   struct GNUNET_NETWORK_Handle *const*lsocks;
3783 #endif
3784   int ret;
3785   int ret_s;
3786   struct sockaddr **addrs;
3787   socklen_t *addrlens;
3788
3789   if (NULL == env->receive)
3790   {
3791     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3792      initialze the plugin or the API */
3793     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
3794     api->cls = NULL;
3795     api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
3796     api->address_to_string = &tcp_plugin_address_to_string;
3797     api->string_to_address = &tcp_plugin_string_to_address;
3798     return api;
3799   }
3800
3801   GNUNET_assert (NULL != env->cfg);
3802   if (GNUNET_OK !=
3803       GNUNET_CONFIGURATION_get_value_number (env->cfg,
3804                                              "transport-tcp",
3805                                              "MAX_CONNECTIONS",
3806                                              &max_connections))
3807     max_connections = 128;
3808
3809   aport = 0;
3810   if ((GNUNET_OK !=
3811        GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
3812                                               "PORT", &bport)) ||
3813       (bport > 65535) ||
3814       ((GNUNET_OK ==
3815         GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
3816                                                "ADVERTISED-PORT", &aport)) &&
3817        (aport > 65535) ))
3818   {
3819     LOG(GNUNET_ERROR_TYPE_ERROR,
3820         _("Require valid port number for service `%s' in configuration!\n"),
3821         "transport-tcp");
3822     return NULL ;
3823   }
3824   if (0 == aport)
3825     aport = bport;
3826   if (0 == bport)
3827     aport = 0;
3828   if (0 != bport)
3829   {
3830     service = LEGACY_SERVICE_start ("transport-tcp",
3831                                     env->cfg,
3832                                     LEGACY_SERVICE_OPTION_NONE);
3833     if (NULL == service)
3834     {
3835       LOG (GNUNET_ERROR_TYPE_WARNING,
3836            _("Failed to start service.\n"));
3837       return NULL;
3838     }
3839   }
3840   else
3841     service = NULL;
3842
3843   api = NULL;
3844   plugin = GNUNET_new (struct Plugin);
3845   plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections,
3846                                                              GNUNET_YES);
3847   plugin->max_connections = max_connections;
3848   plugin->open_port = bport;
3849   plugin->adv_port = aport;
3850   plugin->env = env;
3851   plugin->my_welcome.header.size = htons (sizeof(struct WelcomeMessage));
3852   plugin->my_welcome.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME);
3853   plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
3854
3855   if ( (NULL != service) &&
3856        (GNUNET_YES ==
3857         GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3858                                               "transport-tcp",
3859                                               "TCP_STEALTH")) )
3860   {
3861 #ifdef TCP_STEALTH
3862     plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
3863     lsocks = LEGACY_SERVICE_get_listen_sockets (service);
3864     if (NULL != lsocks)
3865     {
3866       uint32_t len = sizeof (struct WelcomeMessage);
3867
3868       for (i=0;NULL!=lsocks[i];i++)
3869       {
3870         if ( (GNUNET_OK !=
3871               GNUNET_NETWORK_socket_setsockopt (lsocks[i],
3872                                                 IPPROTO_TCP,
3873                                                 TCP_STEALTH,
3874                                                 env->my_identity,
3875                                                 sizeof (struct GNUNET_PeerIdentity))) ||
3876              (GNUNET_OK !=
3877               GNUNET_NETWORK_socket_setsockopt (lsocks[i],
3878                                                 IPPROTO_TCP,
3879                                                 TCP_STEALTH_INTEGRITY_LEN,
3880                                                 &len,
3881                                                 sizeof (len))) )
3882         {
3883           /* TCP STEALTH not supported by kernel */
3884           GNUNET_assert (0 == i);
3885           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3886                       _("TCP_STEALTH not supported on this platform.\n"));
3887           goto die;
3888         }
3889       }
3890     }
3891 #else
3892     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3893                 _("TCP_STEALTH not supported on this platform.\n"));
3894     goto die;
3895 #endif
3896   }
3897
3898   if ( (NULL != service) &&
3899        (GNUNET_SYSERR !=
3900         (ret_s =
3901          get_server_addresses ("transport-tcp",
3902                                env->cfg,
3903                                &addrs,
3904                                &addrlens))))
3905   {
3906     for (ret = ret_s-1; ret >= 0; ret--)
3907       LOG (GNUNET_ERROR_TYPE_INFO,
3908            "Binding to address `%s'\n",
3909            GNUNET_a2s (addrs[ret], addrlens[ret]));
3910     plugin->nat
3911       = GNUNET_NAT_register (env->cfg,
3912                              "transport-tcp",
3913                              IPPROTO_TCP,
3914                              (unsigned int) ret_s,
3915                              (const struct sockaddr **) addrs,
3916                              addrlens,
3917                              &tcp_nat_port_map_callback,
3918                              &try_connection_reversal,
3919                              plugin);
3920     for (ret = ret_s -1; ret >= 0; ret--)
3921       GNUNET_free (addrs[ret]);
3922     GNUNET_free_non_null (addrs);
3923     GNUNET_free_non_null (addrlens);
3924   }
3925   else
3926   {
3927     plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3928                                        "transport-tcp",
3929                                        IPPROTO_TCP,
3930                                        0,
3931                                        NULL,
3932                                        NULL,
3933                                        NULL,
3934                                        &try_connection_reversal,
3935                                        plugin);
3936   }
3937   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
3938   api->cls = plugin;
3939   api->send = &tcp_plugin_send;
3940   api->get_session = &tcp_plugin_get_session;
3941   api->disconnect_session = &tcp_plugin_disconnect_session;
3942   api->query_keepalive_factor = &tcp_plugin_query_keepalive_factor;
3943   api->disconnect_peer = &tcp_plugin_disconnect;
3944   api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
3945   api->check_address = &tcp_plugin_check_address;
3946   api->address_to_string = &tcp_plugin_address_to_string;
3947   api->string_to_address = &tcp_plugin_string_to_address;
3948   api->get_network = &tcp_plugin_get_network;
3949   api->get_network_for_address = &tcp_plugin_get_network_for_address;
3950   api->update_session_timeout = &tcp_plugin_update_session_timeout;
3951   api->update_inbound_delay = &tcp_plugin_update_inbound_delay;
3952   api->setup_monitor = &tcp_plugin_setup_monitor;
3953   plugin->service = service;
3954   if (NULL != service)
3955   {
3956     plugin->server = LEGACY_SERVICE_get_server (service);
3957   }
3958   else
3959   {
3960     if (GNUNET_OK !=
3961         GNUNET_CONFIGURATION_get_value_time (env->cfg,
3962                                              "transport-tcp",
3963                                              "TIMEOUT",
3964                                              &idle_timeout))
3965     {
3966       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3967                                  "transport-tcp",
3968                                  "TIMEOUT");
3969       goto die;
3970     }
3971     plugin->server
3972       = GNUNET_SERVER_create_with_sockets (NULL,
3973                                            plugin,
3974                                            NULL,
3975                                            idle_timeout,
3976                                            GNUNET_YES);
3977   }
3978   plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
3979   GNUNET_memcpy (plugin->handlers,
3980                  my_handlers,
3981                  sizeof(my_handlers));
3982   for (i = 0;i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);i++)
3983     plugin->handlers[i].callback_cls = plugin;
3984
3985   GNUNET_SERVER_add_handlers (plugin->server,
3986                               plugin->handlers);
3987   GNUNET_SERVER_connect_notify (plugin->server,
3988                                 &connect_notify,
3989                                 plugin);
3990   GNUNET_SERVER_disconnect_notify (plugin->server,
3991                                    &disconnect_notify,
3992                                    plugin);
3993   plugin->nat_wait_conns = GNUNET_CONTAINER_multipeermap_create (16,
3994                                                                  GNUNET_YES);
3995   if (0 != bport)
3996     LOG (GNUNET_ERROR_TYPE_INFO,
3997          _("TCP transport listening on port %llu\n"),
3998          bport);
3999   else
4000     LOG (GNUNET_ERROR_TYPE_INFO,
4001          _("TCP transport not listening on any port (client only)\n"));
4002   if ( (aport != bport) &&
4003        (0 != bport) )
4004     LOG (GNUNET_ERROR_TYPE_INFO,
4005          _("TCP transport advertises itself as being on port %llu\n"),
4006          aport);
4007   /* Initially set connections to 0 */
4008   GNUNET_STATISTICS_set (plugin->env->stats,
4009                          gettext_noop ("# TCP sessions active"),
4010                          0,
4011                          GNUNET_NO);
4012   return api;
4013
4014  die:
4015   if (NULL != plugin->nat)
4016     GNUNET_NAT_unregister (plugin->nat);
4017   GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
4018   if (NULL != service)
4019     LEGACY_SERVICE_stop (service);
4020   GNUNET_free (plugin);
4021   GNUNET_free_non_null (api);
4022   return NULL;
4023 }
4024
4025
4026 /**
4027  * Exit point from the plugin.
4028  *
4029  * @param cls the `struct GNUNET_TRANSPORT_PluginFunctions`
4030  * @return NULL
4031  */
4032 void *
4033 libgnunet_plugin_transport_tcp_done (void *cls)
4034 {
4035   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
4036   struct Plugin *plugin = api->cls;
4037   struct TCPProbeContext *tcp_probe;
4038   struct PrettyPrinterContext *cur;
4039   struct PrettyPrinterContext *next;
4040
4041   if (NULL == plugin)
4042   {
4043     GNUNET_free(api);
4044     return NULL ;
4045   }
4046   LOG (GNUNET_ERROR_TYPE_DEBUG,
4047        "Shutting down TCP plugin\n");
4048
4049   /* Removing leftover sessions */
4050   GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
4051                                          &session_disconnect_it,
4052                                          plugin);
4053   /* Removing leftover NAT sessions */
4054   GNUNET_CONTAINER_multipeermap_iterate (plugin->nat_wait_conns,
4055                                          &session_disconnect_it,
4056                                          plugin);
4057
4058   for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
4059   {
4060     next = cur->next;
4061     GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
4062                                  plugin->ppc_dll_tail,
4063                                  cur);
4064     GNUNET_RESOLVER_request_cancel (cur->resolver_handle);
4065     cur->asc (cur->asc_cls,
4066               NULL,
4067               GNUNET_OK);
4068     GNUNET_free (cur);
4069   }
4070
4071   if (NULL != plugin->service)
4072     LEGACY_SERVICE_stop (plugin->service);
4073   else
4074     GNUNET_SERVER_destroy (plugin->server);
4075   GNUNET_free (plugin->handlers);
4076   if (NULL != plugin->nat)
4077     GNUNET_NAT_unregister (plugin->nat);
4078   while (NULL != (tcp_probe = plugin->probe_head))
4079   {
4080     GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
4081                                  plugin->probe_tail,
4082                                  tcp_probe);
4083     GNUNET_CONNECTION_destroy (tcp_probe->sock);
4084     GNUNET_free (tcp_probe);
4085   }
4086   GNUNET_CONTAINER_multipeermap_destroy (plugin->nat_wait_conns);
4087   GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
4088   GNUNET_break (0 == plugin->cur_connections);
4089   GNUNET_free (plugin);
4090   GNUNET_free (api);
4091   return NULL;
4092 }
4093
4094 /* end of plugin_transport_tcp.c */