connection.c (8277B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <errno.h> 3 #include <netinet/in.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <sys/socket.h> 7 #include <sys/types.h> 8 #include <time.h> 9 #include <unistd.h> 10 11 #include "connection.h" 12 #include "data.h" 13 #include "http.h" 14 #include "server.h" 15 #include "sock.h" 16 #include "util.h" 17 18 struct worker_data { 19 int insock; 20 size_t nslots; 21 const struct server *srv; 22 }; 23 24 void 25 connection_log(const struct connection *c) 26 { 27 char inaddr_str[INET6_ADDRSTRLEN /* > INET_ADDRSTRLEN */]; 28 char tstmp[21]; 29 30 /* create timestamp */ 31 if (!strftime(tstmp, sizeof(tstmp), "%Y-%m-%dT%H:%M:%SZ", 32 gmtime(&(time_t){time(NULL)}))) { 33 warn("strftime: Exceeded buffer capacity"); 34 tstmp[0] = '\0'; /* tstmp contents are undefined on failure */ 35 /* continue anyway */ 36 } 37 38 /* generate address-string */ 39 if (sock_get_inaddr_str(&c->ia, inaddr_str, LEN(inaddr_str))) { 40 warn("sock_get_inaddr_str: Couldn't generate adress-string"); 41 inaddr_str[0] = '\0'; 42 } 43 44 printf("%s\t%s\t%s%.*d\t%s\t%s%s%s%s%s\n", 45 tstmp, 46 inaddr_str, 47 (c->res.status == 0) ? "dropped" : "", 48 (c->res.status == 0) ? 0 : 3, 49 c->res.status, 50 c->req.field[REQ_HOST][0] ? c->req.field[REQ_HOST] : "-", 51 c->req.path[0] ? c->req.path : "-", 52 c->req.query[0] ? "?" : "", 53 c->req.query, 54 c->req.fragment[0] ? "#" : "", 55 c->req.fragment); 56 } 57 58 void 59 connection_reset(struct connection *c) 60 { 61 if (c != NULL) { 62 shutdown(c->fd, SHUT_RDWR); 63 close(c->fd); 64 memset(c, 0, sizeof(*c)); 65 } 66 } 67 68 void 69 connection_serve(struct connection *c, const struct server *srv) 70 { 71 enum status s; 72 int done; 73 74 switch (c->state) { 75 case C_VACANT: 76 /* 77 * we were passed a "fresh" connection which should now 78 * try to receive the header, reset buf beforehand 79 */ 80 memset(&c->buf, 0, sizeof(c->buf)); 81 82 c->state = C_RECV_HEADER; 83 /* fallthrough */ 84 case C_RECV_HEADER: 85 /* receive header */ 86 done = 0; 87 if ((s = http_recv_header(c->fd, &c->buf, &done))) { 88 http_prepare_error_response(&c->req, &c->res, s); 89 goto response; 90 } 91 if (!done) { 92 /* not done yet */ 93 return; 94 } 95 96 /* parse header */ 97 if ((s = http_parse_header(c->buf.data, &c->req))) { 98 http_prepare_error_response(&c->req, &c->res, s); 99 goto response; 100 } 101 102 /* prepare response struct */ 103 http_prepare_response(&c->req, &c->res, srv); 104 response: 105 /* generate response header */ 106 if ((s = http_prepare_header_buf(&c->res, &c->buf))) { 107 http_prepare_error_response(&c->req, &c->res, s); 108 if ((s = http_prepare_header_buf(&c->res, &c->buf))) { 109 /* couldn't generate the header, we failed for good */ 110 c->res.status = s; 111 goto err; 112 } 113 } 114 115 c->state = C_SEND_HEADER; 116 /* fallthrough */ 117 case C_SEND_HEADER: 118 if ((s = http_send_buf(c->fd, &c->buf))) { 119 c->res.status = s; 120 goto err; 121 } 122 if (c->buf.len > 0) { 123 /* not done yet */ 124 return; 125 } 126 127 c->state = C_SEND_BODY; 128 /* fallthrough */ 129 case C_SEND_BODY: 130 if (c->req.method == M_GET) { 131 if (c->buf.len == 0) { 132 /* fill buffer with body data */ 133 if ((s = data_fct[c->res.type](&c->res, &c->buf, 134 &c->progress))) { 135 /* too late to do any real error handling */ 136 c->res.status = s; 137 goto err; 138 } 139 140 /* if the buffer remains empty, we are done */ 141 if (c->buf.len == 0) { 142 break; 143 } 144 } else { 145 /* send buffer */ 146 if ((s = http_send_buf(c->fd, &c->buf))) { 147 /* too late to do any real error handling */ 148 c->res.status = s; 149 goto err; 150 } 151 } 152 return; 153 } 154 break; 155 default: 156 warn("serve: invalid connection state"); 157 return; 158 } 159 err: 160 connection_log(c); 161 connection_reset(c); 162 } 163 164 static struct connection * 165 connection_get_drop_candidate(struct connection *connection, size_t nslots) 166 { 167 struct connection *c, *minc; 168 size_t i, j, maxcnt, cnt; 169 170 /* 171 * determine the most-unimportant connection 'minc' of the in-address 172 * with most connections; this algorithm has a complexity of O(n²) 173 * in time but is O(1) in space; there are algorithms with O(n) in 174 * time and space, but this would require memory allocation, 175 * which we avoid. Given the simplicity of the inner loop and 176 * relatively small number of slots per thread, this is fine. 177 */ 178 for (i = 0, minc = NULL, maxcnt = 0; i < nslots; i++) { 179 /* 180 * we determine how many connections have the same 181 * in-address as connection[i], but also minimize over 182 * that set with other criteria, yielding a general 183 * minimizer c. We first set it to connection[i] and 184 * update it, if a better candidate shows up, in the inner 185 * loop 186 */ 187 c = &connection[i]; 188 189 for (j = 0, cnt = 0; j < nslots; j++) { 190 if (!sock_same_addr(&connection[i].ia, 191 &connection[j].ia)) { 192 continue; 193 } 194 cnt++; 195 196 /* minimize over state */ 197 if (connection[j].state < c->state) { 198 c = &connection[j]; 199 } else if (connection[j].state == c->state) { 200 /* minimize over progress */ 201 if (c->state == C_SEND_BODY && 202 connection[i].res.type != c->res.type) { 203 /* 204 * mixed response types; progress 205 * is not comparable 206 * 207 * the res-type-enum is ordered as 208 * DIRLISTING, ERROR, FILE, i.e. 209 * in rising priority, because a 210 * file transfer is most important, 211 * followed by error-messages. 212 * Dirlistings as an "interactive" 213 * feature (that take up lots of 214 * resources) have the lowest 215 * priority 216 */ 217 if (connection[i].res.type < 218 c->res.type) { 219 c = &connection[j]; 220 } 221 } else if (connection[j].progress < 222 c->progress) { 223 /* 224 * for C_SEND_BODY with same response 225 * type, C_RECV_HEADER and C_SEND_BODY 226 * it is sufficient to compare the 227 * raw progress 228 */ 229 c = &connection[j]; 230 } 231 } 232 } 233 234 if (cnt > maxcnt) { 235 /* this run yielded an even greedier in-address */ 236 minc = c; 237 maxcnt = cnt; 238 } 239 } 240 241 return minc; 242 } 243 244 struct connection * 245 connection_accept(int insock, struct connection *connection, size_t nslots) 246 { 247 struct connection *c = NULL; 248 size_t i; 249 250 /* find vacant connection (i.e. one with no fd assigned to it) */ 251 for (i = 0; i < nslots; i++) { 252 if (connection[i].fd == 0) { 253 c = &connection[i]; 254 break; 255 } 256 } 257 if (i == nslots) { 258 /* 259 * all our connection-slots are occupied and the only 260 * way out is to drop another connection, because not 261 * accepting this connection just kicks this can further 262 * down the road (to the next queue_wait()) without 263 * solving anything. 264 * 265 * This may sound bad, but this case can only be hit 266 * either when there's a (D)DoS-attack or a massive 267 * influx of requests. The latter is impossible to solve 268 * at this moment without expanding resources, but the 269 * former has certain characteristics allowing us to 270 * handle this gracefully. 271 * 272 * During an attack (e.g. Slowloris, R-U-Dead-Yet, Slow 273 * Read or just plain flooding) we can not see who is 274 * waiting to be accept()ed. 275 * However, an attacker usually already has many 276 * connections open (while well-behaved clients could 277 * do everything with just one connection using 278 * keep-alive). Inferring a likely attacker-connection 279 * is an educated guess based on which in-address is 280 * occupying the most connection slots. Among those, 281 * connections in early stages (receiving or sending 282 * headers) are preferred over connections in late 283 * stages (sending body). 284 * 285 * This quantitative approach effectively drops malicious 286 * connections while preserving even long-running 287 * benevolent connections like downloads. 288 */ 289 c = connection_get_drop_candidate(connection, nslots); 290 c->res.status = 0; 291 connection_log(c); 292 connection_reset(c); 293 } 294 295 /* accept connection */ 296 if ((c->fd = accept(insock, (struct sockaddr *)&c->ia, 297 &(socklen_t){sizeof(c->ia)})) < 0) { 298 if (errno != EAGAIN && errno != EWOULDBLOCK) { 299 /* 300 * this should not happen, as we received the 301 * event that there are pending connections here 302 */ 303 warn("accept:"); 304 } 305 return NULL; 306 } 307 308 /* set socket to non-blocking mode */ 309 if (sock_set_nonblocking(c->fd)) { 310 /* we can't allow blocking sockets */ 311 return NULL; 312 } 313 314 return c; 315 }