/*
This file is part of GNUnet
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/**
* @file transport/plugin_transport_http.h
* @brief http transport service plugin
* @author Matthias Wachs
*/
#ifndef PLUGIN_TRANSPORT_HTTP_H
#define PLUGIN_TRANSPORT_HTTP_H
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
#include "gnunet_connection_lib.h"
#include "gnunet_service_lib.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
#include "gnunet_resolver_service.h"
#include "gnunet_server_lib.h"
#include "gnunet_container_lib.h"
#include "gnunet_transport_plugin.h"
#include "gnunet_os_lib.h"
#include "gnunet_nat_lib.h"
#include "microhttpd.h"
#if HAVE_CURL_CURL_H
#include
#elif HAVE_GNURL_CURL_H
#include
#endif
#define DEBUG_HTTP GNUNET_EXTRA_LOGGING
#define VERBOSE_SERVER GNUNET_EXTRA_LOGGING
#define VERBOSE_CLIENT GNUNET_EXTRA_LOGGING
#define VERBOSE_CURL GNUNET_NO
#if BUILD_HTTPS
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_init
#define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_done
#else
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_init
#define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_done
#endif
#define INBOUND GNUNET_YES
#define OUTBOUND GNUNET_NO
#define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
/**
* Encapsulation of all of the state of the plugin.
*/
struct Plugin
{
/**
* Our environment.
*/
struct GNUNET_TRANSPORT_PluginEnvironment *env;
/**
* Head of linked list of open sessions.
*/
struct GNUNET_ATS_Session *head;
/**
* Tail of linked list of open sessions.
*/
struct GNUNET_ATS_Session *tail;
/**
* NAT handle & address management
*/
struct GNUNET_NAT_Handle *nat;
/**
* Our own IPv4 addresses DLL head
*/
struct HttpAddressWrapper *addr_head;
/**
* Our own IPv4 addresses DLL tail
*/
struct HttpAddressWrapper *addr_tail;
/**
* External hostname the plugin can be connected to, can be different to
* the host's FQDN, used e.g. for reverse proxying
*/
char *external_hostname;
/**
* External hostname the plugin can be connected to, can be different to
* the host's FQDN, used e.g. for reverse proxying
*/
struct HttpAddress *ext_addr;
/**
* External address length
*/
size_t ext_addr_len;
/**
* Task calling transport service about external address
*/
struct GNUNET_SCHEDULER_Task * notify_ext_task;
/**
* Plugin name.
* Equals configuration section: transport-http, transport-https
*/
char *name;
/**
* Plugin protocol
* http, https
*/
char *protocol;
/**
* Use IPv4? #GNUNET_YES or #GNUNET_NO
*/
int ipv4;
/**
* Use IPv6? #GNUNET_YES or #GNUNET_NO
*/
int ipv6;
/**
* Does plugin just use outbound connections and not accept inbound?
*/
int client_only;
/**
* Port used
*/
uint16_t port;
/**
* Maximum number of sockets the plugin can use
* Each http inbound /outbound connections are two connections
*/
int max_connections;
/**
* Number of outbound sessions
*/
unsigned int outbound_sessions;
/**
* Number of inbound sessions
*/
unsigned int inbound_sessions;
/**
* libCurl TLS crypto init string, can be set to enhance performance
*
* Example:
*
* Use RC4-128 instead of AES:
* NONE:+VERS-TLS1.0:+ARCFOUR-128:+SHA1:+RSA:+COMP-NULL
*/
char *crypto_init;
/**
* TLS key
*/
char *key;
/**
* TLS certificate
*/
char *cert;
/**
* Current number of establishes connections
*/
int cur_connections;
/**
* Last used unique HTTP connection tag
*/
uint32_t last_tag;
/**
* MHD IPv4 daemon
*/
struct MHD_Daemon *server_v4;
/**
* MHD IPv4 task
*/
struct GNUNET_SCHEDULER_Task * server_v4_task;
/**
* The IPv4 server is scheduled to run asap
*/
int server_v4_immediately;
/**
* MHD IPv6 daemon
*/
struct MHD_Daemon *server_v6;
/**
* MHD IPv4 task
*/
struct GNUNET_SCHEDULER_Task * server_v6_task;
/**
* The IPv6 server is scheduled to run asap
*/
int server_v6_immediately;
/**
* IPv4 server socket to bind to
*/
struct sockaddr_in *server_addr_v4;
/**
* IPv6 server socket to bind to
*/
struct sockaddr_in6 *server_addr_v6;
/**
* Head of server semi connections
* A full session consists of 2 semi-connections: send and receive
* If not both directions are established the server keeps this sessions here
*/
struct GNUNET_ATS_Session *server_semi_head;
/**
* Tail of server semi connections
* A full session consists of 2 semi-connections: send and receive
* If not both directions are established the server keeps this sessions here
*/
struct GNUNET_ATS_Session *server_semi_tail;
/**
* cURL Multihandle
*/
CURLM *client_mh;
/**
* curl perform task
*/
struct GNUNET_SCHEDULER_Task * client_perform_task;
};
GNUNET_NETWORK_STRUCT_BEGIN
/**
* HTTP addresses including a full URI
*/
struct HttpAddress
{
/**
* Length of the address following in NBO
*/
uint32_t addr_len GNUNET_PACKED;
/**
* Address following
*/
void *addr GNUNET_PACKED;
};
/**
* IPv4 addresses
*/
struct IPv4HttpAddress
{
/**
* IPv4 address, in network byte order.
*/
uint32_t ipv4_addr GNUNET_PACKED;
/**
* Port number, in network byte order.
*/
uint16_t u4_port GNUNET_PACKED;
};
/**
* IPv4 addresses
*/
struct IPv6HttpAddress
{
/**
* IPv6 address.
*/
struct in6_addr ipv6_addr GNUNET_PACKED;
/**
* Port number, in network byte order.
*/
uint16_t u6_port GNUNET_PACKED;
};
GNUNET_NETWORK_STRUCT_END
struct ServerRequest
{
/**
* _RECV or _SEND
*/
int direction;
/**
* Should this connection get disconnected? #GNUNET_YES / #GNUNET_NO
*/
int disconnect;
/**
* The session this server connection belongs to
*/
struct GNUNET_ATS_Session *session;
/**
* The MHD connection
*/
struct MHD_Connection *mhd_conn;
};
/**
* Session handle for connections.
*/
struct GNUNET_ATS_Session
{
/**
* To whom are we talking to
*/
struct GNUNET_PeerIdentity target;
/**
* Stored in a linked list.
*/
struct GNUNET_ATS_Session *next;
/**
* Stored in a linked list.
*/
struct GNUNET_ATS_Session *prev;
/**
* Pointer to the global plugin struct.
*/
struct Plugin *plugin;
/**
* Address
*/
void *addr;
/**
* Address length
*/
size_t addrlen;
/**
* ATS network type in NBO
*/
uint32_t ats_address_network_type;
/**
* next pointer for double linked list
*/
struct HTTP_Message *msg_head;
/**
* previous pointer for double linked list
*/
struct HTTP_Message *msg_tail;
/**
* Message stream tokenizer for incoming data
*/
struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk;
/**
* Absolute time when to receive data again
* Used for receive throttling
*/
struct GNUNET_TIME_Absolute next_receive;
/**
* Inbound or outbound connection
* Outbound: #GNUNET_NO (client is used to send and receive)
* Inbound : #GNUNET_YES (server is used to send and receive)
*/
int inbound;
/**
* Unique HTTP/S connection tag for this connection
*/
uint32_t tag;
/**
* Client send handle
*/
void *client_put;
/**
* Client receive handle
*/
void *client_get;
/**
* Task to wake up client receive handle when receiving is allowed again
*/
struct GNUNET_SCHEDULER_Task * recv_wakeup_task;
/**
* Session timeout task
*/
struct GNUNET_SCHEDULER_Task * timeout_task;
/**
* Is client send handle paused since there are no data to send?
* #GNUNET_YES or #GNUNET_NO
*/
int client_put_paused;
/**
* Client send handle
*/
struct ServerRequest *server_recv;
/**
* Client send handle
*/
struct ServerRequest *server_send;
};
/**
* Message to send using http
*/
struct HTTP_Message
{
/**
* next pointer for double linked list
*/
struct HTTP_Message *next;
/**
* previous pointer for double linked list
*/
struct HTTP_Message *prev;
/**
* buffer containing data to send
*/
char *buf;
/**
* amount of data already sent
*/
size_t pos;
/**
* buffer length
*/
size_t size;
/**
* Continuation function to call once the transmission buffer
* has again space available. NULL if there is no
* continuation to call.
*/
GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
/**
* Closure for @e transmit_cont.
*/
void *transmit_cont_cls;
};
struct GNUNET_ATS_Session *
create_session (struct Plugin *plugin,
const struct GNUNET_PeerIdentity *target,
const void *addr,
size_t addrlen);
int
exist_session (struct Plugin *plugin,
struct GNUNET_ATS_Session *s);
void
delete_session (struct GNUNET_ATS_Session *s);
int
exist_session (struct Plugin *plugin,
struct GNUNET_ATS_Session *s);
struct GNUNET_TIME_Relative
http_plugin_receive (void *cls,
const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message,
struct GNUNET_ATS_Session *session,
const char *sender_address,
uint16_t sender_address_len);
const char *
http_plugin_address_to_string (void *cls,
const void *addr,
size_t addrlen);
int
client_disconnect (struct GNUNET_ATS_Session *s);
int
client_connect (struct GNUNET_ATS_Session *s);
int
client_send (struct GNUNET_ATS_Session *s, struct HTTP_Message *msg);
int
client_start (struct Plugin *plugin);
void
client_stop (struct Plugin *plugin);
int
server_disconnect (struct GNUNET_ATS_Session *s);
int
server_send (struct GNUNET_ATS_Session *s, struct HTTP_Message *msg);
int
server_start (struct Plugin *plugin);
void
server_stop (struct Plugin *plugin);
void
notify_session_end (void *cls,
const struct GNUNET_PeerIdentity *peer,
struct GNUNET_ATS_Session *s);
/*#ifndef PLUGIN_TRANSPORT_HTTP_H*/
#endif
/* end of plugin_transport_http.h */