File cnx.c changed (mode: 100644) (index 2ffd4ee..0d29b96) |
... |
... |
static bool body_part_header(struct thread_local_storage *tls) |
1393 |
1393 |
} |
} |
1394 |
1394 |
return true; |
return true; |
1395 |
1395 |
} |
} |
1396 |
|
/* |
|
1397 |
|
* We emulate sendfile because it will _NOT_ function properly on our old kernel, we reuse the http message memory, cannot |
|
1398 |
|
* sendfile 0 bytes |
|
1399 |
|
*/ |
|
1400 |
|
static sl sendfile_emulation(struct thread_local_storage *tls, si out_fd, si in_fd, u64 off /* ignored */, u64 bytes_n) |
|
1401 |
|
{ |
|
1402 |
|
/* we first cap the amount of bytes */ |
|
1403 |
|
if (bytes_n > (THREAD_LOCAL_STORAGE_BYTES_N - TLS_HTTP_MESSAGE)) |
|
1404 |
|
bytes_n = THREAD_LOCAL_STORAGE_BYTES_N - TLS_HTTP_MESSAGE; |
|
1405 |
|
/* only one read */ |
|
1406 |
|
u64 remaining_bytes_n = bytes_n; |
|
1407 |
|
sl r; |
|
1408 |
|
loop { |
|
1409 |
|
r = read(in_fd, (u8*)tls + TLS_HTTP_MESSAGE, bytes_n); |
|
1410 |
|
if (r != -EINTR) |
|
1411 |
|
break; |
|
1412 |
|
} |
|
1413 |
|
if (ISERR(r) || r == 0) |
|
1414 |
|
return r; |
|
1415 |
|
/* write */ |
|
1416 |
|
u64 read_bytes_n = (u64)r; |
|
1417 |
|
u64 remaining_bytes_n_to_write = read_bytes_n; |
|
1418 |
|
u8 *next_write = (u8*)tls + TLS_HTTP_MESSAGE; |
|
1419 |
|
loop { /* short write */ |
|
1420 |
|
loop { |
|
1421 |
|
r = write(out_fd, next_write, remaining_bytes_n_to_write); |
|
1422 |
|
if (r != -EINTR) |
|
1423 |
|
break; |
|
1424 |
|
} |
|
1425 |
|
if (ISERR(r) || r == 0) |
|
1426 |
|
return r; |
|
1427 |
|
remaining_bytes_n_to_write -= (u64)r; |
|
1428 |
|
if (remaining_bytes_n_to_write == 0) |
|
1429 |
|
return (sl)read_bytes_n; |
|
1430 |
|
next_write += (u64)r; |
|
1431 |
|
} |
|
1432 |
|
/* unreachable */ |
|
1433 |
|
} |
|
1434 |
1396 |
/* access to the index file should be "synchronized" as much as possible BEFORE this call occurs */ |
/* access to the index file should be "synchronized" as much as possible BEFORE this call occurs */ |
1435 |
1397 |
static bool index_grow(u64 additional_bytes_n) |
static bool index_grow(u64 additional_bytes_n) |
1436 |
1398 |
{ |
{ |
|
... |
... |
static void file_receive(struct thread_local_storage *tls) |
1553 |
1515 |
next_write += (u64)r; |
next_write += (u64)r; |
1554 |
1516 |
} |
} |
1555 |
1517 |
/*-------------------------------------------------------------------------------------------------------------------*/ |
/*-------------------------------------------------------------------------------------------------------------------*/ |
1556 |
|
/* XXX: should be sendfile here, but our kernel is too old, in_fd cannot be a socket, yet */ |
|
1557 |
|
/* now sendfile the rest of the file, with its body trailer (which we will truncate after), if we have any though */ |
|
1558 |
|
/* |
|
1559 |
|
* XXX: BIG FAT WARNING: UPON MOVING TO THE REAL SENDFILE SYSCALL DON'T FORGET THE MAXIMUM AMOUNT OF BYTES ALLOWED |
|
1560 |
|
* IS 0x7ffff000 (S32_MAX - one 4KiB page) |
|
1561 |
|
*/ |
|
1562 |
1518 |
remaining_body_bytes_n -= file_with_body_trailer_already_read_bytes_n; |
remaining_body_bytes_n -= file_with_body_trailer_already_read_bytes_n; |
1563 |
1519 |
loop { /* short send file */ |
loop { /* short send file */ |
1564 |
|
if (remaining_body_bytes_n == 0) /* done, we need to truncate the body trailer */ |
|
|
1520 |
|
if (remaining_body_bytes_n == 0) /* done, now we need to truncate the body trailer */ |
1565 |
1521 |
break; |
break; |
1566 |
1522 |
loop { |
loop { |
1567 |
|
r = sendfile_emulation(tls, fd, tls->cnx, 0, remaining_body_bytes_n); |
|
|
1523 |
|
r = sendfile(fd, tls->cnx, 0, remaining_body_bytes_n); |
1568 |
1524 |
if (r != -EINTR) |
if (r != -EINTR) |
1569 |
1525 |
break; |
break; |
1570 |
1526 |
} |
} |
|
... |
... |
static void file_send(struct thread_local_storage *tls) |
2005 |
1961 |
/* now, sendfile the file itself, if it is not an HTTP_METHOD_HEAD enquiry (probably for sane storage allocation) */ |
/* now, sendfile the file itself, if it is not an HTTP_METHOD_HEAD enquiry (probably for sane storage allocation) */ |
2006 |
1962 |
if (tls->request.line.method.value != HTTP_METHOD_HEAD) { |
if (tls->request.line.method.value != HTTP_METHOD_HEAD) { |
2007 |
1963 |
u64 remaining_bytes_n_to_sendfile = (u64)(fd_statx.size); |
u64 remaining_bytes_n_to_sendfile = (u64)(fd_statx.size); |
2008 |
|
/* XXX: linux has a max: 0x7ffff000 (S32_MAX - one 4KiB page), even in 64bits */ |
|
2009 |
|
#define LINUX_SENDFILE_BYTES_N_MAX 0x7ffff000 |
|
2010 |
1964 |
loop { /* short sendfile */ |
loop { /* short sendfile */ |
2011 |
1965 |
if (remaining_bytes_n_to_sendfile == 0) { /* never send 0 bytes since this is a end-of-connection marker */ |
if (remaining_bytes_n_to_sendfile == 0) { /* never send 0 bytes since this is a end-of-connection marker */ |
2012 |
1966 |
close(fd); |
close(fd); |
2013 |
1967 |
return; |
return; |
2014 |
1968 |
} |
} |
2015 |
|
u64 bytes_n_to_sendfile; |
|
2016 |
|
if (remaining_bytes_n_to_sendfile > bytes_n_to_sendfile) |
|
2017 |
|
bytes_n_to_sendfile = LINUX_SENDFILE_BYTES_N_MAX; /* do cap */ |
|
2018 |
1969 |
loop { |
loop { |
2019 |
|
r = sendfile(tls->cnx, fd, 0, bytes_n_to_sendfile); |
|
|
1970 |
|
r = sendfile(tls->cnx, fd, 0, remaining_bytes_n_to_sendfile); |
2020 |
1971 |
if (r != -EINTR) |
if (r != -EINTR) |
2021 |
1972 |
break; |
break; |
2022 |
1973 |
} |
} |
|
... |
... |
static void file_send(struct thread_local_storage *tls) |
2026 |
1977 |
} |
} |
2027 |
1978 |
remaining_bytes_n_to_sendfile -= (u64)r; |
remaining_bytes_n_to_sendfile -= (u64)r; |
2028 |
1979 |
} |
} |
2029 |
|
#undef LINUX_SENDFILE_BYTES_N_MAX |
|
2030 |
1980 |
} |
} |
2031 |
1981 |
/* unreachable */ |
/* unreachable */ |
2032 |
1982 |
} |
} |
|
... |
... |
static void new(si cnx, struct sockaddr_in6 *peer) |
2117 |
2067 |
{ |
{ |
2118 |
2068 |
sl r; |
sl r; |
2119 |
2069 |
void *thread_stack_bottom; |
void *thread_stack_bottom; |
2120 |
|
void *thread_stack_top; |
|
2121 |
2070 |
struct thread_local_storage *tls; /* we don't use the thread stack, and we use it to pass init data to the thread */ |
struct thread_local_storage *tls; /* we don't use the thread stack, and we use it to pass init data to the thread */ |
|
2071 |
|
struct clone_args args; |
2122 |
2072 |
/*-------------------------------------------------------------------------------------------------------------------*/ |
/*-------------------------------------------------------------------------------------------------------------------*/ |
2123 |
2073 |
|
|
2124 |
2074 |
// XXX: here we should do peer filtering (IPv6 or fixed IPv4) |
// XXX: here we should do peer filtering (IPv6 or fixed IPv4) |
|
... |
... |
static void new(si cnx, struct sockaddr_in6 *peer) |
2130 |
2080 |
goto err_close_cnx; |
goto err_close_cnx; |
2131 |
2081 |
|
|
2132 |
2082 |
thread_stack_bottom = (void*)r; |
thread_stack_bottom = (void*)r; |
2133 |
|
thread_stack_top = (void*)((u64)r + THREAD_STACK_BYTES_N); |
|
2134 |
2083 |
/*-------------------------------------------------------------------------------------------------------------------*/ |
/*-------------------------------------------------------------------------------------------------------------------*/ |
2135 |
2084 |
r = mmap(0, THREAD_LOCAL_STORAGE_BYTES_N, PROT_READ | PROT_WRITE, |
r = mmap(0, THREAD_LOCAL_STORAGE_BYTES_N, PROT_READ | PROT_WRITE, |
2136 |
2085 |
ULINUX_MAP_PRIVATE | ULINUX_MAP_ANONYMOUS, 0, 0); |
ULINUX_MAP_PRIVATE | ULINUX_MAP_ANONYMOUS, 0, 0); |
|
... |
... |
static void new(si cnx, struct sockaddr_in6 *peer) |
2141 |
2090 |
tls->cnx = cnx; |
tls->cnx = cnx; |
2142 |
2091 |
tls->stack = thread_stack_bottom; |
tls->stack = thread_stack_bottom; |
2143 |
2092 |
/*-------------------------------------------------------------------------------------------------------------------*/ |
/*-------------------------------------------------------------------------------------------------------------------*/ |
2144 |
|
/* this is fixed with clone3 in recent kernel, will write an assembly wrapper once we update the kernel */ |
|
2145 |
|
#ifdef ULINUX_ARM64 |
|
2146 |
|
r = clone( ULINUX_CLONE_VM |
|
|
2093 |
|
memset(&args,0,sizeof(args)); |
|
2094 |
|
args.flags = ULINUX_CLONE_VM |
2147 |
2095 |
| ULINUX_CLONE_FS |
| ULINUX_CLONE_FS |
2148 |
2096 |
| ULINUX_CLONE_FILES |
| ULINUX_CLONE_FILES |
2149 |
2097 |
| ULINUX_CLONE_SIGHAND |
| ULINUX_CLONE_SIGHAND |
2150 |
2098 |
| ULINUX_CLONE_THREAD |
| ULINUX_CLONE_THREAD |
2151 |
2099 |
| ULINUX_CLONE_SYSVSEM |
| ULINUX_CLONE_SYSVSEM |
2152 |
2100 |
| ULINUX_CLONE_SETTLS |
| ULINUX_CLONE_SETTLS |
2153 |
|
| ULINUX_CLONE_IO, thread_stack_top, 0, tls, 0); |
|
|
2101 |
|
| ULINUX_CLONE_IO; |
|
2102 |
|
args.stack = (u64)thread_stack_bottom; |
|
2103 |
|
args.stack_size = THREAD_STACK_BYTES_N; |
|
2104 |
|
args.tls = (u64)tls; |
|
2105 |
|
#ifdef ULINUX_ARM64 |
|
2106 |
|
r = clone(&args, sizeof(args), thread_entry); /* this is a noreturn in the thread */ |
2154 |
2107 |
#else |
#else |
2155 |
2108 |
#error "LNANOMSGBRD:ERROR:missing architecture clone syscall support" |
#error "LNANOMSGBRD:ERROR:missing architecture clone syscall support" |
2156 |
2109 |
#endif |
#endif |
2157 |
|
if (ISERR(r)) |
|
2158 |
|
goto err_munmap_tls; |
|
2159 |
|
if (r == 0) |
|
2160 |
|
thread_entry(); /* we waste a stack u64 slot until we write the assembly wrapper */ |
|
2161 |
|
return; |
|
|
2110 |
|
/* here, this is the main thread */ |
|
2111 |
|
if (!ISERR(r)) |
|
2112 |
|
return; |
2162 |
2113 |
/*-------------------------------------------------------------------------------------------------------------------*/ |
/*-------------------------------------------------------------------------------------------------------------------*/ |
2163 |
2114 |
err_munmap_tls: |
err_munmap_tls: |
2164 |
2115 |
munmap(tls, THREAD_LOCAL_STORAGE_BYTES_N); |
munmap(tls, THREAD_LOCAL_STORAGE_BYTES_N); |
File namespace/ulinux.h changed (mode: 100644) (index 3d8514e..dab4ab3) |
76 |
76 |
#define bind(a,b,c) ulinux_sysc_3(bind,a,(sl)b,c) |
#define bind(a,b,c) ulinux_sysc_3(bind,a,(sl)b,c) |
77 |
77 |
#define chdir(a) ulinux_sysc_1(chdir,(sl)a) |
#define chdir(a) ulinux_sysc_1(chdir,(sl)a) |
78 |
78 |
#define chroot(a) ulinux_sysc_1(chroot,(sl)a) |
#define chroot(a) ulinux_sysc_1(chroot,(sl)a) |
79 |
|
#define clone(a,b,c,d,e) ulinux_sysc_5(clone,(sl)a,(sl)b,(sl)c,(sl)d,(sl)e) |
|
80 |
79 |
#define close(a) ulinux_sysc_1(close, a) |
#define close(a) ulinux_sysc_1(close, a) |
81 |
80 |
#define cpu_to_be16_const ulinux_cpu_to_be16_const |
#define cpu_to_be16_const ulinux_cpu_to_be16_const |
82 |
81 |
#define epoll_ctl(a,b,c,d) ulinux_sysc_4(epoll_ctl,a,b,c,(sl)d) |
#define epoll_ctl(a,b,c,d) ulinux_sysc_4(epoll_ctl,a,b,c,(sl)d) |
|
184 |
183 |
#undef bind |
#undef bind |
185 |
184 |
#undef chdir |
#undef chdir |
186 |
185 |
#undef chroot |
#undef chroot |
187 |
|
#undef clone |
|
188 |
186 |
#undef close |
#undef close |
189 |
187 |
#undef cpu_to_be16_const |
#undef cpu_to_be16_const |
190 |
188 |
#undef epoll_ctl |
#undef epoll_ctl |