rename fest: use new libgnunetnt instead of old libgnunetats logic for network type...
[oweals/gnunet.git] / src / transport / plugin_transport_xt.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_xt.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-xt",__VA_ARGS__)
37
38 #define PLUGIN_NAME "xt"
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_NetworkType 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   if (GNUNET_NAT_AC_LOOPBACK == ac)
1452     return;
1453   if (GNUNET_NAT_AC_LAN == ac)
1454     return;
1455   if (GNUNET_NAT_AC_LAN_PRIVATE == ac)
1456     return;
1457   LOG (GNUNET_ERROR_TYPE_INFO,
1458        "NAT notification to %s address `%s'\n",
1459        (GNUNET_YES == add_remove) ? "add" : "remove",
1460        GNUNET_a2s (addr, addrlen));
1461   /* convert 'addr' to our internal format */
1462   switch (addr->sa_family)
1463   {
1464   case AF_INET:
1465     GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
1466     memset (&t4, 0, sizeof(t4));
1467     t4.options = htonl (plugin->myoptions);
1468     t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1469     t4.t4_port = ((struct sockaddr_in *) addr)->sin_port;
1470     arg = &t4;
1471     args = sizeof (t4);
1472     break;
1473   case AF_INET6:
1474     GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
1475     memset (&t6, 0, sizeof(t6));
1476     GNUNET_memcpy (&t6.ipv6_addr,
1477                    &((struct sockaddr_in6 *) addr)->sin6_addr,
1478                    sizeof(struct in6_addr));
1479     t6.options = htonl (plugin->myoptions);
1480     t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1481     arg = &t6;
1482     args = sizeof (t6);
1483     break;
1484   default:
1485     GNUNET_break(0);
1486     return;
1487   }
1488   /* modify our published address list */
1489   GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
1490                  (args == sizeof (struct IPv6TcpAddress)));
1491   /* TODO: use 'ac' here in the future... */
1492   address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1493                                            PLUGIN_NAME,
1494                                            arg,
1495                                            args,
1496                                            GNUNET_HELLO_ADDRESS_INFO_NONE);
1497   plugin->env->notify_address (plugin->env->cls,
1498                                add_remove,
1499                                address);
1500   GNUNET_HELLO_address_free (address);
1501 }
1502
1503
1504 /**
1505  * Function called for a quick conversion of the binary address to
1506  * a numeric address.  Note that the caller must not free the
1507  * address and that the next call to this function is allowed
1508  * to override the address again.
1509  *
1510  * @param cls closure (`struct Plugin*`)
1511  * @param addr binary address
1512  * @param addrlen length of @a addr
1513  * @return string representing the same address
1514  */
1515 static const char *
1516 tcp_plugin_address_to_string (void *cls,
1517                               const void *addr,
1518                               size_t addrlen)
1519 {
1520   static char rbuf[INET6_ADDRSTRLEN + 12];
1521   char buf[INET6_ADDRSTRLEN];
1522   const void *sb;
1523   struct in_addr a4;
1524   struct in6_addr a6;
1525   const struct IPv4TcpAddress *t4;
1526   const struct IPv6TcpAddress *t6;
1527   int af;
1528   uint16_t port;
1529   uint32_t options;
1530
1531   switch (addrlen)
1532   {
1533   case sizeof(struct IPv6TcpAddress):
1534     t6 = addr;
1535     af = AF_INET6;
1536     port = ntohs (t6->t6_port);
1537     options = ntohl (t6->options);
1538     GNUNET_memcpy (&a6, &t6->ipv6_addr, sizeof(a6));
1539     sb = &a6;
1540     break;
1541   case sizeof(struct IPv4TcpAddress):
1542     t4 = addr;
1543     af = AF_INET;
1544     port = ntohs (t4->t4_port);
1545     options = ntohl (t4->options);
1546     GNUNET_memcpy (&a4, &t4->ipv4_addr, sizeof(a4));
1547     sb = &a4;
1548     break;
1549   default:
1550     LOG (GNUNET_ERROR_TYPE_WARNING,
1551          _("Unexpected address length: %u bytes\n"),
1552          (unsigned int) addrlen);
1553     return NULL ;
1554   }
1555   if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN))
1556   {
1557     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1558                          "inet_ntop");
1559     return NULL ;
1560   }
1561   GNUNET_snprintf (rbuf, sizeof(rbuf),
1562                    (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
1563                    PLUGIN_NAME,
1564                    options,
1565                    buf,
1566                    port);
1567   return rbuf;
1568 }
1569
1570
1571 /**
1572  * Function called to convert a string address to
1573  * a binary address.
1574  *
1575  * @param cls closure (`struct Plugin*`)
1576  * @param addr string address
1577  * @param addrlen length of the address
1578  * @param buf location to store the buffer
1579  * @param added location to store the number of bytes in the buffer.
1580  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
1581  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1582  */
1583 static int
1584 tcp_plugin_string_to_address (void *cls,
1585                               const char *addr,
1586                               uint16_t addrlen,
1587                               void **buf,
1588                               size_t *added)
1589 {
1590   struct sockaddr_storage socket_address;
1591   char *address;
1592   char *plugin;
1593   char *optionstr;
1594   uint32_t options;
1595
1596   /* Format tcp.options.address:port */
1597   address = NULL;
1598   plugin = NULL;
1599   optionstr = NULL;
1600   if ((NULL == addr) || (0 == addrlen))
1601   {
1602     GNUNET_break(0);
1603     return GNUNET_SYSERR;
1604   }
1605   if ('\0' != addr[addrlen - 1])
1606   {
1607     GNUNET_break(0);
1608     return GNUNET_SYSERR;
1609   }
1610   if (strlen (addr) != addrlen - 1)
1611   {
1612     GNUNET_break(0);
1613     return GNUNET_SYSERR;
1614   }
1615   plugin = GNUNET_strdup (addr);
1616   optionstr = strchr (plugin, '.');
1617   if (NULL == optionstr)
1618   {
1619     GNUNET_break(0);
1620     GNUNET_free(plugin);
1621     return GNUNET_SYSERR;
1622   }
1623   optionstr[0] = '\0';
1624   optionstr++;
1625   options = atol (optionstr);
1626   address = strchr (optionstr, '.');
1627   if (NULL == address)
1628   {
1629     GNUNET_break(0);
1630     GNUNET_free(plugin);
1631     return GNUNET_SYSERR;
1632   }
1633   address[0] = '\0';
1634   address++;
1635
1636   if (GNUNET_OK !=
1637       GNUNET_STRINGS_to_address_ip (address,
1638                                     strlen (address),
1639                                     &socket_address))
1640   {
1641     GNUNET_break(0);
1642     GNUNET_free(plugin);
1643     return GNUNET_SYSERR;
1644   }
1645
1646   GNUNET_free(plugin);
1647   switch (socket_address.ss_family)
1648   {
1649   case AF_INET:
1650   {
1651     struct IPv4TcpAddress *t4;
1652     struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
1653     t4 = GNUNET_new (struct IPv4TcpAddress);
1654     t4->options = htonl (options);
1655     t4->ipv4_addr = in4->sin_addr.s_addr;
1656     t4->t4_port = in4->sin_port;
1657     *buf = t4;
1658     *added = sizeof(struct IPv4TcpAddress);
1659     return GNUNET_OK;
1660   }
1661   case AF_INET6:
1662   {
1663     struct IPv6TcpAddress *t6;
1664     struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
1665     t6 = GNUNET_new (struct IPv6TcpAddress);
1666     t6->options = htonl (options);
1667     t6->ipv6_addr = in6->sin6_addr;
1668     t6->t6_port = in6->sin6_port;
1669     *buf = t6;
1670     *added = sizeof(struct IPv6TcpAddress);
1671     return GNUNET_OK;
1672   }
1673   default:
1674     return GNUNET_SYSERR;
1675   }
1676 }
1677
1678
1679 /**
1680  * Find the session handle for the given client.
1681  * Currently uses both the hashmap and the client
1682  * context, as the client context is new and the
1683  * logic still needs to be tested.
1684  *
1685  * @param plugin the plugin
1686  * @param client which client to find the session handle for
1687  * @return NULL if no matching session exists
1688  */
1689 static struct GNUNET_ATS_Session *
1690 lookup_session_by_client (struct Plugin *plugin,
1691                           struct GNUNET_SERVER_Client *client)
1692 {
1693   return GNUNET_SERVER_client_get_user_context (client,
1694                                                 struct GNUNET_ATS_Session);
1695 }
1696
1697
1698 /**
1699  * Functions with this signature are called whenever we need
1700  * to close a session due to a disconnect or failure to
1701  * establish a connection.
1702  *
1703  * @param cls the `struct Plugin`
1704  * @param session session to close down
1705  * @return #GNUNET_OK on success
1706  */
1707 static int
1708 tcp_plugin_disconnect_session (void *cls,
1709                                struct GNUNET_ATS_Session *session)
1710 {
1711   struct Plugin *plugin = cls;
1712   struct PendingMessage *pm;
1713
1714   LOG (GNUNET_ERROR_TYPE_DEBUG,
1715        "Disconnecting session of peer `%s' address `%s'\n",
1716        GNUNET_i2s (&session->target),
1717        tcp_plugin_address_to_string (session->plugin,
1718                                      session->address->address,
1719                                      session->address->address_length));
1720
1721   if (NULL != session->timeout_task)
1722   {
1723     GNUNET_SCHEDULER_cancel (session->timeout_task);
1724     session->timeout_task = NULL;
1725     session->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
1726   }
1727
1728   if (GNUNET_YES ==
1729       GNUNET_CONTAINER_multipeermap_remove (plugin->sessionmap,
1730                                             &session->target,
1731                                             session))
1732   {
1733     GNUNET_STATISTICS_update (session->plugin->env->stats,
1734                               gettext_noop ("# TCP sessions active"),
1735                               -1,
1736                               GNUNET_NO);
1737   }
1738   else
1739   {
1740     GNUNET_assert (GNUNET_YES ==
1741                    GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
1742                                                          &session->target,
1743                                                          session));
1744   }
1745   if (NULL != session->client)
1746     GNUNET_SERVER_client_set_user_context (session->client,
1747                                            NULL);
1748
1749   /* clean up state */
1750   if (NULL != session->transmit_handle)
1751   {
1752     GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle);
1753     session->transmit_handle = NULL;
1754   }
1755   session->plugin->env->session_end (session->plugin->env->cls,
1756                                      session->address,
1757                                      session);
1758
1759   if (NULL != session->nat_connection_timeout)
1760   {
1761     GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
1762     session->nat_connection_timeout = NULL;
1763   }
1764
1765   while (NULL != (pm = session->pending_messages_head))
1766   {
1767     LOG (GNUNET_ERROR_TYPE_DEBUG,
1768          (NULL != pm->transmit_cont)
1769          ? "Could not deliver message to `%s' at %s.\n"
1770          : "Could not deliver message to `%s' at %s, notifying.\n",
1771          GNUNET_i2s (&session->target),
1772          tcp_plugin_address_to_string (session->plugin,
1773                                        session->address->address,
1774                                        session->address->address_length));
1775     GNUNET_STATISTICS_update (session->plugin->env->stats,
1776                               gettext_noop ("# bytes currently in TCP buffers"),
1777                               -(int64_t) pm->message_size, GNUNET_NO);
1778     GNUNET_STATISTICS_update (session->plugin->env->stats,
1779                               gettext_noop ("# bytes discarded by TCP (disconnect)"),
1780                               pm->message_size,
1781                               GNUNET_NO);
1782     GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
1783                                  session->pending_messages_tail,
1784                                  pm);
1785     GNUNET_assert (0 < session->msgs_in_queue);
1786     session->msgs_in_queue--;
1787     GNUNET_assert (pm->message_size <= session->bytes_in_queue);
1788     session->bytes_in_queue -= pm->message_size;
1789     if (NULL != pm->transmit_cont)
1790       pm->transmit_cont (pm->transmit_cont_cls,
1791                          &session->target,
1792                          GNUNET_SYSERR,
1793                          pm->message_size,
1794                          0);
1795     GNUNET_free (pm);
1796   }
1797   GNUNET_assert (0 == session->msgs_in_queue);
1798   GNUNET_assert (0 == session->bytes_in_queue);
1799   notify_session_monitor (session->plugin,
1800                           session,
1801                           GNUNET_TRANSPORT_SS_DONE);
1802
1803   if (NULL != session->receive_delay_task)
1804   {
1805     GNUNET_SCHEDULER_cancel (session->receive_delay_task);
1806     session->receive_delay_task = NULL;
1807   }
1808   if (NULL != session->client)
1809   {
1810     GNUNET_SERVER_client_disconnect (session->client);
1811     session->client = NULL;
1812   }
1813   GNUNET_HELLO_address_free (session->address);
1814   GNUNET_assert (NULL == session->transmit_handle);
1815   GNUNET_free (session);
1816   return GNUNET_OK;
1817 }
1818
1819
1820 /**
1821  * Function that is called to get the keepalive factor.
1822  * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
1823  * calculate the interval between keepalive packets.
1824  *
1825  * @param cls closure with the `struct Plugin`
1826  * @return keepalive factor
1827  */
1828 static unsigned int
1829 tcp_plugin_query_keepalive_factor (void *cls)
1830 {
1831   return 3;
1832 }
1833
1834
1835 /**
1836  * Session was idle for too long, so disconnect it
1837  *
1838  * @param cls the `struct GNUNET_ATS_Session` of the idle session
1839  */
1840 static void
1841 session_timeout (void *cls)
1842 {
1843   struct GNUNET_ATS_Session *s = cls;
1844   struct GNUNET_TIME_Relative left;
1845
1846   s->timeout_task = NULL;
1847   left = GNUNET_TIME_absolute_get_remaining (s->timeout);
1848   if (0 != left.rel_value_us)
1849   {
1850     /* not actually our turn yet, but let's at least update
1851        the monitor, it may think we're about to die ... */
1852     notify_session_monitor (s->plugin,
1853                             s,
1854                             GNUNET_TRANSPORT_SS_UPDATE);
1855     s->timeout_task = GNUNET_SCHEDULER_add_delayed (left,
1856                                                     &session_timeout,
1857                                                     s);
1858     return;
1859   }
1860   LOG (GNUNET_ERROR_TYPE_DEBUG,
1861        "Session %p was idle for %s, disconnecting\n",
1862        s,
1863        GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1864                                                GNUNET_YES));
1865   /* call session destroy function */
1866   tcp_plugin_disconnect_session (s->plugin,
1867                                  s);
1868 }
1869
1870
1871 /**
1872  * Increment session timeout due to activity.
1873  *
1874  * @param s session to increment timeout for
1875  */
1876 static void
1877 reschedule_session_timeout (struct GNUNET_ATS_Session *s)
1878 {
1879   GNUNET_assert (NULL != s->timeout_task);
1880   s->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1881 }
1882
1883
1884 /**
1885  * Create a new session.  Also queues a welcome message.
1886  *
1887  * @param plugin the plugin
1888  * @param address the address to create the session for
1889  * @param scope network scope the address is from
1890  * @param client client to use, reference counter must have already been increased
1891  * @param is_nat this a NAT session, we should wait for a client to
1892  *               connect to us from an address, then assign that to
1893  *               the session
1894  * @return new session object
1895  */
1896 static struct GNUNET_ATS_Session *
1897 create_session (struct Plugin *plugin,
1898                 const struct GNUNET_HELLO_Address *address,
1899                 enum GNUNET_NetworkType scope,
1900                 struct GNUNET_SERVER_Client *client,
1901                 int is_nat)
1902 {
1903   struct GNUNET_ATS_Session *session;
1904   struct PendingMessage *pm;
1905
1906   if (GNUNET_YES != is_nat)
1907     GNUNET_assert (NULL != client);
1908   else
1909     GNUNET_assert (NULL == client);
1910
1911   LOG (GNUNET_ERROR_TYPE_DEBUG,
1912        "Creating new session for peer `%s' at address %s\n",
1913        GNUNET_i2s (&address->peer),
1914        tcp_plugin_address_to_string (plugin,
1915                                      address->address,
1916                                      address->address_length));
1917   session = GNUNET_new (struct GNUNET_ATS_Session);
1918   session->last_activity = GNUNET_TIME_absolute_get ();
1919   session->plugin = plugin;
1920   session->is_nat = is_nat;
1921   if (NULL != client)
1922   {
1923     session->client = client;
1924     GNUNET_SERVER_client_set_user_context (client,
1925                                            session);
1926   }
1927   session->address = GNUNET_HELLO_address_copy (address);
1928   session->target = address->peer;
1929   session->expecting_welcome = GNUNET_YES;
1930   session->scope = scope;
1931   pm = GNUNET_malloc (sizeof (struct PendingMessage) +
1932                       sizeof (struct WelcomeMessage));
1933   pm->msg = (const char *) &pm[1];
1934   pm->message_size = sizeof(struct WelcomeMessage);
1935   GNUNET_memcpy (&pm[1],
1936           &plugin->my_welcome,
1937           sizeof(struct WelcomeMessage));
1938   pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1939   GNUNET_STATISTICS_update (plugin->env->stats,
1940                             gettext_noop ("# bytes currently in TCP buffers"),
1941                             pm->message_size,
1942                             GNUNET_NO);
1943   GNUNET_CONTAINER_DLL_insert (session->pending_messages_head,
1944                                session->pending_messages_tail,
1945                                pm);
1946   session->msgs_in_queue++;
1947   session->bytes_in_queue += pm->message_size;
1948   session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1949   session->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1950                                                         &session_timeout,
1951                                                         session);
1952   notify_session_monitor (session->plugin,
1953                           session,
1954                           GNUNET_TRANSPORT_SS_INIT);
1955   if (GNUNET_YES != is_nat)
1956   {
1957     GNUNET_STATISTICS_update (plugin->env->stats,
1958                               gettext_noop ("# TCP sessions active"),
1959                               1,
1960                               GNUNET_NO);
1961     notify_session_monitor (session->plugin,
1962                             session,
1963                             GNUNET_TRANSPORT_SS_UP);
1964   }
1965   else
1966   {
1967     notify_session_monitor (session->plugin,
1968                             session,
1969                             GNUNET_TRANSPORT_SS_HANDSHAKE);
1970   }
1971   return session;
1972 }
1973
1974
1975 /**
1976  * If we have pending messages, ask the server to
1977  * transmit them (schedule the respective tasks, etc.)
1978  *
1979  * @param session for which session should we do this
1980  */
1981 static void
1982 process_pending_messages (struct GNUNET_ATS_Session *session);
1983
1984
1985 /**
1986  * Function called to notify a client about the socket
1987  * being ready to queue more data.  "buf" will be
1988  * NULL and "size" zero if the socket was closed for
1989  * writing in the meantime.
1990  *
1991  * @param cls closure
1992  * @param size number of bytes available in @a buf
1993  * @param buf where the callee should write the message
1994  * @return number of bytes written to @a buf
1995  */
1996 static size_t
1997 do_transmit (void *cls,
1998              size_t size,
1999              void *buf)
2000 {
2001   struct GNUNET_ATS_Session *session = cls;
2002   struct GNUNET_PeerIdentity pid;
2003   struct Plugin *plugin;
2004   struct PendingMessage *pos;
2005   struct PendingMessage *hd;
2006   struct PendingMessage *tl;
2007   struct GNUNET_TIME_Absolute now;
2008   char *cbuf;
2009   size_t ret;
2010
2011   session->transmit_handle = NULL;
2012   plugin = session->plugin;
2013   if (NULL == buf)
2014   {
2015     LOG (GNUNET_ERROR_TYPE_DEBUG,
2016          "Timeout trying to transmit to peer `%s', discarding message queue.\n",
2017          GNUNET_i2s (&session->target));
2018     /* timeout; cancel all messages that have already expired */
2019     hd = NULL;
2020     tl = NULL;
2021     ret = 0;
2022     now = GNUNET_TIME_absolute_get ();
2023     while ( (NULL != (pos = session->pending_messages_head)) &&
2024             (pos->timeout.abs_value_us <= now.abs_value_us) )
2025     {
2026       GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
2027                                    session->pending_messages_tail,
2028                                    pos);
2029       GNUNET_assert (0 < session->msgs_in_queue);
2030       session->msgs_in_queue--;
2031       GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2032       session->bytes_in_queue -= pos->message_size;
2033       LOG (GNUNET_ERROR_TYPE_DEBUG,
2034            "Failed to transmit %u byte message to `%s'.\n",
2035            pos->message_size,
2036            GNUNET_i2s (&session->target));
2037       ret += pos->message_size;
2038       GNUNET_CONTAINER_DLL_insert_after (hd,
2039                                          tl,
2040                                          tl,
2041                                          pos);
2042     }
2043     /* do this call before callbacks (so that if callbacks destroy
2044      * session, they have a chance to cancel actions done by this
2045      * call) */
2046     process_pending_messages (session);
2047     pid = session->target;
2048     /* no do callbacks and do not use session again since
2049      * the callbacks may abort the session */
2050     while (NULL != (pos = hd))
2051     {
2052       GNUNET_CONTAINER_DLL_remove (hd,
2053                                    tl,
2054                                    pos);
2055       if (NULL != pos->transmit_cont)
2056         pos->transmit_cont (pos->transmit_cont_cls,
2057                             &pid,
2058                             GNUNET_SYSERR,
2059                             pos->message_size,
2060                             0);
2061       GNUNET_free (pos);
2062     }
2063     GNUNET_STATISTICS_update (plugin->env->stats,
2064                               gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret,
2065                               GNUNET_NO);
2066     GNUNET_STATISTICS_update (plugin->env->stats,
2067                               gettext_noop ("# bytes discarded by TCP (timeout)"),
2068                               ret,
2069                               GNUNET_NO);
2070     if (0 < ret)
2071       notify_session_monitor (session->plugin,
2072                               session,
2073                               GNUNET_TRANSPORT_SS_UPDATE);
2074     return 0;
2075   }
2076   /* copy all pending messages that would fit */
2077   ret = 0;
2078   cbuf = buf;
2079   hd = NULL;
2080   tl = NULL;
2081   while (NULL != (pos = session->pending_messages_head))
2082   {
2083     if (ret + pos->message_size > size)
2084       break;
2085     GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
2086                                  session->pending_messages_tail,
2087                                  pos);
2088     GNUNET_assert (0 < session->msgs_in_queue);
2089     session->msgs_in_queue--;
2090     GNUNET_assert (pos->message_size <= session->bytes_in_queue);
2091     session->bytes_in_queue -= pos->message_size;
2092     GNUNET_assert(size >= pos->message_size);
2093     LOG (GNUNET_ERROR_TYPE_DEBUG,
2094          "Transmitting message of type %u size %u to peer %s at %s\n",
2095          ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type),
2096          pos->message_size,
2097          GNUNET_i2s (&session->target),
2098          tcp_plugin_address_to_string (session->plugin,
2099                                        session->address->address,
2100                                        session->address->address_length));
2101     /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
2102     GNUNET_memcpy (cbuf,
2103             pos->msg,
2104             pos->message_size);
2105     cbuf += pos->message_size;
2106     ret += pos->message_size;
2107     size -= pos->message_size;
2108     GNUNET_CONTAINER_DLL_insert_tail (hd,
2109                                       tl,
2110                                       pos);
2111   }
2112   notify_session_monitor (session->plugin,
2113                           session,
2114                           GNUNET_TRANSPORT_SS_UPDATE);
2115   /* schedule 'continuation' before callbacks so that callbacks that
2116    * cancel everything don't cause us to use a session that no longer
2117    * exists... */
2118   process_pending_messages (session);
2119   session->last_activity = GNUNET_TIME_absolute_get ();
2120   pid = session->target;
2121   /* we'll now call callbacks that may cancel the session; hence
2122    * we should not use 'session' after this point */
2123   while (NULL != (pos = hd))
2124   {
2125     GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
2126     if (NULL != pos->transmit_cont)
2127       pos->transmit_cont (pos->transmit_cont_cls,
2128                           &pid,
2129                           GNUNET_OK,
2130                           pos->message_size,
2131                           pos->message_size); /* FIXME: include TCP overhead */
2132     GNUNET_free (pos);
2133   }
2134   GNUNET_assert (NULL == hd);
2135   GNUNET_assert (NULL == tl);
2136   GNUNET_STATISTICS_update (plugin->env->stats,
2137                             gettext_noop ("# bytes currently in TCP buffers"),
2138                             - (int64_t) ret,
2139                             GNUNET_NO);
2140   GNUNET_STATISTICS_update (plugin->env->stats,
2141                             gettext_noop ("# bytes transmitted via TCP"),
2142                             ret,
2143                             GNUNET_NO);
2144   return ret;
2145 }
2146
2147
2148 /**
2149  * If we have pending messages, ask the server to
2150  * transmit them (schedule the respective tasks, etc.)
2151  *
2152  * @param session for which session should we do this
2153  */
2154 static void
2155 process_pending_messages (struct GNUNET_ATS_Session *session)
2156 {
2157   struct PendingMessage *pm;
2158
2159   GNUNET_assert (NULL != session->client);
2160   if (NULL != session->transmit_handle)
2161     return;
2162   if (NULL == (pm = session->pending_messages_head))
2163     return;
2164
2165   session->transmit_handle
2166     = GNUNET_SERVER_notify_transmit_ready (session->client,
2167                                            pm->message_size,
2168                                            GNUNET_TIME_absolute_get_remaining (pm->timeout),
2169                                            &do_transmit,
2170                                            session);
2171 }
2172
2173
2174 /**
2175  * Function that can be used by the transport service to transmit
2176  * a message using the plugin.   Note that in the case of a
2177  * peer disconnecting, the continuation MUST be called
2178  * prior to the disconnect notification itself.  This function
2179  * will be called with this peer's HELLO message to initiate
2180  * a fresh connection to another peer.
2181  *
2182  * @param cls closure
2183  * @param session which session must be used
2184  * @param msgbuf the message to transmit
2185  * @param msgbuf_size number of bytes in @a msgbuf
2186  * @param priority how important is the message (most plugins will
2187  *                 ignore message priority and just FIFO)
2188  * @param to how long to wait at most for the transmission (does not
2189  *                require plugins to discard the message after the timeout,
2190  *                just advisory for the desired delay; most plugins will ignore
2191  *                this as well)
2192  * @param cont continuation to call once the message has
2193  *        been transmitted (or if the transport is ready
2194  *        for the next transmission call; or if the
2195  *        peer disconnected...); can be NULL
2196  * @param cont_cls closure for @a cont
2197  * @return number of bytes used (on the physical network, with overheads);
2198  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
2199  *         and does NOT mean that the message was not transmitted (DV)
2200  */
2201 static ssize_t
2202 tcp_plugin_send (void *cls,
2203                  struct GNUNET_ATS_Session *session,
2204                  const char *msgbuf,
2205                  size_t msgbuf_size,
2206                  unsigned int priority,
2207                  struct GNUNET_TIME_Relative to,
2208                  GNUNET_TRANSPORT_TransmitContinuation cont,
2209                  void *cont_cls)
2210 {
2211   struct Plugin * plugin = cls;
2212   struct PendingMessage *pm;
2213
2214   /* create new message entry */
2215   pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
2216   pm->msg = (const char *) &pm[1];
2217   GNUNET_memcpy (&pm[1], msgbuf, msgbuf_size);
2218   pm->message_size = msgbuf_size;
2219   pm->timeout = GNUNET_TIME_relative_to_absolute (to);
2220   pm->transmit_cont = cont;
2221   pm->transmit_cont_cls = cont_cls;
2222
2223   LOG (GNUNET_ERROR_TYPE_DEBUG,
2224        "Asked to transmit %u bytes to `%s', added message to list.\n",
2225        msgbuf_size,
2226        GNUNET_i2s (&session->target));
2227
2228   if (GNUNET_YES ==
2229       GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
2230                                                     &session->target,
2231                                                     session))
2232   {
2233     GNUNET_assert (NULL != session->client);
2234     GNUNET_SERVER_client_set_timeout (session->client,
2235                                       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2236     GNUNET_STATISTICS_update (plugin->env->stats,
2237                               gettext_noop ("# bytes currently in TCP buffers"),
2238                               msgbuf_size,
2239                               GNUNET_NO);
2240
2241     /* append pm to pending_messages list */
2242     GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
2243                                       session->pending_messages_tail,
2244                                       pm);
2245     notify_session_monitor (session->plugin,
2246                             session,
2247                             GNUNET_TRANSPORT_SS_UPDATE);
2248     session->msgs_in_queue++;
2249     session->bytes_in_queue += pm->message_size;
2250     process_pending_messages (session);
2251     return msgbuf_size;
2252   }
2253   if (GNUNET_YES ==
2254       GNUNET_CONTAINER_multipeermap_contains_value (plugin->nat_wait_conns,
2255                                                     &session->target,
2256                                                     session))
2257   {
2258     LOG (GNUNET_ERROR_TYPE_DEBUG,
2259          "This NAT WAIT session for peer `%s' is not yet ready!\n",
2260          GNUNET_i2s (&session->target));
2261     GNUNET_STATISTICS_update (plugin->env->stats,
2262                               gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size,
2263                               GNUNET_NO);
2264     /* append pm to pending_messages list */
2265     GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
2266                                       session->pending_messages_tail,
2267                                       pm);
2268     session->msgs_in_queue++;
2269     session->bytes_in_queue += pm->message_size;
2270     notify_session_monitor (session->plugin,
2271                             session,
2272                             GNUNET_TRANSPORT_SS_HANDSHAKE);
2273     return msgbuf_size;
2274   }
2275   LOG (GNUNET_ERROR_TYPE_ERROR,
2276        "Invalid session %p\n",
2277        session);
2278   if (NULL != cont)
2279     cont (cont_cls,
2280           &session->target,
2281           GNUNET_SYSERR,
2282           pm->message_size,
2283           0);
2284   GNUNET_break (0);
2285   GNUNET_free (pm);
2286   return GNUNET_SYSERR; /* session does not exist here */
2287 }
2288
2289
2290 /**
2291  * Closure for #session_lookup_it().
2292  */
2293 struct GNUNET_ATS_SessionItCtx
2294 {
2295   /**
2296    * Address we are looking for.
2297    */
2298   const struct GNUNET_HELLO_Address *address;
2299
2300   /**
2301    * Where to store the session (if we found it).
2302    */
2303   struct GNUNET_ATS_Session *result;
2304
2305 };
2306
2307
2308 /**
2309  * Look for a session by address.
2310  *
2311  * @param cls the `struct GNUNET_ATS_SessionItCtx`
2312  * @param key unused
2313  * @param value a `struct GNUNET_ATS_Session`
2314  * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the session
2315  */
2316 static int
2317 session_lookup_it (void *cls,
2318                    const struct GNUNET_PeerIdentity *key,
2319                    void *value)
2320 {
2321   struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
2322   struct GNUNET_ATS_Session *session = value;
2323
2324   if (0 !=
2325       GNUNET_HELLO_address_cmp (si_ctx->address,
2326                                 session->address))
2327     return GNUNET_YES;
2328   si_ctx->result = session;
2329   return GNUNET_NO;
2330 }
2331
2332
2333 /**
2334  * Task cleaning up a NAT connection attempt after timeout
2335  *
2336  * @param cls the `struct GNUNET_ATS_Session`
2337  */
2338 static void
2339 nat_connect_timeout (void *cls)
2340 {
2341   struct GNUNET_ATS_Session *session = cls;
2342
2343   session->nat_connection_timeout = NULL;
2344   LOG (GNUNET_ERROR_TYPE_DEBUG,
2345        "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
2346        GNUNET_i2s (&session->target),
2347        tcp_plugin_address_to_string (session->plugin,
2348                                      session->address->address,
2349                                      session->address->address_length));
2350   tcp_plugin_disconnect_session (session->plugin,
2351                                  session);
2352 }
2353
2354
2355 /**
2356  * Function that will be called whenever the transport service wants to
2357  * notify the plugin that a session is still active and in use and
2358  * therefore the session timeout for this session has to be updated
2359  *
2360  * @param cls closure
2361  * @param peer which peer was the session for
2362  * @param session which session is being updated
2363  */
2364 static void
2365 tcp_plugin_update_session_timeout (void *cls,
2366                                    const struct GNUNET_PeerIdentity *peer,
2367                                    struct GNUNET_ATS_Session *session)
2368 {
2369   reschedule_session_timeout (session);
2370 }
2371
2372
2373 /**
2374  * Task to signal the server that we can continue
2375  * receiving from the TCP client now.
2376  *
2377  * @param cls the `struct GNUNET_ATS_Session *`
2378  */
2379 static void
2380 delayed_done (void *cls)
2381 {
2382   struct GNUNET_ATS_Session *session = cls;
2383
2384   session->receive_delay_task = NULL;
2385   reschedule_session_timeout (session);
2386   GNUNET_SERVER_receive_done (session->client,
2387                               GNUNET_OK);
2388 }
2389
2390
2391 /**
2392  * Function that will be called whenever the transport service wants to
2393  * notify the plugin that the inbound quota changed and that the plugin
2394  * should update it's delay for the next receive value
2395  *
2396  * @param cls closure
2397  * @param peer which peer was the session for
2398  * @param session which session is being updated
2399  * @param delay new delay to use for receiving
2400  */
2401 static void
2402 tcp_plugin_update_inbound_delay (void *cls,
2403                                  const struct GNUNET_PeerIdentity *peer,
2404                                  struct GNUNET_ATS_Session *session,
2405                                  struct GNUNET_TIME_Relative delay)
2406 {
2407   if (NULL == session->receive_delay_task)
2408     return;
2409   LOG (GNUNET_ERROR_TYPE_DEBUG,
2410        "New inbound delay %s\n",
2411        GNUNET_STRINGS_relative_time_to_string (delay,
2412                                                GNUNET_NO));
2413   session->receive_delay = GNUNET_TIME_relative_to_absolute (delay);
2414   GNUNET_SCHEDULER_cancel (session->receive_delay_task);
2415   session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
2416                                                               &delayed_done,
2417                                                               session);
2418 }
2419
2420
2421 /**
2422  * Create a new session to transmit data to the target
2423  * This session will used to send data to this peer and the plugin will
2424  * notify us by calling the env->session_end function
2425  *
2426  * @param cls closure
2427  * @param address the address to use
2428  * @return the session if the address is valid, NULL otherwise
2429  */
2430 static struct GNUNET_ATS_Session *
2431 tcp_plugin_get_session (void *cls,
2432                         const struct GNUNET_HELLO_Address *address)
2433 {
2434   struct Plugin *plugin = cls;
2435   struct GNUNET_ATS_Session *session = NULL;
2436   int af;
2437   const void *sb;
2438   size_t sbs;
2439   struct GNUNET_CONNECTION_Handle *sa;
2440   struct sockaddr_in a4;
2441   struct sockaddr_in6 a6;
2442   const struct IPv4TcpAddress *t4;
2443   const struct IPv6TcpAddress *t6;
2444   unsigned int options;
2445   enum GNUNET_NetworkType net_type;
2446   unsigned int is_natd = GNUNET_NO;
2447   size_t addrlen;
2448 #ifdef TCP_STEALTH
2449   struct GNUNET_NETWORK_Handle *s;
2450 #endif
2451
2452   addrlen = address->address_length;
2453   LOG (GNUNET_ERROR_TYPE_DEBUG,
2454        "Trying to get session for `%s' address of peer `%s'\n",
2455        tcp_plugin_address_to_string (plugin,
2456                                      address->address,
2457                                      address->address_length),
2458        GNUNET_i2s (&address->peer));
2459
2460   if (GNUNET_HELLO_address_check_option (address,
2461                                          GNUNET_HELLO_ADDRESS_INFO_INBOUND))
2462   {
2463     GNUNET_break (0);
2464     return NULL;
2465   }
2466
2467   /* look for existing session */
2468   if (GNUNET_YES ==
2469       GNUNET_CONTAINER_multipeermap_contains (plugin->sessionmap,
2470                                               &address->peer))
2471   {
2472     struct GNUNET_ATS_SessionItCtx si_ctx;
2473
2474     si_ctx.address = address;
2475     si_ctx.result = NULL;
2476     GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
2477                                                 &address->peer,
2478                                                 &session_lookup_it,
2479                                                 &si_ctx);
2480     if (NULL != si_ctx.result)
2481     {
2482       session = si_ctx.result;
2483       LOG (GNUNET_ERROR_TYPE_DEBUG,
2484            "Found existing session for `%s' address `%s'\n",
2485            GNUNET_i2s (&address->peer),
2486            tcp_plugin_address_to_string (plugin,
2487                                          address->address,
2488                                          address->address_length));
2489       return session;
2490     }
2491     /* This is a bit of a hack, limiting TCP to never allow more than
2492        one TCP connection to any given peer at the same time.
2493        Without this, peers sometimes disagree about which of the TCP
2494        connections they should use, causing one side to believe that
2495        they transmit successfully, while the other receives nothing. */
2496     return NULL; /* Refuse to have more than one TCP connection per
2497                     peer pair at the same time. */
2498   }
2499
2500   if (addrlen == sizeof(struct IPv6TcpAddress))
2501   {
2502     GNUNET_assert (NULL != address->address); /* make static analysis happy */
2503     t6 = address->address;
2504     options = t6->options;
2505     af = AF_INET6;
2506     memset (&a6, 0, sizeof(a6));
2507 #if HAVE_SOCKADDR_IN_SIN_LEN
2508     a6.sin6_len = sizeof (a6);
2509 #endif
2510     a6.sin6_family = AF_INET6;
2511     a6.sin6_port = t6->t6_port;
2512     if (t6->t6_port == 0)
2513       is_natd = GNUNET_YES;
2514     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2515     sb = &a6;
2516     sbs = sizeof(a6);
2517   }
2518   else if (addrlen == sizeof(struct IPv4TcpAddress))
2519   {
2520     GNUNET_assert(NULL != address->address); /* make static analysis happy */
2521     t4 = address->address;
2522     options = t4->options;
2523     af = AF_INET;
2524     memset (&a4, 0, sizeof(a4));
2525 #if HAVE_SOCKADDR_IN_SIN_LEN
2526     a4.sin_len = sizeof (a4);
2527 #endif
2528     a4.sin_family = AF_INET;
2529     a4.sin_port = t4->t4_port;
2530     if (t4->t4_port == 0)
2531       is_natd = GNUNET_YES;
2532     a4.sin_addr.s_addr = t4->ipv4_addr;
2533     sb = &a4;
2534     sbs = sizeof(a4);
2535   }
2536   else
2537   {
2538     GNUNET_STATISTICS_update (plugin->env->stats,
2539                               gettext_noop ("# requests to create session with invalid address"),
2540                               1,
2541                               GNUNET_NO);
2542     return NULL;
2543   }
2544
2545   net_type = plugin->env->get_address_type (plugin->env->cls,
2546                                             sb,
2547                                             sbs);
2548   GNUNET_break (net_type != GNUNET_NT_UNSPECIFIED);
2549
2550   if ( (is_natd == GNUNET_YES) &&
2551        (addrlen == sizeof(struct IPv6TcpAddress)) )
2552   {
2553     /* NAT client only works with IPv4 addresses */
2554     return NULL;
2555   }
2556
2557   if (plugin->cur_connections >= plugin->max_connections)
2558   {
2559     /* saturated */
2560     return NULL;
2561   }
2562
2563   if ( (is_natd == GNUNET_YES) &&
2564        (GNUNET_YES ==
2565         GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
2566                                                 &address->peer)))
2567   {
2568     /* Only do one NAT punch attempt per peer identity */
2569     return NULL;
2570   }
2571
2572   if ( (is_natd == GNUNET_YES) &&
2573        (NULL != plugin->nat) &&
2574        (GNUNET_NO ==
2575         GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
2576                                                 &address->peer)))
2577   {
2578     struct sockaddr_in local_sa;
2579
2580     LOG (GNUNET_ERROR_TYPE_DEBUG,
2581          "Found valid IPv4 NAT address (creating session)!\n");
2582     session = create_session (plugin,
2583                               address,
2584                               net_type,
2585                               NULL,
2586                               GNUNET_YES);
2587     session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT,
2588                                                                     &nat_connect_timeout,
2589                                                                     session);
2590     GNUNET_assert (GNUNET_OK ==
2591                    GNUNET_CONTAINER_multipeermap_put (plugin->nat_wait_conns,
2592                                                       &session->target,
2593                                                       session,
2594                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2595
2596     LOG (GNUNET_ERROR_TYPE_DEBUG,
2597          "Created NAT WAIT connection to `%s' at `%s'\n",
2598          GNUNET_i2s (&session->target),
2599          GNUNET_a2s (sb, sbs));
2600     memset (&local_sa,
2601             0,
2602             sizeof (local_sa));
2603     local_sa.sin_family = AF_INET;
2604     local_sa.sin_port = htons (plugin->open_port);
2605     /* We leave sin_address at 0, let the kernel figure it out,
2606        even if our bind() is more specific.  (May want to reconsider
2607        later.) */
2608     if (GNUNET_OK ==
2609         GNUNET_NAT_request_reversal (plugin->nat,
2610                                      &local_sa,
2611                                      &a4))
2612       return session;
2613     LOG (GNUNET_ERROR_TYPE_DEBUG,
2614          "Running NAT client for `%s' at `%s' failed\n",
2615          GNUNET_i2s (&session->target),
2616          GNUNET_a2s (sb, sbs));
2617     tcp_plugin_disconnect_session (plugin,
2618                                    session);
2619     return NULL;
2620   }
2621
2622   /* create new outbound session */
2623   if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
2624   {
2625 #ifdef TCP_STEALTH
2626     s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
2627     if (NULL == s)
2628     {
2629       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
2630                            "socket");
2631       sa = NULL;
2632     }
2633     else
2634     {
2635       if ( (GNUNET_OK !=
2636             GNUNET_NETWORK_socket_setsockopt (s,
2637                                               IPPROTO_TCP,
2638                                               TCP_STEALTH,
2639                                               &session->target,
2640                                               sizeof (struct GNUNET_PeerIdentity))) ||
2641            (GNUNET_OK !=
2642             GNUNET_NETWORK_socket_setsockopt (s,
2643                                               IPPROTO_TCP,
2644                                               TCP_STEALTH_INTEGRITY,
2645                                               &plugin->my_welcome,
2646                                               sizeof (struct WelcomeMessage))) )
2647       {
2648         /* TCP STEALTH not supported by kernel */
2649         GNUNET_break (GNUNET_OK ==
2650                       GNUNET_NETWORK_socket_close (s));
2651         sa = NULL;
2652       }
2653       else
2654       {
2655         sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
2656       }
2657     }
2658 #else
2659     sa = NULL;
2660 #endif
2661   }
2662   else
2663   {
2664     sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
2665   }
2666   if (NULL == sa)
2667   {
2668     LOG (GNUNET_ERROR_TYPE_DEBUG,
2669          "Failed to create connection to `%s' at `%s'\n",
2670          GNUNET_i2s (&address->peer),
2671          GNUNET_a2s (sb, sbs));
2672     return NULL;
2673   }
2674   LOG (GNUNET_ERROR_TYPE_DEBUG,
2675        "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
2676        GNUNET_i2s (&address->peer),
2677        GNUNET_a2s (sb, sbs));
2678
2679   session = create_session (plugin,
2680                             address,
2681                             net_type,
2682                             GNUNET_SERVER_connect_socket (plugin->server,
2683                                                           sa),
2684                             GNUNET_NO);
2685   (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
2686                                             &session->target,
2687                                             session,
2688                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2689   /* Send TCP Welcome */
2690   process_pending_messages (session);
2691
2692   return session;
2693 }
2694
2695
2696 /**
2697  * We have been asked to destroy all connections to a particular peer.
2698  * This function is called on each applicable session and must tear it
2699  * down.
2700  *
2701  * @param cls the `struct Plugin *`
2702  * @param key the peer which the session belongs to (unused)
2703  * @param value the `struct GNUNET_ATS_Session`
2704  * @return #GNUNET_YES (continue to iterate)
2705  */
2706 static int
2707 session_disconnect_it (void *cls,
2708                        const struct GNUNET_PeerIdentity *key,
2709                        void *value)
2710 {
2711   struct Plugin *plugin = cls;
2712   struct GNUNET_ATS_Session *session = value;
2713
2714   GNUNET_STATISTICS_update (session->plugin->env->stats,
2715                             gettext_noop ("# transport-service disconnect requests for TCP"),
2716                             1,
2717                             GNUNET_NO);
2718   tcp_plugin_disconnect_session (plugin,
2719                                  session);
2720   return GNUNET_YES;
2721 }
2722
2723
2724 /**
2725  * Function that can be called to force a disconnect from the
2726  * specified neighbour.  This should also cancel all previously
2727  * scheduled transmissions.  Obviously the transmission may have been
2728  * partially completed already, which is OK.  The plugin is supposed
2729  * to close the connection (if applicable) and no longer call the
2730  * transmit continuation(s).
2731  *
2732  * Finally, plugin MUST NOT call the services's receive function to
2733  * notify the service that the connection to the specified target was
2734  * closed after a getting this call.
2735  *
2736  * @param cls closure
2737  * @param target peer for which the last transmission is
2738  *        to be cancelled
2739  */
2740 static void
2741 tcp_plugin_disconnect (void *cls,
2742                        const struct GNUNET_PeerIdentity *target)
2743 {
2744   struct Plugin *plugin = cls;
2745
2746   LOG (GNUNET_ERROR_TYPE_DEBUG,
2747        "Disconnecting peer `%s'\n",
2748        GNUNET_i2s (target));
2749   GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
2750                                               target,
2751                                               &session_disconnect_it,
2752                                               plugin);
2753   GNUNET_CONTAINER_multipeermap_get_multiple (plugin->nat_wait_conns,
2754                                               target,
2755                                               &session_disconnect_it,
2756                                               plugin);
2757 }
2758
2759
2760 /**
2761  * We are processing an address pretty printing request and finished
2762  * the IP resolution (if applicable).  Append our port and forward the
2763  * result.  If called with @a hostname NULL, we are done and should
2764  * clean up the pretty printer (otherwise, there might be multiple
2765  * hostnames for the IP address and we might receive more).
2766  *
2767  * @param cls the `struct PrettyPrinterContext *`
2768  * @param hostname hostname part of the address
2769  */
2770 static void
2771 append_port (void *cls,
2772              const char *hostname)
2773 {
2774   struct PrettyPrinterContext *ppc = cls;
2775   struct Plugin *plugin = ppc->plugin;
2776   char *ret;
2777
2778   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2779               "append_port called with hostname `%s'\n",
2780               hostname);
2781   if (NULL == hostname)
2782   {
2783     /* Final call, done */
2784     ppc->resolver_handle = NULL;
2785     GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
2786                                  plugin->ppc_dll_tail,
2787                                  ppc);
2788     ppc->asc (ppc->asc_cls,
2789               NULL,
2790               GNUNET_OK);
2791     GNUNET_free (ppc);
2792     return;
2793   }
2794   if (GNUNET_YES == ppc->ipv6)
2795     GNUNET_asprintf (&ret,
2796                      "%s.%u.[%s]:%d",
2797                      PLUGIN_NAME,
2798                      ppc->options,
2799                      hostname,
2800                      ppc->port);
2801   else
2802     GNUNET_asprintf (&ret,
2803                      "%s.%u.%s:%d",
2804                      PLUGIN_NAME,
2805                      ppc->options,
2806                      hostname,
2807                      ppc->port);
2808   ppc->asc (ppc->asc_cls,
2809             ret,
2810             GNUNET_OK);
2811   GNUNET_free (ret);
2812 }
2813
2814
2815 /**
2816  * Convert the transports address to a nice, human-readable format.
2817  *
2818  * @param cls closure with the `struct Plugin`
2819  * @param type name of the transport that generated the address
2820  * @param addr one of the addresses of the host, NULL for the last address
2821  *        the specific address format depends on the transport
2822  * @param addrlen length of the @a addr
2823  * @param numeric should (IP) addresses be displayed in numeric form?
2824  * @param timeout after how long should we give up?
2825  * @param asc function to call on each string
2826  * @param asc_cls closure for @a asc
2827  */
2828 static void
2829 tcp_plugin_address_pretty_printer (void *cls,
2830                                    const char *type,
2831                                    const void *addr,
2832                                    size_t addrlen,
2833                                    int numeric,
2834                                    struct GNUNET_TIME_Relative timeout,
2835                                    GNUNET_TRANSPORT_AddressStringCallback asc,
2836                                    void *asc_cls)
2837 {
2838   struct Plugin *plugin = cls;
2839   struct PrettyPrinterContext *ppc;
2840   const void *sb;
2841   size_t sbs;
2842   struct sockaddr_in a4;
2843   struct sockaddr_in6 a6;
2844   const struct IPv4TcpAddress *t4;
2845   const struct IPv6TcpAddress *t6;
2846   uint16_t port;
2847   uint32_t options;
2848
2849   if (sizeof(struct IPv6TcpAddress) == addrlen)
2850   {
2851     t6 = addr;
2852     memset (&a6, 0, sizeof(a6));
2853     a6.sin6_family = AF_INET6;
2854     a6.sin6_port = t6->t6_port;
2855     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
2856     port = ntohs (t6->t6_port);
2857     options = ntohl (t6->options);
2858     sb = &a6;
2859     sbs = sizeof(a6);
2860   }
2861   else if (sizeof(struct IPv4TcpAddress) == addrlen)
2862   {
2863     t4 = addr;
2864     memset (&a4, 0, sizeof(a4));
2865     a4.sin_family = AF_INET;
2866     a4.sin_port = t4->t4_port;
2867     a4.sin_addr.s_addr = t4->ipv4_addr;
2868     port = ntohs (t4->t4_port);
2869     options = ntohl (t4->options);
2870     sb = &a4;
2871     sbs = sizeof(a4);
2872   }
2873   else
2874   {
2875     /* invalid address */
2876     LOG (GNUNET_ERROR_TYPE_WARNING,
2877          _("Unexpected address length: %u bytes\n"),
2878          (unsigned int) addrlen);
2879     asc (asc_cls, NULL, GNUNET_SYSERR);
2880     asc (asc_cls, NULL, GNUNET_OK);
2881     return;
2882   }
2883   ppc = GNUNET_new (struct PrettyPrinterContext);
2884   ppc->plugin = plugin;
2885   if (addrlen == sizeof(struct IPv6TcpAddress))
2886     ppc->ipv6 = GNUNET_YES;
2887   else
2888     ppc->ipv6 = GNUNET_NO;
2889   ppc->asc = asc;
2890   ppc->asc_cls = asc_cls;
2891   ppc->port = port;
2892   ppc->options = options;
2893   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2894               "Starting DNS reverse lookup\n");
2895   ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb,
2896                                                        sbs,
2897                                                        ! numeric,
2898                                                        timeout,
2899                                                        &append_port,
2900                                                        ppc);
2901   if (NULL == ppc->resolver_handle)
2902   {
2903     GNUNET_break (0);
2904     GNUNET_free (ppc);
2905     return;
2906   }
2907   GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head,
2908                                plugin->ppc_dll_tail,
2909                                ppc);
2910 }
2911
2912
2913 /**
2914  * Function that will be called to check if a binary address for this
2915  * plugin is well-formed and corresponds to an address for THIS peer
2916  * (as per our configuration).  Naturally, if absolutely necessary,
2917  * plugins can be a bit conservative in their answer, but in general
2918  * plugins should make sure that the address does not redirect
2919  * traffic to a 3rd party that might try to man-in-the-middle our
2920  * traffic.
2921  *
2922  * @param cls closure, our `struct Plugin *`
2923  * @param addr pointer to the address
2924  * @param addrlen length of @a addr
2925  * @return #GNUNET_OK if this is a plausible address for this peer
2926  *         and transport, #GNUNET_SYSERR if not
2927  */
2928 static int
2929 tcp_plugin_check_address (void *cls,
2930                           const void *addr,
2931                           size_t addrlen)
2932 {
2933   struct Plugin *plugin = cls;
2934   const struct IPv4TcpAddress *v4;
2935   const struct IPv6TcpAddress *v6;
2936
2937   if ( (addrlen != sizeof(struct IPv4TcpAddress)) &&
2938        (addrlen != sizeof(struct IPv6TcpAddress)) )
2939   {
2940     GNUNET_break_op (0);
2941     return GNUNET_SYSERR;
2942   }
2943
2944   if (addrlen == sizeof(struct IPv4TcpAddress))
2945   {
2946     struct sockaddr_in s4;
2947
2948     v4 = (const struct IPv4TcpAddress *) addr;
2949     if (0 != memcmp (&v4->options,
2950                      &plugin->myoptions,
2951                      sizeof(uint32_t)))
2952     {
2953       GNUNET_break (0);
2954       return GNUNET_SYSERR;
2955     }
2956     memset (&s4, 0, sizeof (s4));
2957     s4.sin_family = AF_INET;
2958 #if HAVE_SOCKADDR_IN_SIN_LEN
2959     s4.sin_len = sizeof (s4);
2960 #endif
2961     s4.sin_port = v4->t4_port;
2962     s4.sin_addr.s_addr = v4->ipv4_addr;
2963
2964     if (GNUNET_OK !=
2965         GNUNET_NAT_test_address (plugin->nat,
2966                                  &s4,
2967                                  sizeof (struct sockaddr_in)))
2968       return GNUNET_SYSERR;
2969   }
2970   else
2971   {
2972     struct sockaddr_in6 s6;
2973
2974     v6 = (const struct IPv6TcpAddress *) addr;
2975     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
2976     {
2977       GNUNET_break_op (0);
2978       return GNUNET_SYSERR;
2979     }
2980     if (0 != memcmp (&v6->options,
2981                      &plugin->myoptions,
2982                      sizeof (uint32_t)))
2983     {
2984       GNUNET_break (0);
2985       return GNUNET_SYSERR;
2986     }
2987     memset (&s6, 0, sizeof (s6));
2988     s6.sin6_family = AF_INET6;
2989 #if HAVE_SOCKADDR_IN_SIN_LEN
2990     s6.sin6_len = sizeof (s6);
2991 #endif
2992     s6.sin6_port = v6->t6_port;
2993     s6.sin6_addr = v6->ipv6_addr;
2994
2995     if (GNUNET_OK !=
2996         GNUNET_NAT_test_address (plugin->nat,
2997                                  &s6,
2998                                  sizeof(struct sockaddr_in6)))
2999       return GNUNET_SYSERR;
3000   }
3001   return GNUNET_OK;
3002 }
3003
3004
3005 /**
3006  * We've received a nat probe from this peer via TCP.  Finish
3007  * creating the client session and resume sending of queued
3008  * messages.
3009  *
3010  * @param cls closure
3011  * @param client identification of the client
3012  * @param message the actual message
3013  */
3014 static void
3015 handle_tcp_nat_probe (void *cls,
3016                       struct GNUNET_SERVER_Client *client,
3017                       const struct GNUNET_MessageHeader *message)
3018 {
3019   struct Plugin *plugin = cls;
3020   struct GNUNET_ATS_Session *session;
3021   const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
3022   size_t alen;
3023   void *vaddr;
3024   struct IPv4TcpAddress *t4;
3025   struct IPv6TcpAddress *t6;
3026   const struct sockaddr_in *s4;
3027   const struct sockaddr_in6 *s6;
3028
3029   LOG (GNUNET_ERROR_TYPE_DEBUG,
3030        "Received NAT probe\n");
3031   /* We have received a TCP NAT probe, meaning we (hopefully) initiated
3032    * a connection to this peer by running gnunet-nat-client.  This peer
3033    * received the punch message and now wants us to use the new connection
3034    * as the default for that peer.  Do so and then send a WELCOME message
3035    * so we can really be connected!
3036    */
3037   if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage))
3038   {
3039     GNUNET_break_op(0);
3040     GNUNET_SERVER_receive_done (client,
3041                                 GNUNET_SYSERR);
3042     return;
3043   }
3044
3045   tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message;
3046   if (0 == memcmp (&tcp_nat_probe->clientIdentity, plugin->env->my_identity,
3047           sizeof(struct GNUNET_PeerIdentity)))
3048   {
3049     /* refuse connections from ourselves */
3050     GNUNET_SERVER_receive_done (client,
3051                                 GNUNET_SYSERR);
3052     return;
3053   }
3054
3055   session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns,
3056                                                &tcp_nat_probe->clientIdentity);
3057   if (NULL == session)
3058   {
3059     LOG (GNUNET_ERROR_TYPE_DEBUG,
3060          "Did NOT find session for NAT probe!\n");
3061     GNUNET_SERVER_receive_done (client,
3062                                 GNUNET_OK);
3063     return;
3064   }
3065   LOG (GNUNET_ERROR_TYPE_DEBUG,
3066        "Found session for NAT probe!\n");
3067
3068   if (NULL != session->nat_connection_timeout)
3069   {
3070     GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
3071     session->nat_connection_timeout = NULL;
3072   }
3073
3074   if (GNUNET_OK !=
3075       GNUNET_SERVER_client_get_address (client,
3076                                         &vaddr,
3077                                         &alen))
3078   {
3079     GNUNET_break(0);
3080     GNUNET_SERVER_receive_done (client,
3081                                 GNUNET_SYSERR);
3082     tcp_plugin_disconnect_session (plugin,
3083                                    session);
3084     return;
3085   }
3086   GNUNET_assert (GNUNET_YES ==
3087                  GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
3088                                                        &tcp_nat_probe->clientIdentity,
3089                                                        session));
3090   GNUNET_SERVER_client_set_user_context (client,
3091                                          session);
3092   (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
3093                                             &session->target,
3094                                             session,
3095                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3096   session->last_activity = GNUNET_TIME_absolute_get ();
3097   LOG (GNUNET_ERROR_TYPE_DEBUG,
3098        "Found address `%s' for incoming connection\n",
3099        GNUNET_a2s (vaddr, alen));
3100   switch (((const struct sockaddr *) vaddr)->sa_family)
3101   {
3102   case AF_INET:
3103     s4 = vaddr;
3104     t4 = GNUNET_new (struct IPv4TcpAddress);
3105     t4->options = htonl (TCP_OPTIONS_NONE);
3106     t4->t4_port = s4->sin_port;
3107     t4->ipv4_addr = s4->sin_addr.s_addr;
3108     session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3109                                                       PLUGIN_NAME,
3110                                                       &t4,
3111                                                       sizeof(struct IPv4TcpAddress),
3112                                                       GNUNET_HELLO_ADDRESS_INFO_NONE);
3113     break;
3114   case AF_INET6:
3115     s6 = vaddr;
3116     t6 = GNUNET_new (struct IPv6TcpAddress);
3117     t6->options = htonl (TCP_OPTIONS_NONE);
3118     t6->t6_port = s6->sin6_port;
3119     GNUNET_memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3120     session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
3121                                                       PLUGIN_NAME,
3122                                                       &t6,
3123                                                       sizeof(struct IPv6TcpAddress),
3124                                                       GNUNET_HELLO_ADDRESS_INFO_NONE);
3125     break;
3126   default:
3127     GNUNET_break_op(0);
3128     LOG(GNUNET_ERROR_TYPE_DEBUG,
3129         "Bad address for incoming connection!\n");
3130     GNUNET_free(vaddr);
3131     GNUNET_SERVER_receive_done (client,
3132                                 GNUNET_SYSERR);
3133     tcp_plugin_disconnect_session (plugin,
3134                                    session);
3135     return;
3136   }
3137   GNUNET_free (vaddr);
3138   GNUNET_break (NULL == session->client);
3139   session->client = client;
3140   GNUNET_STATISTICS_update (plugin->env->stats,
3141                             gettext_noop ("# TCP sessions active"),
3142                             1,
3143                             GNUNET_NO);
3144   process_pending_messages (session);
3145   GNUNET_SERVER_receive_done (client,
3146                               GNUNET_OK);
3147 }
3148
3149
3150 /**
3151  * We've received a welcome from this peer via TCP.  Possibly create a
3152  * fresh client record and send back our welcome.
3153  *
3154  * @param cls closure
3155  * @param client identification of the client
3156  * @param message the actual message
3157  */
3158 static void
3159 handle_tcp_welcome (void *cls,
3160                     struct GNUNET_SERVER_Client *client,
3161                     const struct GNUNET_MessageHeader *message)
3162 {
3163   struct Plugin *plugin = cls;
3164   const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message;
3165   struct GNUNET_HELLO_Address *address;
3166   struct GNUNET_ATS_Session *session;
3167   size_t alen;
3168   void *vaddr;
3169   struct IPv4TcpAddress t4;
3170   struct IPv6TcpAddress t6;
3171   const struct sockaddr_in *s4;
3172   const struct sockaddr_in6 *s6;
3173
3174   if (0 == memcmp (&wm->clientIdentity,
3175                    plugin->env->my_identity,
3176                    sizeof(struct GNUNET_PeerIdentity)))
3177   {
3178     /* refuse connections from ourselves */
3179     if (GNUNET_OK ==
3180         GNUNET_SERVER_client_get_address (client,
3181                                           &vaddr,
3182                                           &alen))
3183     {
3184       LOG (GNUNET_ERROR_TYPE_INFO,
3185            "Received WELCOME message from my own identity `%s' on address `%s'\n",
3186            GNUNET_i2s (&wm->clientIdentity),
3187            GNUNET_a2s (vaddr, alen));
3188       GNUNET_free (vaddr);
3189     }
3190     GNUNET_SERVER_receive_done (client,
3191                                 GNUNET_SYSERR);
3192     return;
3193   }
3194
3195   if (GNUNET_OK ==
3196       GNUNET_SERVER_client_get_address (client,
3197                                         &vaddr,
3198                                         &alen))
3199   {
3200     LOG(GNUNET_ERROR_TYPE_DEBUG,
3201         "Received WELCOME message from `%s' on address `%s'\n",
3202         GNUNET_i2s (&wm->clientIdentity),
3203         GNUNET_a2s (vaddr, alen));
3204     GNUNET_free (vaddr);
3205   }
3206   GNUNET_STATISTICS_update (plugin->env->stats,
3207                             gettext_noop ("# TCP WELCOME messages received"),
3208                             1,
3209                             GNUNET_NO);
3210   session = lookup_session_by_client (plugin,
3211                                       client);
3212   if (NULL != session)
3213   {
3214     if (GNUNET_OK ==
3215         GNUNET_SERVER_client_get_address (client,
3216                                           &vaddr,
3217                                           &alen))
3218     {
3219       LOG (GNUNET_ERROR_TYPE_DEBUG,
3220            "Found existing session %p for peer `%s'\n",
3221            session,
3222            GNUNET_a2s (vaddr, alen));
3223       GNUNET_free (vaddr);
3224     }
3225   }
3226   else
3227   {
3228     if (GNUNET_OK ==
3229         GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
3230     {
3231       if (alen == sizeof(struct sockaddr_in))
3232       {
3233         s4 = vaddr;
3234         memset (&t4, '\0', sizeof (t4));
3235         t4.options = htonl (TCP_OPTIONS_NONE);
3236         t4.t4_port = s4->sin_port;
3237         t4.ipv4_addr = s4->sin_addr.s_addr;
3238         address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
3239                                                  PLUGIN_NAME,
3240                                                  &t4,
3241                                                  sizeof(t4),
3242                                                  GNUNET_HELLO_ADDRESS_INFO_INBOUND);
3243       }
3244       else if (alen == sizeof(struct sockaddr_in6))
3245       {
3246         s6 = vaddr;
3247         memset (&t6, '\0', sizeof (t6));
3248         t6.options = htonl (TCP_OPTIONS_NONE);
3249         t6.t6_port = s6->sin6_port;
3250         GNUNET_memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
3251         address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
3252                                                  PLUGIN_NAME,
3253                                                  &t6,
3254                                                  sizeof (t6),
3255                                                  GNUNET_HELLO_ADDRESS_INFO_INBOUND);
3256       }
3257       else
3258       {
3259         GNUNET_break (0);
3260         GNUNET_free_non_null (vaddr);
3261         GNUNET_SERVER_receive_done (client,
3262                                     GNUNET_SYSERR);
3263         return;
3264       }
3265       session = create_session (plugin,
3266                                 address,
3267                                 plugin->env->get_address_type (plugin->env->cls,
3268                                                                vaddr,
3269                                                                alen),
3270                                 client,
3271                                 GNUNET_NO);
3272       GNUNET_break (GNUNET_NT_UNSPECIFIED != session->scope);
3273       GNUNET_HELLO_address_free (address);
3274       LOG (GNUNET_ERROR_TYPE_DEBUG,
3275            "Creating new%s session %p for peer `%s' client %p\n",
3276            GNUNET_HELLO_address_check_option (session->address,
3277                                               GNUNET_HELLO_ADDRESS_INFO_INBOUND)
3278            ? " inbound" : "",
3279            session,
3280            tcp_plugin_address_to_string (plugin,
3281                                          session->address->address,
3282                                          session->address->address_length),
3283            client);
3284       GNUNET_free (vaddr);
3285       (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
3286                                                 &session->target,
3287                                                 session,
3288                                                 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3289       /* Notify transport and ATS about new session */
3290       plugin->env->session_start (plugin->env->cls,
3291                                   session->address,
3292                                   session,
3293                                   session->scope);
3294     }
3295     else
3296     {
3297       LOG(GNUNET_ERROR_TYPE_DEBUG,
3298           "Did not obtain TCP socket address for incoming connection\n");
3299       GNUNET_break(0);
3300       GNUNET_SERVER_receive_done (client,
3301                                   GNUNET_SYSERR);
3302       return;
3303     }
3304   }
3305
3306   if (GNUNET_YES != session->expecting_welcome)
3307   {
3308     GNUNET_break_op (0);
3309     GNUNET_SERVER_receive_done (client,
3310                                 GNUNET_SYSERR);
3311     return;
3312   }
3313   session->last_activity = GNUNET_TIME_absolute_get ();
3314   session->expecting_welcome = GNUNET_NO;
3315
3316   process_pending_messages (session);
3317   GNUNET_SERVER_client_set_timeout (client,
3318                                     GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
3319   GNUNET_SERVER_receive_done (client,
3320                               GNUNET_OK);
3321 }
3322
3323
3324 /**
3325  * We've received data for this peer via TCP.  Unbox,
3326  * compute latency and forward.
3327  *
3328  * @param cls closure
3329  * @param client identification of the client
3330  * @param message the actual message
3331  */
3332 static void
3333 handle_tcp_data (void *cls,
3334                  struct GNUNET_SERVER_Client *client,
3335                  const struct GNUNET_MessageHeader *message)
3336 {
3337   struct Plugin *plugin = cls;
3338   struct GNUNET_ATS_Session *session;
3339   struct GNUNET_TIME_Relative delay;
3340   uint16_t type;
3341
3342   type = ntohs (message->type);
3343   if ( (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == type) ||
3344        (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE == type) )
3345   {
3346     /* We don't want to propagate WELCOME and NAT Probe messages up! */
3347     GNUNET_SERVER_receive_done (client,
3348                                 GNUNET_OK);
3349     return;
3350   }
3351   session = lookup_session_by_client (plugin, client);
3352   if (NULL == session)
3353   {
3354     /* No inbound session found */
3355     void *vaddr = NULL;
3356     size_t alen;
3357
3358     GNUNET_assert (GNUNET_OK ==
3359                    GNUNET_SERVER_client_get_address (client,
3360                                                      &vaddr,
3361                                                      &alen));
3362     LOG (GNUNET_ERROR_TYPE_ERROR,
3363          "Received unexpected %u bytes of type %u from `%s'\n",
3364          (unsigned int) ntohs (message->size),
3365          (unsigned int) ntohs (message->type),
3366          GNUNET_a2s (vaddr,
3367                      alen));
3368     GNUNET_break_op(0);
3369     GNUNET_SERVER_receive_done (client,
3370                                 GNUNET_SYSERR);
3371     GNUNET_free_non_null (vaddr);
3372     return;
3373   }
3374   if (GNUNET_YES == session->expecting_welcome)
3375   {
3376     /* Session is expecting WELCOME message */
3377     void *vaddr = NULL;
3378     size_t alen;
3379
3380     GNUNET_SERVER_client_get_address (client,
3381                                       &vaddr,
3382                                       &alen);
3383     LOG (GNUNET_ERROR_TYPE_ERROR,
3384          "Received unexpected %u bytes of type %u from `%s'\n",
3385          (unsigned int) ntohs (message->size),
3386          (unsigned int) ntohs (message->type),
3387          GNUNET_a2s (vaddr, alen));
3388     GNUNET_break_op(0);
3389     GNUNET_SERVER_receive_done (client,
3390                                 GNUNET_SYSERR);
3391     GNUNET_free_non_null (vaddr);
3392     return;
3393   }
3394
3395   session->last_activity = GNUNET_TIME_absolute_get ();
3396   {
3397     void *vaddr = NULL;
3398     size_t alen;
3399
3400     GNUNET_SERVER_client_get_address (client,
3401                                       &vaddr,
3402                                       &alen);
3403     LOG (GNUNET_ERROR_TYPE_DEBUG,
3404          "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
3405          (unsigned int) ntohs (message->size),
3406          (unsigned int) ntohs (message->type),
3407          GNUNET_i2s (&session->target),
3408          GNUNET_a2s (vaddr, alen));
3409     GNUNET_free_non_null (vaddr);
3410   }
3411
3412   GNUNET_STATISTICS_update (plugin->env->stats,
3413                             gettext_noop ("# bytes received via TCP"),
3414                             ntohs (message->size),
3415                             GNUNET_NO);
3416
3417   GNUNET_assert (GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
3418                                                                &session->target,
3419                                                                session));
3420   delay = plugin->env->receive (plugin->env->cls,
3421                                 session->address,
3422                                 session,
3423                                 message);
3424   reschedule_session_timeout (session);
3425   if (0 == delay.rel_value_us)
3426   {
3427     GNUNET_SERVER_receive_done (client,
3428                                 GNUNET_OK);
3429   }
3430   else
3431   {
3432     LOG (GNUNET_ERROR_TYPE_DEBUG,
3433          "Throttling receiving from `%s' for %s\n",
3434          GNUNET_i2s (&session->target),
3435          GNUNET_STRINGS_relative_time_to_string (delay,
3436                                                  GNUNET_YES));
3437     GNUNET_SERVER_disable_receive_done_warning (client);
3438     GNUNET_assert (NULL == session->receive_delay_task);
3439     session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
3440                                                                 &delayed_done,
3441                                                                 session);
3442   }
3443 }
3444
3445
3446 /**
3447  * Function called whenever a peer is connected on the "SERVER" level.
3448  * Increments number of active connections and suspends server if we
3449  * have reached the limit.
3450  *
3451  * @param cls closure
3452  * @param client identification of the client
3453  */
3454 static void
3455 connect_notify (void *cls,
3456                 struct GNUNET_SERVER_Client *client)
3457 {
3458   struct Plugin *plugin = cls;
3459
3460   if (NULL == client)
3461     return;
3462   plugin->cur_connections++;
3463   GNUNET_STATISTICS_set (plugin->env->stats,
3464                          gettext_noop ("# TCP server connections active"),
3465                          plugin->cur_connections,
3466                          GNUNET_NO);
3467   GNUNET_STATISTICS_update (plugin->env->stats,
3468                             gettext_noop ("# TCP server connect events"),
3469                             1,
3470                             GNUNET_NO);
3471   if (plugin->cur_connections != plugin->max_connections)
3472     return;
3473   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3474               _("TCP connection limit reached, suspending server\n"));
3475   GNUNET_STATISTICS_update (plugin->env->stats,
3476                             gettext_noop ("# TCP service suspended"),
3477                             1,
3478                             GNUNET_NO);
3479   GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
3480 }
3481
3482
3483 /**
3484  * Function called whenever a peer is disconnected on the "SERVER"
3485  * level.  Cleans up the connection, decrements number of active
3486  * connections and if applicable resumes listening.
3487  *
3488  * @param cls closure
3489  * @param client identification of the client
3490  */
3491 static void
3492 disconnect_notify (void *cls,
3493                    struct GNUNET_SERVER_Client *client)
3494 {
3495   struct Plugin *plugin = cls;
3496   struct GNUNET_ATS_Session *session;
3497
3498   if (NULL == client)
3499     return;
3500   GNUNET_assert (plugin->cur_connections >= 1);
3501   plugin->cur_connections--;
3502   session = lookup_session_by_client (plugin,
3503                                       client);
3504   if (NULL == session)
3505     return; /* unknown, nothing to do */
3506   LOG (GNUNET_ERROR_TYPE_DEBUG,
3507        "Destroying session of `%s' with %s due to network-level disconnect.\n",
3508        GNUNET_i2s (&session->target),
3509        tcp_plugin_address_to_string (session->plugin,
3510                                      session->address->address,
3511                                      session->address->address_length));
3512
3513   if (plugin->cur_connections == plugin->max_connections)
3514   {
3515     GNUNET_STATISTICS_update (session->plugin->env->stats,
3516                               gettext_noop ("# TCP service resumed"),
3517                               1,
3518                               GNUNET_NO);
3519     GNUNET_SERVER_resume (plugin->server); /* Resume server  */
3520   }
3521   GNUNET_STATISTICS_set (plugin->env->stats,
3522                          gettext_noop ("# TCP server connections active"),
3523                          plugin->cur_connections,
3524                          GNUNET_NO);
3525   GNUNET_STATISTICS_update (session->plugin->env->stats,
3526                             gettext_noop ("# network-level TCP disconnect events"),
3527                             1,
3528                             GNUNET_NO);
3529   tcp_plugin_disconnect_session (plugin,
3530                                  session);
3531 }
3532
3533
3534 /**
3535  * We can now send a probe message, copy into buffer to really send.
3536  *
3537  * @param cls closure, a `struct TCPProbeContext`
3538  * @param size max size to copy
3539  * @param buf buffer to copy message to
3540  * @return number of bytes copied into @a buf
3541  */
3542 static size_t
3543 notify_send_probe (void *cls,
3544                    size_t size,
3545                    void *buf)
3546 {
3547   struct TCPProbeContext *tcp_probe_ctx = cls;
3548   struct Plugin *plugin = tcp_probe_ctx->plugin;
3549   size_t ret;
3550
3551   tcp_probe_ctx->transmit_handle = NULL;
3552   GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
3553                                plugin->probe_tail,
3554                                tcp_probe_ctx);
3555   if (NULL == buf)
3556   {
3557     GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
3558     GNUNET_free(tcp_probe_ctx);
3559     return 0;
3560   }
3561   GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
3562   GNUNET_memcpy (buf,
3563           &tcp_probe_ctx->message,
3564           sizeof(tcp_probe_ctx->message));
3565   GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
3566                                 tcp_probe_ctx->sock);
3567   ret = sizeof(tcp_probe_ctx->message);
3568   GNUNET_free (tcp_probe_ctx);
3569   return ret;
3570 }
3571
3572
3573 /**
3574  * Function called by the NAT subsystem suggesting another peer wants
3575  * to connect to us via connection reversal.  Try to connect back to the
3576  * given IP.
3577  *
3578  * @param cls closure
3579  * @param addr address to try
3580  * @param addrlen number of bytes in @a addr
3581  */
3582 static void
3583 try_connection_reversal (void *cls,
3584                          const struct sockaddr *addr,
3585                          socklen_t addrlen)
3586 {
3587   struct Plugin *plugin = cls;
3588   struct GNUNET_CONNECTION_Handle *sock;
3589   struct TCPProbeContext *tcp_probe_ctx;
3590
3591   /**
3592    * We have received an ICMP response, ostensibly from a peer
3593    * that wants to connect to us! Send a message to establish a connection.
3594    */
3595   sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET,
3596                                                  addr,
3597                                                  addrlen);
3598   if (NULL == sock)
3599   {
3600     /* failed for some odd reason (out of sockets?); ignore attempt */
3601     return;
3602   }
3603
3604   tcp_probe_ctx = GNUNET_new (struct TCPProbeContext);
3605   tcp_probe_ctx->message.header.size
3606     = htons (sizeof (struct TCP_NAT_ProbeMessage));
3607   tcp_probe_ctx->message.header.type
3608     = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
3609   tcp_probe_ctx->message.clientIdentity
3610     = *plugin->env->my_identity;
3611   tcp_probe_ctx->plugin = plugin;
3612   tcp_probe_ctx->sock = sock;
3613   GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
3614                                plugin->probe_tail,
3615                                tcp_probe_ctx);
3616   tcp_probe_ctx->transmit_handle
3617     = GNUNET_CONNECTION_notify_transmit_ready (sock,
3618                                                ntohs (tcp_probe_ctx->message.header.size),
3619                                                GNUNET_TIME_UNIT_FOREVER_REL,
3620                                                &notify_send_probe,
3621                                                tcp_probe_ctx);
3622 }
3623
3624
3625 /**
3626  * Function obtain the network type for a session
3627  *
3628  * @param cls closure (`struct Plugin *`)
3629  * @param session the session
3630  * @return the network type in HBO or #GNUNET_SYSERR
3631  */
3632 static enum GNUNET_NetworkType
3633 tcp_plugin_get_network (void *cls,
3634                         struct GNUNET_ATS_Session *session)
3635 {
3636   return session->scope;
3637 }
3638
3639
3640 /**
3641  * Function obtain the network type for an address.
3642  *
3643  * @param cls closure (`struct Plugin *`)
3644  * @param address the address
3645  * @return the network type
3646  */
3647 static enum GNUNET_NetworkType
3648 tcp_plugin_get_network_for_address (void *cls,
3649                                     const struct GNUNET_HELLO_Address *address)
3650 {
3651   struct Plugin *plugin = cls;
3652   size_t addrlen;
3653   struct sockaddr_in a4;
3654   struct sockaddr_in6 a6;
3655   const struct IPv4TcpAddress *t4;
3656   const struct IPv6TcpAddress *t6;
3657   const void *sb;
3658   size_t sbs;
3659
3660   addrlen = address->address_length;
3661   if (addrlen == sizeof(struct IPv6TcpAddress))
3662   {
3663     GNUNET_assert (NULL != address->address); /* make static analysis happy */
3664     t6 = address->address;
3665     memset (&a6, 0, sizeof(a6));
3666 #if HAVE_SOCKADDR_IN_SIN_LEN
3667     a6.sin6_len = sizeof (a6);
3668 #endif
3669     a6.sin6_family = AF_INET6;
3670     a6.sin6_port = t6->t6_port;
3671     GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
3672     sb = &a6;
3673     sbs = sizeof(a6);
3674   }
3675   else if (addrlen == sizeof(struct IPv4TcpAddress))
3676   {
3677     GNUNET_assert (NULL != address->address); /* make static analysis happy */
3678     t4 = address->address;
3679     memset (&a4, 0, sizeof(a4));
3680 #if HAVE_SOCKADDR_IN_SIN_LEN
3681     a4.sin_len = sizeof (a4);
3682 #endif
3683     a4.sin_family = AF_INET;
3684     a4.sin_port = t4->t4_port;
3685     a4.sin_addr.s_addr = t4->ipv4_addr;
3686     sb = &a4;
3687     sbs = sizeof(a4);
3688   }
3689   else
3690   {
3691     GNUNET_break (0);
3692     return GNUNET_NT_UNSPECIFIED;
3693   }
3694   return plugin->env->get_address_type (plugin->env->cls,
3695                                         sb,
3696                                         sbs);
3697 }
3698
3699
3700 /**
3701  * Return information about the given session to the
3702  * monitor callback.
3703  *
3704  * @param cls the `struct Plugin` with the monitor callback (`sic`)
3705  * @param peer peer we send information about
3706  * @param value our `struct GNUNET_ATS_Session` to send information about
3707  * @return #GNUNET_OK (continue to iterate)
3708  */
3709 static int
3710 send_session_info_iter (void *cls,
3711                         const struct GNUNET_PeerIdentity *peer,
3712                         void *value)
3713 {
3714   struct Plugin *plugin = cls;
3715   struct GNUNET_ATS_Session *session = value;
3716
3717   notify_session_monitor (plugin,
3718                           session,
3719                           GNUNET_TRANSPORT_SS_INIT);
3720   /* FIXME: cannot tell if this is up or not from current
3721      session state... */
3722   notify_session_monitor (plugin,
3723                           session,
3724                           GNUNET_TRANSPORT_SS_UP);
3725   return GNUNET_OK;
3726 }
3727
3728
3729 /**
3730  * Begin monitoring sessions of a plugin.  There can only
3731  * be one active monitor per plugin (i.e. if there are
3732  * multiple monitors, the transport service needs to
3733  * multiplex the generated events over all of them).
3734  *
3735  * @param cls closure of the plugin
3736  * @param sic callback to invoke, NULL to disable monitor;
3737  *            plugin will being by iterating over all active
3738  *            sessions immediately and then enter monitor mode
3739  * @param sic_cls closure for @a sic
3740  */
3741 static void
3742 tcp_plugin_setup_monitor (void *cls,
3743                           GNUNET_TRANSPORT_SessionInfoCallback sic,
3744                           void *sic_cls)
3745 {
3746   struct Plugin *plugin = cls;
3747
3748   plugin->sic = sic;
3749   plugin->sic_cls = sic_cls;
3750   if (NULL != sic)
3751   {
3752     GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
3753                                            &send_session_info_iter,
3754                                            plugin);
3755     /* signal end of first iteration */
3756     sic (sic_cls, NULL, NULL);
3757   }
3758 }
3759
3760
3761 /**
3762  * Entry point for the plugin.
3763  *
3764  * @param cls closure, the `struct GNUNET_TRANSPORT_PluginEnvironment *`
3765  * @return the `struct GNUNET_TRANSPORT_PluginFunctions *` or NULL on error
3766  */
3767 void *
3768 libgnunet_plugin_transport_xt_init (void *cls)
3769 {
3770   static const struct GNUNET_SERVER_MessageHandler my_handlers[] = {
3771     { &handle_tcp_welcome, NULL,
3772       GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME,
3773       sizeof(struct WelcomeMessage) },
3774     { &handle_tcp_nat_probe, NULL,
3775       GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE,
3776       sizeof(struct TCP_NAT_ProbeMessage) },
3777     { &handle_tcp_data, NULL,
3778       GNUNET_MESSAGE_TYPE_ALL, 0 },
3779     { NULL, NULL, 0, 0 }
3780   };
3781   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3782   struct GNUNET_TRANSPORT_PluginFunctions *api;
3783   struct Plugin *plugin;
3784   struct LEGACY_SERVICE_Context *service;
3785   unsigned long long aport;
3786   unsigned long long bport;
3787   unsigned long long max_connections;
3788   unsigned int i;
3789   struct GNUNET_TIME_Relative idle_timeout;
3790 #ifdef TCP_STEALTH
3791   struct GNUNET_NETWORK_Handle *const*lsocks;
3792 #endif
3793   int ret;
3794   int ret_s;
3795   struct sockaddr **addrs;
3796   socklen_t *addrlens;
3797
3798   if (NULL == env->receive)
3799   {
3800     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
3801      initialze the plugin or the API */
3802     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
3803     api->cls = NULL;
3804     api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
3805     api->address_to_string = &tcp_plugin_address_to_string;
3806     api->string_to_address = &tcp_plugin_string_to_address;
3807     return api;
3808   }
3809
3810   GNUNET_assert (NULL != env->cfg);
3811   if (GNUNET_OK !=
3812       GNUNET_CONFIGURATION_get_value_number (env->cfg,
3813                                              "transport-xt",
3814                                              "MAX_CONNECTIONS",
3815                                              &max_connections))
3816     max_connections = 128;
3817
3818   aport = 0;
3819   if ((GNUNET_OK !=
3820        GNUNET_CONFIGURATION_get_value_number (env->cfg,
3821                                               "transport-xt",
3822                                               "PORT", &bport)) ||
3823       (bport > 65535) ||
3824       ((GNUNET_OK ==
3825         GNUNET_CONFIGURATION_get_value_number (env->cfg,
3826                                                "transport-xt",
3827                                                "ADVERTISED-PORT", &aport)) &&
3828        (aport > 65535) ))
3829   {
3830     LOG(GNUNET_ERROR_TYPE_ERROR,
3831         _("Require valid port number for service `%s' in configuration!\n"),
3832         "transport-xt");
3833     return NULL ;
3834   }
3835   if (0 == aport)
3836     aport = bport;
3837   if (0 == bport)
3838     aport = 0;
3839   if (0 != bport)
3840   {
3841     service = LEGACY_SERVICE_start ("transport-xt",
3842                                     env->cfg,
3843                                     LEGACY_SERVICE_OPTION_NONE);
3844     if (NULL == service)
3845     {
3846       LOG (GNUNET_ERROR_TYPE_WARNING,
3847            _("Failed to start service.\n"));
3848       return NULL;
3849     }
3850   }
3851   else
3852     service = NULL;
3853
3854   api = NULL;
3855   plugin = GNUNET_new (struct Plugin);
3856   plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections,
3857                                                              GNUNET_YES);
3858   plugin->max_connections = max_connections;
3859   plugin->open_port = bport;
3860   plugin->adv_port = aport;
3861   plugin->env = env;
3862   plugin->my_welcome.header.size = htons (sizeof(struct WelcomeMessage));
3863   plugin->my_welcome.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME);
3864   plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
3865
3866   if ( (NULL != service) &&
3867        (GNUNET_YES ==
3868         GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
3869                                               "transport-xt",
3870                                               "TCP_STEALTH")) )
3871   {
3872 #ifdef TCP_STEALTH
3873     plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
3874     lsocks = LEGACY_SERVICE_get_listen_sockets (service);
3875     if (NULL != lsocks)
3876     {
3877       uint32_t len = sizeof (struct WelcomeMessage);
3878
3879       for (i=0;NULL!=lsocks[i];i++)
3880       {
3881         if ( (GNUNET_OK !=
3882               GNUNET_NETWORK_socket_setsockopt (lsocks[i],
3883                                                 IPPROTO_TCP,
3884                                                 TCP_STEALTH,
3885                                                 env->my_identity,
3886                                                 sizeof (struct GNUNET_PeerIdentity))) ||
3887              (GNUNET_OK !=
3888               GNUNET_NETWORK_socket_setsockopt (lsocks[i],
3889                                                 IPPROTO_TCP,
3890                                                 TCP_STEALTH_INTEGRITY_LEN,
3891                                                 &len,
3892                                                 sizeof (len))) )
3893         {
3894           /* TCP STEALTH not supported by kernel */
3895           GNUNET_assert (0 == i);
3896           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3897                       _("TCP_STEALTH not supported on this platform.\n"));
3898           goto die;
3899         }
3900       }
3901     }
3902 #else
3903     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3904                 _("TCP_STEALTH not supported on this platform.\n"));
3905     goto die;
3906 #endif
3907   }
3908
3909   if ( (NULL != service) &&
3910        (GNUNET_SYSERR !=
3911         (ret_s =
3912          get_server_addresses ("transport-xt",
3913                                env->cfg,
3914                                &addrs,
3915                                &addrlens))))
3916   {
3917     for (ret = ret_s-1; ret >= 0; ret--)
3918       LOG (GNUNET_ERROR_TYPE_INFO,
3919            "Binding to address `%s'\n",
3920            GNUNET_a2s (addrs[ret], addrlens[ret]));
3921     plugin->nat
3922       = GNUNET_NAT_register (env->cfg,
3923                              "transport-xt",
3924                              IPPROTO_TCP,
3925                              (unsigned int) ret_s,
3926                              (const struct sockaddr **) addrs,
3927                              addrlens,
3928                              &tcp_nat_port_map_callback,
3929                              &try_connection_reversal,
3930                              plugin);
3931     for (ret = ret_s -1; ret >= 0; ret--)
3932       GNUNET_free (addrs[ret]);
3933     GNUNET_free_non_null (addrs);
3934     GNUNET_free_non_null (addrlens);
3935   }
3936   else
3937   {
3938     plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
3939                                        "transport-xt",
3940                                        IPPROTO_TCP,
3941                                        0,
3942                                        NULL,
3943                                        NULL,
3944                                        NULL,
3945                                        &try_connection_reversal,
3946                                        plugin);
3947   }
3948   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
3949   api->cls = plugin;
3950   api->send = &tcp_plugin_send;
3951   api->get_session = &tcp_plugin_get_session;
3952   api->disconnect_session = &tcp_plugin_disconnect_session;
3953   api->query_keepalive_factor = &tcp_plugin_query_keepalive_factor;
3954   api->disconnect_peer = &tcp_plugin_disconnect;
3955   api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
3956   api->check_address = &tcp_plugin_check_address;
3957   api->address_to_string = &tcp_plugin_address_to_string;
3958   api->string_to_address = &tcp_plugin_string_to_address;
3959   api->get_network = &tcp_plugin_get_network;
3960   api->get_network_for_address = &tcp_plugin_get_network_for_address;
3961   api->update_session_timeout = &tcp_plugin_update_session_timeout;
3962   api->update_inbound_delay = &tcp_plugin_update_inbound_delay;
3963   api->setup_monitor = &tcp_plugin_setup_monitor;
3964   plugin->service = service;
3965   if (NULL != service)
3966   {
3967     plugin->server = LEGACY_SERVICE_get_server (service);
3968   }
3969   else
3970   {
3971     if (GNUNET_OK !=
3972         GNUNET_CONFIGURATION_get_value_time (env->cfg,
3973                                              "transport-xt",
3974                                              "TIMEOUT",
3975                                              &idle_timeout))
3976     {
3977       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3978                                  "transport-xt",
3979                                  "TIMEOUT");
3980       goto die;
3981     }
3982     plugin->server
3983       = GNUNET_SERVER_create_with_sockets (NULL,
3984                                            plugin,
3985                                            NULL,
3986                                            idle_timeout,
3987                                            GNUNET_YES);
3988   }
3989   plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
3990   GNUNET_memcpy (plugin->handlers,
3991                  my_handlers,
3992                  sizeof(my_handlers));
3993   for (i = 0;i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);i++)
3994     plugin->handlers[i].callback_cls = plugin;
3995
3996   GNUNET_SERVER_add_handlers (plugin->server,
3997                               plugin->handlers);
3998   GNUNET_SERVER_connect_notify (plugin->server,
3999                                 &connect_notify,
4000                                 plugin);
4001   GNUNET_SERVER_disconnect_notify (plugin->server,
4002                                    &disconnect_notify,
4003                                    plugin);
4004   plugin->nat_wait_conns = GNUNET_CONTAINER_multipeermap_create (16,
4005                                                                  GNUNET_YES);
4006   if (0 != bport)
4007     LOG (GNUNET_ERROR_TYPE_INFO,
4008          _("XT transport listening on port %llu\n"),
4009          bport);
4010   else
4011     LOG (GNUNET_ERROR_TYPE_INFO,
4012          _("XT transport not listening on any port (client only)\n"));
4013   if ( (aport != bport) &&
4014        (0 != bport) )
4015     LOG (GNUNET_ERROR_TYPE_INFO,
4016          _("XT transport advertises itself as being on port %llu\n"),
4017          aport);
4018   /* Initially set connections to 0 */
4019   GNUNET_STATISTICS_set (plugin->env->stats,
4020                          gettext_noop ("# XT sessions active"),
4021                          0,
4022                          GNUNET_NO);
4023   return api;
4024
4025  die:
4026   if (NULL != plugin->nat)
4027     GNUNET_NAT_unregister (plugin->nat);
4028   GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
4029   if (NULL != service)
4030     LEGACY_SERVICE_stop (service);
4031   GNUNET_free (plugin);
4032   GNUNET_free_non_null (api);
4033   return NULL;
4034 }
4035
4036
4037 /**
4038  * Exit point from the plugin.
4039  *
4040  * @param cls the `struct GNUNET_TRANSPORT_PluginFunctions`
4041  * @return NULL
4042  */
4043 void *
4044 libgnunet_plugin_transport_xt_done (void *cls)
4045 {
4046   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
4047   struct Plugin *plugin = api->cls;
4048   struct TCPProbeContext *tcp_probe;
4049   struct PrettyPrinterContext *cur;
4050   struct PrettyPrinterContext *next;
4051
4052   if (NULL == plugin)
4053   {
4054     GNUNET_free(api);
4055     return NULL ;
4056   }
4057   LOG (GNUNET_ERROR_TYPE_DEBUG,
4058        "Shutting down XT plugin\n");
4059
4060   /* Removing leftover sessions */
4061   GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
4062                                          &session_disconnect_it,
4063                                          plugin);
4064   /* Removing leftover NAT sessions */
4065   GNUNET_CONTAINER_multipeermap_iterate (plugin->nat_wait_conns,
4066                                          &session_disconnect_it,
4067                                          plugin);
4068
4069   for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
4070   {
4071     next = cur->next;
4072     GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
4073                                  plugin->ppc_dll_tail,
4074                                  cur);
4075     GNUNET_RESOLVER_request_cancel (cur->resolver_handle);
4076     cur->asc (cur->asc_cls,
4077               NULL,
4078               GNUNET_OK);
4079     GNUNET_free (cur);
4080   }
4081
4082   if (NULL != plugin->service)
4083     LEGACY_SERVICE_stop (plugin->service);
4084   else
4085     GNUNET_SERVER_destroy (plugin->server);
4086   GNUNET_free (plugin->handlers);
4087   if (NULL != plugin->nat)
4088     GNUNET_NAT_unregister (plugin->nat);
4089   while (NULL != (tcp_probe = plugin->probe_head))
4090   {
4091     GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
4092                                  plugin->probe_tail,
4093                                  tcp_probe);
4094     GNUNET_CONNECTION_destroy (tcp_probe->sock);
4095     GNUNET_free (tcp_probe);
4096   }
4097   GNUNET_CONTAINER_multipeermap_destroy (plugin->nat_wait_conns);
4098   GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
4099   GNUNET_break (0 == plugin->cur_connections);
4100   GNUNET_free (plugin);
4101   GNUNET_free (api);
4102   return NULL;
4103 }
4104
4105 /* end of plugin_transport_xt.c */