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