/* * Arguments: sd_udata, [membuf_udata, count (number)] * Returns: [string | false (EAGAIN)] */ static int sock_read (lua_State *L) { sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); size_t n = !lua_isnumber(L, -1) ? ~((size_t) 0) : (size_t) lua_tointeger(L, -1); const size_t len = n; /* how much total to read */ size_t rlen; /* how much to read */ int nr; /* number of bytes actually read */ struct sys_buffer sb; char buf[SYS_BUFSIZE]; sys_buffer_write_init(L, 2, &sb, buf, sizeof(buf)); do { rlen = (n <= sb.size) ? n : sb.size; sys_vm_leave(); #ifndef _WIN32 do nr = read(sd, sb.ptr.w, rlen); while (nr == -1 && SYS_ERRNO == EINTR); #else { WSABUF buf = {rlen, sb.ptr.w}; DWORD l, flags = 0; nr = !WSARecv(sd, &buf, 1, &l, &flags, NULL, NULL) ? l : -1; } #endif sys_vm_enter(); if (nr == -1) break; n -= nr; /* still have to read `n' bytes */ } while ((n != 0L && nr == (int) rlen) /* until end of count or eof */ && sys_buffer_write_next(L, &sb, buf, 0)); if (nr <= 0 && len == n) { if (!nr || !SYS_EAGAIN(SYS_ERRNO)) goto err; lua_pushboolean(L, 0); } else { if (!sys_buffer_write_done(L, &sb, buf, nr)) lua_pushinteger(L, len - n); } return 1; err: return sys_seterror(L, 0); }
/* * Arguments: ecb_udata, [membuf_udata, count (number)] * Returns: [string | count (number)] */ static int ecb_read (lua_State *L) { LPEXTENSION_CONTROL_BLOCK ecb = lua_unboxpointer(L, 1, ECB_TYPENAME); size_t n = !lua_isnumber(L, -1) ? ~((size_t) 0) : (size_t) lua_tointeger(L, -1); const size_t len = n; /* how much total to read */ size_t rlen; /* how much to read */ int nr; /* number of bytes actually read */ struct sys_thread *td = sys_thread_get(); struct sys_buffer sb; char buf[SYS_BUFSIZE]; int res = 0; sys_buffer_write_init(L, 2, &sb, buf, sizeof(buf)); do { rlen = (n <= sb.size) ? n : sb.size; if (td) sys_vm2_leave(td); { DWORD l; nr = ecb->ReadClient(ecb->ConnID, sb.ptr.w, &l) ? (int) l : -1; } if (td) sys_vm2_enter(td); if (nr == -1) break; n -= nr; /* still have to read `n' bytes */ } while ((n != 0L && nr == (int) rlen) /* until end of count or eof */ && sys_buffer_write_next(L, &sb, buf, 0)); if (nr <= 0 && len == n) { res = -1; } else { if (!sys_buffer_write_done(L, &sb, buf, nr)) lua_pushinteger(L, len - n); } if (td) sys_thread_check(td); if (!res) return 1; return sys_seterror(L, 0); }
/* * Arguments: sd_udata, [count (number) | membuf_udata, * from (sock_addr_udata), options (string) ...] * Returns: [string | count (number) | false (EAGAIN)] */ static int sock_recv (lua_State *L) { static const int o_flags[] = { MSG_OOB, MSG_PEEK, #ifndef _WIN32 MSG_WAITALL #endif }; static const char *const o_names[] = { "oob", "peek", #ifndef _WIN32 "waitall", #endif NULL }; sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); size_t n = !lua_isnumber(L, 2) ? ~((size_t) 0) : (size_t) lua_tointeger(L, 2); struct sock_addr *from = !lua_isuserdata(L, 3) ? NULL : checkudata(L, 3, SA_TYPENAME); struct sockaddr *sap = NULL; socklen_t *slp = NULL; const size_t len = n; /* how much total to read */ size_t rlen; /* how much to read */ int nr; /* number of bytes actually read */ struct sys_buffer sb; char buf[SYS_BUFSIZE]; unsigned int i, flags = 0; sys_buffer_write_init(L, 2, &sb, buf, sizeof(buf)); for (i = lua_gettop(L); i > 3; --i) { flags |= o_flags[luaL_checkoption(L, i, NULL, o_names)]; } if (from) { sap = &from->u.addr; slp = &from->addrlen; } do { rlen = (n <= sb.size) ? n : sb.size; sys_vm_leave(); #ifndef _WIN32 do nr = recvfrom(sd, sb.ptr.w, rlen, flags, sap, slp); while (nr == -1 && SYS_ERRNO == EINTR); #else nr = recvfrom(sd, sb.ptr.w, rlen, flags, sap, slp); #endif sys_vm_enter(); if (nr == -1) break; n -= nr; /* still have to read `n' bytes */ } while ((n != 0L && nr == (int) rlen) /* until end of count or eof */ && sys_buffer_write_next(L, &sb, buf, 0)); if (nr <= 0 && len == n) { if (!nr || !SYS_EAGAIN(SYS_ERRNO)) goto err; lua_pushboolean(L, 0); } else { if (!sys_buffer_write_done(L, &sb, buf, nr)) lua_pushinteger(L, len - n); } return 1; err: return sys_seterror(L, 0); }