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