0 /* See LICENSE for license details. */
1 #ifdef __FreeBSD__
2 #define __BSD_VISIBLE 1
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <sys/uio.h>
6 #endif
7 #include "server.h"
8 #include "parser.h"
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <sys/types.h>
14 #include <time.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <poll.h>
19 #ifdef __sun
20 #include <signal.h>
21 #endif
22 #define _GNU_SOURCE
23 size_t strlcpy(char*, const char*, size_t);
24
25 #ifdef QRCODE
26 #define HOST "http://localhost"
27 #endif
28
29 char header[] =
30 "HTTP/1.0 200 OK\r\n"
31 "Connection: close\r\n"
32 "Content-Length: %d\r\n"
33 "Content-Type: %s\r\n"
34 "Server: uploadservice\r\n\r\n";
35
36 void
37 print_now()
38 {
39 time_t now = time(NULL);
40 struct tm tm = *localtime(&now);
41 printf("[%d/%02d/%02d %02d:%02d:%02d] ",
42 tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday,
43 tm.tm_hour, tm.tm_min, tm.tm_sec);
44 }
45
46 int listener = 0;
47
48 #include <sys/stat.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51
52 char data_error[] =
53 "<!DOCTYPE html>\n"
54 "<html>\n"
55 "<head>\n"
56 " <title>Fatal error</title>\n"
57 "</head>\n"
58 "<body>\n"
59 " <h1>An error occured</h1>\n"
60 "</body>\n"
61 "</html>\n";
62
63 char data_upload[] =
64 "<!DOCTYPE html>\n"
65 "<html>\n"
66 "<head>\n"
67 " <title>File uploaded</title>\n"
68 "</head>\n"
69 "<body>\n"
70 " <a href=\"/\">Go back</a>\n"
71 " <h1>File succesfully uploaded</h1>\n"
72 " <p>Download link : <a href=\"%s\">%s</a></p>\n"
73 #ifdef QRCODE
74 " <div id=\"qrcode\" style=\"width: 256px; border: 5px solid green;\"></div>\n"
75 " <script src=\"/js/qrcode.min.js\"></script>\n"
76 " <script type=\"text/javascript\">\n"
77 " new QRCode(document.getElementById(\"qrcode\"), \""HOST"%s\");\n"
78 " </script>"
79 #endif
80 "</body>\n"
81 "</html>\n";
82
83 int
84 path_to_url(const char* path, char* url, int len)
85 {
86 int j = 0;
87 int i = 0;
88 for (; path[i] && j < len; i++) {
89 char c = path[i];
90 if ((c >= 'a' && c <= 'z') ||
91 (c >= 'A' && c <= 'Z') ||
92 (c >= '0' && c <= '9') ||
93 c == '.' || c == '/' || c == '_') {
94 url[j] = path[i];
95 j++;
96 continue;
97 }
98 snprintf(&url[j], len - j, "%%%02X", c);
99 j += 3;
100 }
101 url[j] = '\0';
102 return j;
103 }
104
105 int
106 server_upload(struct http_request* req)
107 {
108 char file_name[256], path[1024], url[2048];
109 char *start, *name_ptr, *slash_ptr;
110 int name_fail, fd, len;
111
112 /* path + name */
113 start = strstr(req->packet, "\r\n\r\n");
114 if (!start) start = req->packet;
115 name_ptr = strstr(start, "filename=\"");
116 name_fail = 1;
117 if (name_ptr) {
118 char* name_end;
119
120 name_ptr += sizeof("filename=\"") - 1;
121 name_end = strstr(name_ptr, "\"\r\n");
122 if (name_end && (size_t)(name_end - name_ptr) <
123 sizeof(file_name)) {
124 strlcpy(file_name, name_ptr, name_end - name_ptr + 1);
125 name_fail = 0;
126 }
127 }
128 if (name_fail)
129 strlcpy(file_name, "generic.dat", sizeof(file_name));
130 snprintf(path, sizeof(path), "/download/%08X%08X/%s",
131 (unsigned)(rand() * rand() + rand()),
132 (unsigned)(rand() * rand() - rand()), file_name);
133
134 start = strstr(start+4, "\r\n\r\n");
135 if (!start) start = req->content;
136 slash_ptr = strrchr(path, '/');
137 if (!slash_ptr) return -1;
138 *slash_ptr = '\0';
139 mkdir(&path[1], 0700);
140 *slash_ptr = '/';
141 fd = open((char*)&path[1], O_RDWR|O_CREAT, 0600);
142 if (fd < 0)
143 return -1;
144 req->data = fd;
145 path_to_url(path, url, sizeof(url));
146 len = snprintf(req->updata, sizeof(req->updata),
147 #ifdef QRCODE
148 data_upload, url, file_name, url);
149 #else
150 data_upload, url, file_name);
151 #endif
152 snprintf(req->header, sizeof(req->header), header, len, "text/html");
153 http_parse(req);
154 return 0;
155 }
156
157 int
158 server_init(int port)
159 {
160 #ifdef DEBUG
161 struct linger sl;
162 #endif
163 struct sockaddr_in addr;
164 listener = socket(AF_INET, SOCK_STREAM, 0);
165 if (listener == -1) {
166 printf("Failed to create socket\n");
167 return -1;
168 }
169 #ifdef DEBUG
170 /* instant reset, useful for testing */
171 sl.l_onoff = 1;
172 sl.l_linger = 0;
173 setsockopt(listener, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
174 #endif
175 #ifdef __sun
176 signal(SIGPIPE, SIG_IGN);
177 #endif
178
179 memset(&addr, 0, sizeof(addr));
180 addr.sin_family = AF_INET;
181 addr.sin_addr.s_addr = htonl(INADDR_ANY);
182 addr.sin_port = htons(port);
183 if (bind(listener, (struct sockaddr*)&addr, sizeof(addr))) {
184 printf("Failed to bind socket on port %d\n", port);
185 return -1;
186 }
187 if (listen(listener, 5)) {
188 printf("Failed to listen on port %d\n", port);
189 return -1;
190 }
191 print_now();
192 printf("Listening on port %d\n", port);
193 fflush(stdout); /* to print log in sfm on illumos */
194 return 0;
195 }
196
197 int
198 server_accept(struct http_request* req)
199 {
200 unsigned int len;
201 int socket;
202
203 memset(req, 0, sizeof(struct http_request));
204 req->data = -1;
205 len = sizeof(req->addr);
206 socket = accept(listener, (struct sockaddr*)&req->addr, &len);
207 if (socket == -1) {
208 printf("Failed to accept socket\n");
209 return -1;
210 }
211 req->socket = socket;
212 return 0;
213 }
214
215 int
216 server_recv(struct http_request* req)
217 {
218 char *data_ptr, *end;
219 int bytes, blen;
220
221 bytes = recv(req->socket,
222 (req->data > -1) ? req->packet : &req->packet[req->size],
223 (req->data > -1) ? sizeof(req->packet):
224 (sizeof(req->packet) - req->size), 0);
225 if (bytes <= 0) return -1;
226 if (!req->boundary_found) {
227 char* ptr = strstr(&req->packet[req->size], "boundary=");
228 if (ptr) {
229 char* start = ptr + sizeof("boundary=");
230 ptr = start;
231 while (ptr++ && *ptr != '\r');
232 strlcpy(req->boundary, start, ptr - start);
233 req->boundary_found = 1;
234 }
235 }
236 req->size += bytes;
237 data_ptr = req->packet;
238 end = NULL;
239 blen = 0;
240 if (req->boundary_found)
241 blen = strnlen(req->boundary, sizeof(req->boundary));
242 while (req->data < 0 && req->boundary_found) {
243 char* ptr = strstr(req->packet, req->boundary);
244 if (!ptr) break;
245 ptr = strstr(ptr + blen, req->boundary);
246 if (!ptr) break;
247 req->content = ptr + strnlen(req->boundary,
248 sizeof(req->boundary));
249 req->length = req->size - (req->content - req->packet);
250 server_upload(req);
251 end = strstr(req->packet + req->size - blen - 8,
252 req->boundary);
253 data_ptr = strstr(req->content + 4, "\r\n\r\n") + 4;
254 bytes = req->size - (data_ptr - req->packet);
255 break;
256 }
257 if (req->data > -1) {
258 char packet[4096];
259 size_t size;
260 if (!end && data_ptr == req->packet)
261 end = strstr(data_ptr + bytes - blen - 8,
262 req->boundary);
263 write(req->data, data_ptr,
264 end?(end - data_ptr - 4):bytes);
265 if (!end) return 1;
266 size = snprintf(packet, sizeof(packet), "%s%s",
267 req->header, req->updata);
268 bytes = 0;
269 while ((size_t)bytes < size) {
270 int ret = send(req->socket, &packet[bytes],
271 size - bytes, 0);
272 if (ret <= 0) break;
273 bytes += ret;
274 }
275 return 2;
276 }
277 if (!req->boundary_found &&
278 req->packet[req->size - 1] == '\n' &&
279 req->packet[req->size - 2] == '\r' &&
280 req->packet[req->size - 3] == '\n' &&
281 req->packet[req->size - 4] == '\r') {
282 return 0;
283 }
284 return 1;
285 }
286
287 #define MAX_REQUESTS 1024
288 #define TIMEOUT_SINCE_STARTED 1200000
289 #define TIMEOUT_SINCE_LAST 10000
290 struct http_request requests[MAX_REQUESTS];
291 struct pollfd fds[MAX_REQUESTS];
292 size_t requests_count = 0;
293
294 int
295 new_request()
296 {
297 int new = 1;
298 size_t i = 0;
299 time_t now = time(NULL);
300 for (; i < requests_count; i++) {
301 if (requests[i].done ||
302 now - requests[i].started >= TIMEOUT_SINCE_STARTED ||
303 now - requests[i].last >= TIMEOUT_SINCE_LAST) {
304 new = 0;
305 break;
306 }
307 }
308 if (new && i >= sizeof(requests)/sizeof(struct http_request) - 1)
309 return -1;
310 if (server_accept(&requests[i]))
311 return -1;
312 fds[i + 1].fd = requests[i].socket;
313 fds[i + 1].events = POLLIN;
314 requests[i].last = requests[i].started = time(NULL);
315 if (new)
316 requests_count++;
317 return 0;
318 }
319
320 void
321 print_req(struct http_request* req, int code)
322 {
323 uint8_t *ptr;
324 print_now();
325 ptr = (uint8_t*)&req->addr.sin_addr.s_addr;
326 printf("%d.%d.%d.%d, requested [%d]\n",
327 ptr[0], ptr[1], ptr[2], ptr[3], code);
328 fflush(stdout); /* to print log in sfm on illumos */
329 }
330
331 int
332 server_serve(struct http_request* req)
333 {
334 char packet[4096];
335 size_t l;
336
337 memset(packet, 0, sizeof(packet));
338 l = snprintf(packet, sizeof(packet),
339 header, sizeof(data_error) - 1, "text/html");
340 if (l >= sizeof(packet)) {
341 printf("packet buffer overflowing");
342 return -1;
343 }
344 l += strlcpy(&packet[l], data_error, sizeof(packet) - l);
345 send(req->socket, packet, l + 1, 0);
346 return 404;
347 }
348
349 int
350 server_thread()
351 {
352 size_t i;
353 memset(requests, 0, sizeof(requests));
354 for (i = 1; i < sizeof(fds)/sizeof(struct pollfd); i++) {
355 fds[i].fd = -1;
356 fds[i].events = POLLIN;
357 }
358 fds[0].fd = listener;
359 fds[0].events = POLLIN;
360 while (1) {
361 int nfds, ready;
362 size_t i;
363
364 nfds = requests_count + 1;
365 ready = poll(fds, nfds, -1);
366 if (ready == -1) break;
367 if (fds[0].revents == POLLIN && new_request()) {
368 print_now();
369 printf("Failed to accept client\n");
370 fflush(stdout);
371 }
372 for (i = 0; i < requests_count; i++) {
373 int ret = 0;
374 struct http_request* req = &requests[i];
375 switch (fds[i + 1].revents) {
376 case 0:
377 break;
378 case POLLOUT:
379 goto clean;
380 case POLLIN:
381 requests[i].last = time(NULL);
382 ret = server_recv(req);
383 if (ret == 1) continue;
384 if (ret == 2) print_req(req, 200);
385 if (ret == 0) {
386 if (req->data > -1) {
387 close(req->data);
388 req->data = -1;
389 }
390 http_parse(req);
391 print_req(req, server_serve(req));
392 if (req->data > -1) {
393 fds[i + 1].events = POLLOUT;
394 break;
395 }
396 }
397 clean:
398 if (req->data > -1) {
399 close(req->data);
400 req->data = -1;
401 }
402
403 close(req->socket);
404 req->socket = -1;
405 req->done = 1;
406 if (i + 1 == requests_count)
407 requests_count--;
408 memset(&fds[i + 1], 0, sizeof(struct pollfd));
409 fds[i + 1].fd = -1;
410 fds[i + 1].events = POLLIN;
411 break;
412 default:
413 fds[i + 1].fd = -1;
414 fds[i + 1].events = POLLIN;
415 }
416 }
417 }
418 return 0;
419 }
420
421 int
422 server_stop()
423 {
424 close(listener);
425 return 0;
426 }
427