• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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