Go Back

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