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