1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef __gnu_linux__
30 #define _GNU_SOURCE
31 #endif
32
33 #include <unistd.h>
34 #include <stdlib.h>
35
36 #ifdef XP_UNIX
37 #include <sys/uio.h>
38 #include <sys/uio.h>
39 #endif
40
41 #ifdef XP_WIN32
42
43 #endif
44
45 #if defined(
LINUX) || defined(
SOLARIS)
46 #include <sys/sendfile.h>
47 #define WS_SENDFILE
48 #elif defined(
BSD)
49 #if defined(__NetBSD__) || defined(__OpenBSD__)
50 #define net_sys_sendfile net_fallback_sendfile
51 #else
52 #define WS_SENDFILE
53 #endif
54 #endif
55
56 #ifdef WS_SENDFILE
57 #define NET_SYS_SENDFILE net_sys_sendfile
58 #else
59 #define NET_SYS_SENDFILE net_fallback_sendfile
60 #endif
61
62
63
64 #include "../daemon/vfs.h"
65 #include "io.h"
66 #include "pool.h"
67 #include "../daemon/netsite.h"
68 #include "../daemon/event.h"
69 #include "ucx/utils.h"
70
71 IOStream native_io_funcs = {
72 (io_write_f)net_sys_write,
73 (io_writev_f)net_sys_writev,
74 (io_read_f)net_sys_read,
75 (io_sendfile_f)
NET_SYS_SENDFILE,
76 (io_close_f)net_sys_close,
77 NULL,
78 (io_setmode_f)net_sys_setmode,
79 (io_poll_f)net_sys_poll,
80 0
81 };
82
83 IOStream http_io_funcs = {
84 (io_write_f)net_http_write,
85 (io_writev_f)net_http_writev,
86 (io_read_f)net_http_read,
87 (io_sendfile_f)net_http_sendfile,
88 (io_close_f)net_http_close,
89 (io_finish_f)net_http_finish,
90 (io_setmode_f)net_http_setmode,
91 (io_poll_f)net_http_poll,
92 0
93 };
94
95 IOStream ssl_io_funcs = {
96 (io_write_f)net_ssl_write,
97 (io_writev_f)net_ssl_writev,
98 (io_read_f)net_ssl_read,
99 NULL,
100 (io_close_f)net_ssl_close,
101 (io_finish_f)net_ssl_finish,
102 (io_setmode_f)net_ssl_setmode,
103 (io_poll_f)net_ssl_poll,
104 0
105 };
106
107
108
109
110
111
112 IOStream* sysstream_new(
pool_handle_t *pool,
SYS_SOCKET fd) {
113 SysStream *st = pool_malloc(pool,
sizeof(SysStream));
114 st->st = native_io_funcs;
115 st->fd = fd;
116 return (IOStream*)st;
117 }
118
119 #ifdef XP_UNIX
120 ssize_t net_sys_write(SysStream *st,
void *buf,
size_t nbytes) {
121 return write(st->fd, buf, nbytes);
122 }
123
124 ssize_t net_sys_writev(SysStream *st,
struct iovec *iovec,
int iovcnt) {
125 return writev(st->fd, iovec, iovcnt);
126 }
127
128 ssize_t net_sys_read(SysStream *st,
void *buf,
size_t nbytes) {
129 return read(st->fd, buf, nbytes);
130 }
131
132 #ifdef WS_SENDFILE
133 ssize_t net_sys_sendfile(SysStream *st, sendfiledata *sfd) {
134 ssize_t ret =
0;
135 off_t fileoffset = sfd->offset;
136 if(sfd->fd->fd != -
1) {
137 #ifdef BSD
138 struct iovec hdvec;
139 hdvec.iov_base = (
void*)sfd->header;
140 hdvec.iov_len = sfd->hlen;
141 struct iovec trvec;
142 trvec.iov_base = (
void*)sfd->trailer;
143 trvec.iov_len = sfd->tlen;
144 struct sf_hdtr hdtr;
145 hdtr.headers = &hdvec;
146 hdtr.hdr_cnt =
1;
147 hdtr.trailers = &trvec;
148 hdtr.trl_cnt =
1;
149
150 off_t len = sfd->len;
151 #ifdef OSX
152 ret = sendfile(sfd->fd->fd, st->fd, fileoffset, &len, &hdtr,
0);
153 #else
154 ret = sendfile(
155 sfd->fd->fd,
156 st->fd,
157 fileoffset,
158 sfd->len,
159 &hdtr,
160 NULL,
161 0);
162 #endif
163 #else
164 if(sfd->header) {
165 ret += write(st->fd, sfd->header, sfd->hlen);
166 }
167 ret += sendfile(st->fd, sfd->fd->fd, &fileoffset, sfd->len);
168 if(sfd->trailer) {
169 ret += write(st->fd, sfd->trailer, sfd->tlen);
170 }
171 #endif
172 }
else {
173 return net_fallback_sendfile((IOStream*)st, sfd);
174 }
175
176 return ret;
177 }
178 #endif
179
180 void net_sys_close(SysStream *st) {
181 system_close(st->fd);
182 }
183
184 void net_sys_setmode(SysStream *st,
int mode) {
185 int flags;
186 if (-
1 == (flags = fcntl(st->fd,
F_GETFL,
0))) {
187 flags =
0;
188 }
189 if(mode ==
IO_MODE_BLOCKING) {
190 if (fcntl(st->fd,
F_SETFL, flags & ~
O_NONBLOCK) !=
0) {
191 perror(
"fcntl");
192
193 }
194 }
else if(mode ==
IO_MODE_NONBLOCKING) {
195 if (fcntl(st->fd,
F_SETFL, flags |
O_NONBLOCK) !=
0) {
196 perror(
"fcntl");
197
198 }
199 }
200 }
201
202 int net_sys_poll(SysStream *st, EventHandler *ev,
int events, Event *cb) {
203 switch(events) {
204 default:
return -
1;
205 case IO_POLL_NONE:
return ev_remove_poll(ev, st->fd);
206 case IO_POLL_IN:
return ev_pollin(ev, st->fd, cb);
207 case IO_POLL_OUT:
return ev_pollout(ev, st->fd, cb);
208 case IO_POLL_IN |
IO_POLL_OUT:
return -
1;
209 }
210 }
211
212 #elif defined(
XP_WIN32)
213
214 ssize_t net_sys_write(SysStream *st,
void *buf,
size_t nbytes) {
215 int ret = send(st->fd, buf, nbytes,
0);
216 if(ret ==
SOCKET_ERROR) {
217 return IO_ERROR;
218 }
219 return ret;
220 }
221
222 ssize_t net_sys_writev(SysStream *st,
struct iovec *iovec,
int iovcnt) {
223
224 }
225
226 ssize_t net_sys_read(SysStream *st,
void *buf,
size_t nbytes) {
227 int ret = recv(st->fd, buf, nbytes,
0);
228 if(ret ==
SOCKET_ERROR) {
229 return IO_ERROR;
230 }
231 return ret;
232 }
233
234 ssize_t net_sys_sendfile(SysStream *st, sendfiledata *sfd) {
235
236 }
237
238 void net_sys_close(SysStream *st) {
239 closesocket(st->fd);
240 }
241
242 #endif
243
244
245
246
247
248
249 IOStream* httpstream_new(
pool_handle_t *pool, IOStream *fd) {
250 HttpStream *st = pool_malloc(pool,
sizeof(HttpStream));
251 st->st = http_io_funcs;
252 st->fd = fd;
253 st->max_read =
0;
254 st->read =
0;
255 st->chunked_enc =
WS_FALSE;
256 st->buffered =
WS_FALSE;
257 return (IOStream*)st;
258 }
259
260 ssize_t net_http_write(HttpStream *st,
void *buf,
size_t nbytes) {
261 IOStream *fd = st->fd;
262 if(st->chunked_enc) {
263
264 struct iovec io[
3];
265 char chunk_len[
16];
266 io[
0].iov_base = chunk_len;
267 io[
0].iov_len = snprintf(chunk_len,
16,
"%zx\r\n", nbytes);
268 io[
1].iov_base = buf;
269 io[
1].iov_len = nbytes;
270 io[
2].iov_base =
"\r\n";
271 io[
2].iov_len =
2;
272 ssize_t r = fd->writev(fd, io,
3);
273 return r - io[
0].iov_len;
274 }
else {
275 return fd->write(fd, buf, nbytes);
276 }
277 }
278
279 ssize_t net_http_writev(HttpStream *st,
struct iovec *iovec,
int iovcnt) {
280 IOStream *fd = st->fd;
281 if(st->chunked_enc) {
282 struct iovec *io = calloc(iovcnt +
1,
sizeof(
struct iovec));
283 char chunk_len[
16];
284 io[
0].iov_base = chunk_len;
285 size_t len =
0;
286 for(
int i=
0;i<iovcnt;i++) {
287 len += iovec[i].iov_len;
288 }
289 io[
0].iov_len = snprintf(chunk_len,
16,
"\r\n%zx\r\n", len);
290 memcpy(io +
1, iovec, iovcnt *
sizeof(
struct iovec));
291 ssize_t r = fd->writev(fd, io, iovcnt +
1);
292 return r - io[
0].iov_len;
293 }
else {
294 return fd->writev(fd, iovec, iovcnt);
295 }
296 }
297
298 ssize_t net_http_read(HttpStream *st,
void *buf,
size_t nbytes) {
299 if(st->max_read !=
0 && st->read >= st->max_read) {
300 return 0;
301 }
302 ssize_t r = st->fd->read(st->fd, buf, nbytes);
303 st->read += r;
304 return r;
305 }
306
307 ssize_t net_http_sendfile(HttpStream *st, sendfiledata *sfd) {
308 ssize_t ret =
0;
309
310 if(st->fd->sendfile) {
311 ret = st->fd->sendfile(st->fd, sfd);
312 }
else {
313 ret = net_fallback_sendfile((IOStream*)st, sfd);
314 }
315
316 return ret;
317 }
318
319 void net_http_close(HttpStream *st) {
320 st->fd->close(st->fd);
321 }
322
323 void net_http_finish(HttpStream *st) {
324 if(st->chunked_enc) {
325 st->fd->write(st->fd,
"0\r\n\r\n",
5);
326 }
327 }
328
329 void net_http_setmode(HttpStream *st,
int mode) {
330 st->fd->setmode(st->fd, mode);
331 }
332
333 int net_http_poll(HttpStream *st, EventHandler *ev,
int events, Event *cb) {
334 return st->fd->poll(st->fd, ev, events, cb);
335 }
336
337
338
339
340
341
342 IOStream* sslstream_new(
pool_handle_t *pool,
SSL *ssl) {
343 SSLStream *st = pool_malloc(pool,
sizeof(SSLStream));
344 st->st = ssl_io_funcs;
345 st->ssl = ssl;
346 st->error =
0;
347 return (IOStream*)st;
348 }
349
350 ssize_t net_ssl_write(SSLStream *st,
void *buf,
size_t nbytes) {
351 int ret = SSL_write(st->ssl, buf, nbytes);
352 if(ret <=
0) {
353 st->error = SSL_get_error(st->ssl, ret);
354 }
355 return ret;
356 }
357
358 ssize_t net_ssl_writev(SSLStream *st,
struct iovec *iovec,
int iovcnt) {
359 ssize_t r =
0;
360 for(
int i=
0;i<iovcnt;i++) {
361 int ret = SSL_write(st->ssl, iovec[i].iov_base, iovec[i].iov_len);
362 if(ret <=
0) {
363 st->error = SSL_get_error(st->ssl, ret);
364 return 0;
365 }
366 r += ret;
367 }
368 return r;
369 }
370
371 ssize_t net_ssl_read(SSLStream *st,
void *buf,
size_t nbytes) {
372 int ret = SSL_read(st->ssl, buf, nbytes);
373 if(ret <=
0) {
374 st->error = SSL_get_error(st->ssl, ret);
375 }
376 return ret;
377 }
378
379 void net_ssl_close(SSLStream *st) {
380 int ret = SSL_shutdown(st->ssl);
381 if(ret !=
1) {
382 st->error = SSL_get_error(st->ssl, ret);
383 }
384 system_close(SSL_get_fd(st->ssl));
385 }
386
387 void net_ssl_finish(SSLStream *st) {
388
389 }
390
391 void net_ssl_setmode(SSLStream *st,
int mode) {
392 int flags;
393 if (-
1 == (flags = fcntl(SSL_get_fd(st->ssl),
F_GETFL,
0))) {
394 flags =
0;
395 }
396 if(mode ==
IO_MODE_BLOCKING) {
397 if (fcntl(SSL_get_fd(st->ssl),
F_SETFL, flags & ~
O_NONBLOCK) !=
0) {
398 perror(
"fcntl");
399
400 }
401 }
else if(mode ==
IO_MODE_NONBLOCKING) {
402 if (fcntl(SSL_get_fd(st->ssl),
F_SETFL, flags |
O_NONBLOCK) !=
0) {
403 perror(
"fcntl");
404
405 }
406 }
407 }
408
409 int net_ssl_poll(SSLStream *st, EventHandler *ev,
int events, Event *cb) {
410 int fd = SSL_get_fd(st->ssl);
411 switch(events) {
412 default:
return -
1;
413 case IO_POLL_NONE:
return ev_remove_poll(ev, fd);
414 case IO_POLL_IN:
return ev_pollin(ev, fd, cb);
415 case IO_POLL_OUT:
return ev_pollout(ev, fd, cb);
416 case IO_POLL_IN |
IO_POLL_OUT:
return -
1;
417 }
418 }
419
420
421
422 ssize_t net_read(
SYS_NETFD fd,
void *buf,
size_t nbytes) {
423 ssize_t r = ((IOStream*)fd)->read(fd, buf, nbytes);
424 if(r ==
0) {
425 return IO_EOF;
426 }
else if(r <
0) {
427 ((IOStream*)fd)->io_errno = errno;
428 return IO_ERROR;
429 }
430 return r;
431 }
432
433 ssize_t net_write(
SYS_NETFD fd,
void *buf,
size_t nbytes) {
434 ssize_t r = ((IOStream*)fd)->write(fd, buf, nbytes);
435 if(r <
0) {
436 ((IOStream*)fd)->io_errno = errno;
437 return IO_ERROR;
438 }
439 return r;
440 }
441
442 ssize_t net_writev(
SYS_NETFD fd,
struct iovec *iovec,
int iovcnt) {
443 ssize_t r = ((IOStream*)fd)->writev(fd, iovec, iovcnt);
444 if(r <
0) {
445 ((IOStream*)fd)->io_errno = errno;
446 return IO_ERROR;
447 }
448 return r;
449 }
450
451 ssize_t net_printf(
SYS_NETFD fd,
char *format, ...) {
452 va_list arg;
453 va_start(arg, format);
454 sstr_t buf = ucx_vasprintf(ucx_default_allocator(), format, arg);
455 ssize_t r = net_write(fd, buf.ptr, buf.length);
456 free(buf.ptr);
457 va_end(arg);
458 if(r <
0) {
459 ((IOStream*)fd)->io_errno = errno;
460 }
461 return r;
462 }
463
464 ssize_t net_sendfile(
SYS_NETFD fd, sendfiledata *sfd) {
465 IOStream *out = fd;
466 if(out->sendfile && sfd->fd && sfd->fd->fd != -
1) {
467 ssize_t r = out->sendfile(fd, sfd);
468 if(r <
0) {
469 out->io_errno = errno;
470 return IO_ERROR;
471 }
472 return r;
473 }
else {
474
475
476 return net_fallback_sendfile(out, sfd);
477 }
478 }
479
480
481 ssize_t net_fallback_sendfile(IOStream *fd, sendfiledata *sfd) {
482 char *buf = malloc(
4096);
483 if(!buf) {
484
485 return IO_ERROR;
486 }
487 char *header = (
char*)sfd->header;
488 int hlen = sfd->hlen;
489 char *trailer = (
char*)sfd->trailer;
490 int tlen = sfd->tlen;
491 if(header ==
NULL) {
492 hlen =
0;
493 }
494 if(trailer ==
NULL) {
495 tlen =
0;
496 }
497
498 ssize_t r;
499 while(hlen >
0) {
500 r = fd->write(fd, header, hlen);
501 header += r;
502 hlen -= r;
503 if(r <=
0) {
504 free(buf);
505 fd->io_errno = errno;
506 return IO_ERROR;
507 }
508 }
509
510 if(system_lseek(sfd->fd, sfd->offset,
SEEK_SET) == -
1) {
511 free(buf);
512 fd->io_errno = errno;
513 return IO_ERROR;
514 }
515
516 size_t length = sfd->len;
517 while(length >
0) {
518
519 if(length > sfd->len) {
520 log_ereport(
LOG_WARN,
"net_fallback_sendfile: length > sfd->len: %zu > %zu", length, sfd->len);
521 free(buf);
522 return IO_ERROR;
523 }
524
525 if((r = system_fread(sfd->fd, buf,
4096)) <=
0) {
526 break;
527 }
528 char *write_buf = buf;
529 while(r >
0) {
530 ssize_t w = fd->write(fd, write_buf, r);
531
532 if(w > r) {
533 log_ereport(
LOG_WARN,
"net_fallback_sendfile: w > r, %zd > %zd", w, r);
534 w =
0;
535 }
536
537 if(w <=
0) {
538 free(buf);
539 fd->io_errno = errno;
540 return IO_ERROR;
541 }
542 r -= w;
543 length -= w;
544 write_buf += w;
545 }
546 }
547 free(buf);
548 if(length >
0) {
549 fd->io_errno = errno;
550 return IO_ERROR;
551 }
552
553 while(tlen >
0) {
554 r = fd->write(fd, trailer, tlen);
555 trailer += r;
556 tlen -= r;
557 if(r <=
0) {
558 fd->io_errno = errno;
559 return IO_ERROR;
560 }
561 }
562
563 return sfd->hlen + sfd->len + sfd->tlen;
564 }
565
566 int net_flush(
SYS_NETFD sd) {
567
568 return 0;
569 }
570
571 void net_close(
SYS_NETFD fd) {
572 ((IOStream*)fd)->close(fd);
573 }
574
575 int net_setnonblock(
SYS_NETFD fd,
int nonblock) {
576 ((IOStream*)fd)->setmode(
577 fd,
578 nonblock ?
IO_MODE_NONBLOCKING :
IO_MODE_BLOCKING);
579 return 0;
580 }
581
582 int net_errno(
SYS_NETFD fd) {
583 return ((IOStream*)fd)->io_errno;
584 }
585
586
587 void net_finish(
SYS_NETFD fd) {
588 ((IOStream*)fd)->finish(fd);
589 }
590