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