Home | History | Annotate | Download | only in examples
      1 /*
      2     Copyright Copyright (C) 2013 Andrey Uzunov
      3 
      4     This program is free software: you can redistribute it and/or modify
      5     it under the terms of the GNU General Public License as published by
      6     the Free Software Foundation, either version 3 of the License, or
      7     (at your option) any later version.
      8 
      9     This program is distributed in the hope that it will be useful,
     10     but WITHOUT ANY WARRANTY; without even the implied warranty of
     11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12     GNU General Public License for more details.
     13 
     14     You should have received a copy of the GNU General Public License
     15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 
     18 /**
     19  * @file mhd2spdy_structures.h
     20  * @brief  Common structures, functions, macros and global variables.
     21  * @author Andrey Uzunov
     22  */
     23 #ifndef STRUCTURES_H
     24 #define STRUCTURES_H
     25 
     26 #define _GNU_SOURCE
     27 
     28 #include <unistd.h>
     29 #include <stdlib.h>
     30 #include <stdint.h>
     31 #include <stdbool.h>
     32 #include <string.h>
     33 #include <stdio.h>
     34 #include <ctype.h>
     35 #include <errno.h>
     36 #include <assert.h>
     37 #include <microhttpd.h>
     38 #include <signal.h>
     39 #include <poll.h>
     40 #include <fcntl.h>
     41 #include <regex.h>
     42 #include <sys/types.h>
     43 #include <sys/socket.h>
     44 #include <netdb.h>
     45 #include <netinet/in.h>
     46 #include <netinet/tcp.h>
     47 #include <openssl/ssl.h>
     48 #include <openssl/err.h>
     49 #include <spdylay/spdylay.h>
     50 #include <getopt.h>
     51 
     52 
     53 /* WANT_READ if SSL connection needs more input; or WANT_WRITE if it
     54    needs more output; or IO_NONE. This is necessary because SSL/TLS
     55    re-negotiation is possible at any time. Spdylay API offers
     56    similar functions like spdylay_session_want_read() and
     57    spdylay_session_want_write() but they do not take into account
     58    SSL connection. */
     59 enum
     60 {
     61   IO_NONE,
     62   WANT_READ,
     63   WANT_WRITE
     64 };
     65 
     66 
     67 struct Proxy;
     68 
     69 
     70 struct SPDY_Connection {
     71   SSL *ssl;
     72   spdylay_session *session;
     73   struct SPDY_Connection *prev;
     74   struct SPDY_Connection *next;
     75   struct Proxy *proxies_head;
     76   struct Proxy *proxies_tail;
     77   char *host;
     78   int fd;
     79   int want_io;
     80   uint counter;
     81   uint streams_opened;
     82   bool is_tls;
     83 };
     84 
     85 
     86 struct URI
     87 {
     88   char * full_uri;
     89   char * scheme;
     90   char * host_and_port;
     91   char * host;
     92   char * path;
     93   char * path_and_more;
     94   char * query;
     95   char * fragment;
     96   uint16_t port;
     97 };
     98 
     99 
    100 struct HTTP_URI;
    101 
    102 
    103 struct Proxy
    104 {
    105 	struct MHD_Connection *http_connection;
    106 	struct MHD_Response *http_response;
    107 	struct URI *uri;
    108   struct HTTP_URI *http_uri;
    109   struct SPDY_Connection *spdy_connection;
    110   struct Proxy *next;
    111   struct Proxy *prev;
    112 	char *url;
    113 	char *version;
    114 	void *http_body;
    115 	void *received_body;
    116 	size_t http_body_size;
    117 	size_t received_body_size;
    118 	ssize_t length;
    119 	int status;
    120 	int id;
    121   int32_t stream_id;
    122 	bool done;
    123 	bool http_error;
    124 	bool spdy_error;
    125   bool http_active;
    126   bool spdy_active;
    127   bool receiving_done;
    128 };
    129 
    130 
    131 struct HTTP_URI
    132 {
    133   char * uri;
    134   struct Proxy * proxy;
    135 };
    136 
    137 
    138 struct SPDY_Headers
    139 {
    140   const char **nv;
    141   int num;
    142   int cnt;
    143 };
    144 
    145 
    146 struct global_options
    147 {
    148   char *spdy2http_str;
    149   struct SPDY_Connection *spdy_connection;
    150   struct SPDY_Connection *spdy_connections_head;
    151   struct SPDY_Connection *spdy_connections_tail;
    152   int streams_opened;
    153   int responses_pending;
    154   regex_t uri_preg;
    155   size_t global_memory;
    156   SSL_CTX *ssl_ctx;
    157   uint32_t total_spdy_connections;
    158   uint16_t spdy_proto_version;
    159   uint16_t listen_port;
    160   bool verbose;
    161   bool only_proxy;
    162   bool spdy_data_received;
    163   bool statistics;
    164   bool ignore_rst_stream;
    165 }
    166 glob_opt;
    167 
    168 
    169 struct global_statistics
    170 {
    171   //unsigned long long http_bytes_sent;
    172   //unsigned long long http_bytes_received;
    173   unsigned long long spdy_bytes_sent;
    174   unsigned long long spdy_bytes_received;
    175   unsigned long long spdy_bytes_received_and_dropped;
    176 }
    177 glob_stat;
    178 
    179 
    180 //forbidden headers
    181 #define SPDY_HTTP_HEADER_TRANSFER_ENCODING "transfer-encoding"
    182 #define SPDY_HTTP_HEADER_PROXY_CONNECTION "proxy-connection"
    183 #define SPDY_HTTP_HEADER_KEEP_ALIVE "keep-alive"
    184 #define SPDY_HTTP_HEADER_CONNECTION "connection"
    185 
    186 #define MAX_SPDY_CONNECTIONS 100
    187 
    188 #define SPDY_MAX_OUTLEN 4096
    189 
    190 /**
    191  * Insert an element at the head of a DLL. Assumes that head, tail and
    192  * element are structs with prev and next fields.
    193  *
    194  * @param head pointer to the head of the DLL (struct ? *)
    195  * @param tail pointer to the tail of the DLL (struct ? *)
    196  * @param element element to insert (struct ? *)
    197  */
    198 #define DLL_insert(head,tail,element) do { \
    199 	(element)->next = (head); \
    200 	(element)->prev = NULL; \
    201 	if ((tail) == NULL) \
    202 		(tail) = element; \
    203 	else \
    204 		(head)->prev = element; \
    205 	(head) = (element); } while (0)
    206 
    207 
    208 /**
    209  * Remove an element from a DLL. Assumes
    210  * that head, tail and element are structs
    211  * with prev and next fields.
    212  *
    213  * @param head pointer to the head of the DLL (struct ? *)
    214  * @param tail pointer to the tail of the DLL (struct ? *)
    215  * @param element element to remove (struct ? *)
    216  */
    217 #define DLL_remove(head,tail,element) do { \
    218 	if ((element)->prev == NULL) \
    219 		(head) = (element)->next;  \
    220 	else \
    221 		(element)->prev->next = (element)->next; \
    222 	if ((element)->next == NULL) \
    223 		(tail) = (element)->prev;  \
    224 	else \
    225 		(element)->next->prev = (element)->prev; \
    226 	(element)->next = NULL; \
    227 	(element)->prev = NULL; } while (0)
    228 
    229 
    230 #define PRINT_INFO(msg) do{\
    231   if(glob_opt.verbose){\
    232 	printf("%i:%s\n", __LINE__, msg);\
    233 	fflush(stdout);\
    234 	}\
    235   }\
    236 	while(0)
    237 
    238 
    239 #define PRINT_INFO2(fmt, ...) do{\
    240   if(glob_opt.verbose){\
    241 	printf("%i\n", __LINE__);\
    242 	printf(fmt,##__VA_ARGS__);\
    243 	printf("\n");\
    244 	fflush(stdout);\
    245 	}\
    246 	}\
    247 	while(0)
    248 
    249 
    250 #define DIE(msg) do{\
    251 	printf("FATAL ERROR (line %i): %s\n", __LINE__, msg);\
    252 	fflush(stdout);\
    253   exit(EXIT_FAILURE);\
    254 	}\
    255 	while(0)
    256 
    257 
    258 #define UPDATE_STAT(stat, value) do{\
    259   if(glob_opt.statistics)\
    260   {\
    261     stat += value;\
    262   }\
    263   }\
    264   while(0)
    265 
    266 
    267 void
    268 free_uri(struct URI * uri);
    269 
    270 
    271 int
    272 init_parse_uri(regex_t * preg);
    273 
    274 
    275 void
    276 deinit_parse_uri(regex_t * preg);
    277 
    278 
    279 int
    280 parse_uri(regex_t * preg,
    281           char * full_uri,
    282           struct URI ** uri);
    283 
    284 
    285 void
    286 free_proxy(struct Proxy *proxy);
    287 
    288 
    289 void *
    290 au_malloc(size_t size);
    291 
    292 
    293 bool
    294 copy_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size);
    295 
    296 #endif
    297