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