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