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