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