/* * Arguments: ecb_udata, {string | membuf_udata} ... * Returns: [success/partial (boolean), count (number)] */ static int ecb_write (lua_State *L) { LPEXTENSION_CONTROL_BLOCK ecb = lua_unboxpointer(L, 1, ECB_TYPENAME); size_t n = 0; /* number of chars actually write */ int i, narg = lua_gettop(L); if (ecb->dwHttpStatusCode & ECB_STATUS_HEADERS_SEND) { ecb->dwHttpStatusCode ^= ECB_STATUS_HEADERS_SEND; lua_pushfstring(L, "HTTP/1.1 %d\r\n", (ecb->dwHttpStatusCode & ECB_STATUS_MASK)); lua_rawgetp(L, LUA_REGISTRYINDEX, ecb); lua_pushliteral(L, "\r\n"); lua_concat(L, 3); lua_insert(L, 2); ++narg; } for (i = 2; i <= narg; ++i) { struct sys_buffer sb; int nw; if (!sys_buffer_read_init(L, i, &sb) || sb.size == 0) /* don't close the connection */ continue; sys_vm_leave(); { DWORD l = sb.size; nw = ecb->WriteClient(ecb->ConnID, sb.ptr.w, &l, 0) ? (int) l : -1; } sys_vm_enter(); if (nw == -1) { if (n > 0) break; return sys_seterror(L, 0); } n += nw; sys_buffer_read_next(&sb, nw); if ((size_t) nw < sb.size) break; } lua_pushboolean(L, (i > narg)); lua_pushinteger(L, n); return 2; }
/* * Arguments: sd_udata, {string | membuf_udata}, * [to (sock_addr_udata), options (string) ...] * Returns: [success/partial (boolean), count (number)] */ static int sock_send (lua_State *L) { static const int o_flags[] = { MSG_OOB, MSG_DONTROUTE, }; static const char *const o_names[] = { "oob", "dontroute", NULL }; sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); const struct sock_addr *to = !lua_isuserdata(L, 3) ? NULL : checkudata(L, 3, SA_TYPENAME); struct sys_buffer sb; int nw; /* number of chars actually send */ unsigned int i, flags = 0; if (!sys_buffer_read_init(L, 2, &sb)) luaL_argerror(L, 2, "buffer expected"); for (i = lua_gettop(L); i > 3; --i) { flags |= o_flags[luaL_checkoption(L, i, NULL, o_names)]; } sys_vm_leave(); do nw = !to ? send(sd, sb.ptr.r, sb.size, flags) : sendto(sd, sb.ptr.r, sb.size, flags, &to->u.addr, to->addrlen); while (nw == -1 && SYS_ERRNO == EINTR); sys_vm_enter(); if (nw == -1) { if (!SYS_EAGAIN(SYS_ERRNO)) return sys_seterror(L, 0); nw = 0; } else { sys_buffer_read_next(&sb, nw); } lua_pushboolean(L, ((size_t) nw == sb.size)); lua_pushinteger(L, nw); return 2; }
/* * Arguments: sd_udata, fd_udata, [count (number)] * Returns: [count (number) | false (EAGAIN)] */ static int sock_sendfile (lua_State *L) { sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); fd_t fd = (fd_t) lua_unboxinteger(L, 2, FD_TYPENAME); size_t n = (size_t) lua_tointeger(L, 3); ssize_t res; sys_vm_leave(); #ifndef _WIN32 #if defined(__linux__) do res = sendfile(sd, fd, NULL, n ? n : ~((size_t) 0)); while (res == -1 && SYS_ERRNO == EINTR); #else { off_t nw, off = lseek(fd, 0, SEEK_CUR); #if defined(__APPLE__) && defined(__MACH__) nw = n; do res = sendfile(fd, sd, off, &nw, NULL, 0); #else do res = sendfile(fd, sd, off, n, NULL, &nw, 0); #endif while (res == -1 && SYS_ERRNO == EINTR); if (res != -1) { res = (size_t) nw; lseek(fd, nw, SEEK_CUR); } } #endif sys_vm_enter(); if (res != -1 || SYS_EAGAIN(SYS_ERRNO)) { if (res == -1) { lua_pushboolean(L, 0); return 1; } #else res = TransmitFileMap(sd, fd, n); sys_vm_enter(); if (res != 0L) { #endif lua_pushinteger(L, res); return 1; } return sys_seterror(L, 0); } /* * Arguments: sd_udata, {string | membuf_udata} ... * Returns: [success/partial (boolean), count (number)] */ static int sock_write (lua_State *L) { sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); ssize_t n = 0; /* number of chars actually write */ int i, nargs = lua_gettop(L); for (i = 2; i <= nargs; ++i) { struct sys_buffer sb; int nw; if (!sys_buffer_read_init(L, i, &sb)) continue; sys_vm_leave(); #ifndef _WIN32 do nw = write(sd, sb.ptr.r, sb.size); while (nw == -1 && SYS_ERRNO == EINTR); #else { WSABUF buf = {sb.size, sb.ptr.w}; DWORD l; nw = !WSASend(sd, &buf, 1, &l, 0, NULL, NULL) ? l : -1; } #endif sys_vm_enter(); if (nw == -1) { if (n > 0 || SYS_EAGAIN(SYS_ERRNO)) break; return sys_seterror(L, 0); } n += nw; sys_buffer_read_next(&sb, nw); if ((size_t) nw < sb.size) break; } lua_pushboolean(L, (i > nargs)); lua_pushinteger(L, n); return 2; }