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