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