LUA_API int luanet_tonetobject(lua_State *L,int index) { int *udata; if (lua_type(L,index)==LUA_TUSERDATA) { if (luaL_checkmetatable(L,index)) { udata = (int*)lua_touserdata (L,index); if (udata != NULL) return *udata; } udata = (int*)checkudata (L, index, "luaNet_class"); if (udata!=NULL) return *udata; udata = (int*)checkudata (L, index, "luaNet_searchbase"); if (udata!=NULL) return *udata; udata = (int*)checkudata(L, index, "luaNet_function"); if (udata!=NULL) return *udata; } return -1; }
/* * Arguments: sd_udata, new_sd_udata, [sock_addr_udata] * Returns: [new_sd_udata | false (EAGAIN)] */ static int sock_accept (lua_State *L) { sd_t sd = (sd_t) lua_unboxinteger(L, 1, SD_TYPENAME); sd_t *sdp = checkudata(L, 2, SD_TYPENAME); struct sock_addr *from = lua_isnoneornil(L, 3) ? NULL : checkudata(L, 3, SA_TYPENAME); struct sockaddr *sap = NULL; socklen_t *slp = NULL; if (from) { sap = &from->u.addr; slp = &from->addrlen; } #ifndef _WIN32 do sd = accept(sd, sap, slp); while (sd == -1 && SYS_ERRNO == EINTR); #else sd = accept(sd, sap, slp); #endif if (sd != (sd_t) -1) { *sdp = sd; lua_settop(L, 2); return 1; } else if (SYS_EAGAIN(SYS_ERRNO)) { lua_pushboolean(L, 0); return 1; } return sys_seterror(L, 0); }
/* * Arguments: membuf_udata, source (membuf_udata), num_bytes (number) * Returns: [membuf_udata] */ static int mem_memcpy (lua_State *L) { struct membuf *mb = checkudata(L, 1, MEM_TYPENAME); struct membuf *src = checkudata(L, 2, MEM_TYPENAME); const int len = luaL_checkinteger(L, 3); lua_settop(L, 1); return memcpy(mb->data, src->data, len) ? 1 : 0; }
/* * Returns: [rand_udata] */ static int sys_random (lua_State *L) { #ifndef _WIN32 fd_t *fdp = lua_newuserdata(L, sizeof(fd_t)); #if defined(__OpenBSD__) *fdp = open("/dev/arandom", O_RDONLY, 0); if (*fdp == (fd_t) -1) *fdp = open("/dev/urandom", O_RDONLY, 0); #else *fdp = open("/dev/urandom", O_RDONLY, 0); #endif if (*fdp != (fd_t) -1) { #else HCRYPTPROV *p = lua_newuserdata(L, sizeof(void *)); if (CryptAcquireContext(p, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { #endif luaL_getmetatable(L, RAND_TYPENAME); lua_setmetatable(L, -2); return 1; } return sys_seterror(L, 0); } /* * Arguments: rand_udata */ static int rand_close (lua_State *L) { #ifndef _WIN32 fd_t *fdp = (fd_t *) checkudata(L, 1, RAND_TYPENAME); if (*fdp != (fd_t) -1) { close(*fdp); *fdp = (fd_t) -1; } #else HCRYPTPROV *p = (HCRYPTPROV *) checkudata(L, 1, RAND_TYPENAME); if (*p != (HCRYPTPROV) -1) { CryptReleaseContext(*p, 0); *p = (HCRYPTPROV) -1; } #endif return 0; }
static int lnet_tag_type(lua_State* L) { libnet_t* ud = checkudata(L); libnet_pblock_t* pblock = checkpblock(L, ud, 2); lua_pushstring(L, libnet_diag_dump_pblock_type(pblock->type)); return 1; }
/* * Arguments: evq_udata, ev_ludata, [reuse_fd (boolean)] * Returns: [evq_udata] */ static int levq_del (lua_State *L) { struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME); struct event *ev = levq_toevent(L, 2); const int reuse_fd = lua_toboolean(L, 3); int res = 0; lua_assert(ev); #undef ARG_LAST #define ARG_LAST 1 #ifdef EVQ_POST_INIT if (ev == evq->ev_post) evq->ev_post = NULL; #endif if (!event_deleted(ev)) res = evq_del(ev, reuse_fd); if (!(ev->flags & (EVENT_ACTIVE | EVENT_DELETE))) levq_del_event(evq, ev); ev->flags |= EVENT_DELETE; if (!res) { lua_settop(L, 1); return 1; } return sys_seterror(L, 0); }
/*- -- net:dump() Write summary of protocol blocks to stdout. */ static int lnet_dump(lua_State* L) { libnet_t* ud = checkudata(L); libnet_pblock_t* p = ud->protocol_blocks; int strings = 0; while(p) { /* h_len is header length for checksumming? "chksum length"? */ char str[1024]; sprintf(str, "tag %d flags %d type %s/%#x buf %p b_len %2u h_len %2u copied %u prev %d next %d\n", p->ptag, p->flags, type_string(p->type), p->type, p->buf, p->b_len, p->h_len, p->copied, p->prev ? p->prev->ptag : -1, p->next ? p->next->ptag : -1 ); lua_pushstring(L, str); p = p->next; strings++; } lua_pushfstring(L, "link_offset %d aligner %d total_size %d nblocks %d\n", ud->link_offset, ud->aligner, ud->total_size, ud->n_pblocks); strings++; lua_concat(L, strings); return 1; }
/*- -- argt = net:get_eth() Get eth pblock argument table. */ static int lnet_get_eth (lua_State *L) { libnet_t* ud = checkudata(L); libnet_pblock_t* pblock = checkptype(L, ud, LIBNET_PBLOCK_ETH_H); struct libnet_ethernet_hdr* hdr = (struct libnet_ethernet_hdr*) pblock->buf; lua_newtable(L); setintfield(L, 2, "ptag", pblock->ptag); setethfield(L, 2, "src", hdr->ether_shost); setethfield(L, 2, "dst", hdr->ether_dhost); setnsintfield(L, 2, "type", hdr->ether_type); if(!pblock->prev) { /* direct payload */ uint8_t* data = pblock->buf + LIBNET_ETH_H; uint32_t datasz = 0; if(pblock->b_len > LIBNET_ETH_H) { datasz = pblock->b_len - LIBNET_ETH_H; } setlstringfield(L, 2, "payload", data, (size_t)datasz); } return 1; }
/* * Arguments: evq_udata, ev_ludata, [callback (function)] * Returns: evq_udata | callback (function) */ static int levq_callback (lua_State *L) { struct event_queue *evq = checkudata(L, 1, EVQ_TYPENAME); struct event *ev = levq_toevent(L, 2); lua_State *NL = evq->L; const int top = lua_gettop(L); lua_assert(ev && !event_deleted(ev)); if (top < 3) { lua_rawgeti(NL, EVQ_CORO_CALLBACK, ev->ev_id); lua_xmove(NL, L, 1); } else { ev->flags &= ~(EVENT_CALLBACK | EVENT_CALLBACK_CORO); if (!lua_isnoneornil(L, 3)) { ev->flags |= EVENT_CALLBACK | (lua_isthread(L, 3) ? EVENT_CALLBACK_CORO : 0); } lua_settop(L, 3); lua_xmove(L, NL, 1); lua_rawseti(NL, EVQ_CORO_CALLBACK, ev->ev_id); lua_settop(L, 1); } return 1; }
/* * Arguments: membuf_udata * Returns: membuf_udata */ static int mem_free (lua_State *L) { struct membuf *mb = checkudata(L, 1, MEM_TYPENAME); if (mb->data) { const unsigned int mb_flags = mb->flags; switch (mb_flags & (MEM_ALLOC | MEM_MAP)) { case MEM_ALLOC: free(mb->data); break; #ifdef USE_MMAP case MEM_MAP: #ifndef _WIN32 munmap(mb->data, mb->len); #else UnmapViewOfFile(mb->data); #endif break; #endif /* USE_MMAP */ } mb->data = NULL; mb->flags &= MEM_TYPE_MASK; } return 1; }
static int channel_tostring (lua_State *L) { struct channel *chan = checkudata(L, 1, CHANNEL_TYPENAME); lua_pushfstring(L, "[chan: %p]", chan); return 1; }
/* * Arguments: pipe_udata */ static int pipe_close (lua_State *L) { struct pipe_ref *pr = checkudata(L, 1, PIPE_TYPENAME); struct pipe *pp = pr->pipe; if (pp) { thread_critsect_t *csp = pipe_critsect_ptr(pp); int nref; thread_critsect_enter(csp); nref = pp->nref--; thread_critsect_leave(csp); if (!nref) { thread_critsect_del(&pp->cs); thread_cond_del(&pp->put_cond); thread_cond_del(&pp->get_cond); /* deallocate buffers */ if (pp->rbuf) { struct pipe_buf *rpb = pp->rbuf, *wpb = pp->wbuf; do { struct pipe_buf *pb = rpb->next_buf; free(rpb); rpb = pb; } while (rpb != wpb); } free(pp); } pr->pipe = NULL; } return 0; }
LUA_API int luanet_checkudata (lua_State *L,int index,const char *meta) { int *udata = (int*)checkudata (L, index, meta); if(udata!=NULL) return *udata; return -1; }
/* * Arguments: membuf_udata, [count (number) | mode (string: "*l", "*a")] * Returns: [string | number] */ static int membuf_read (lua_State *L) { struct membuf *mb = checkudata(L, 1, MEM_TYPENAME); lua_settop(L, 2); if (mb->flags & MEM_ISTREAM) { lua_getfenv(L, 1); lua_rawgeti(L, -1, MEM_INPUT); /* stream object */ lua_getfield(L, -1, "read"); lua_insert(L, -2); } if (lua_type(L, 2) == LUA_TNUMBER) read_bytes(L, mb, lua_tointeger(L, 2)); else { const char *s = luaL_optstring(L, 2, "*a"); switch (s[1]) { case 'l': return read_line(L, mb); case 'a': read_bytes(L, mb, ~((size_t) 0)); break; default: luaL_argerror(L, 2, "invalid option"); } } return 1; }
/* * Arguments: dpool_udata * Returns: string */ static int dpool_tostring (lua_State *L) { struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); lua_pushfstring(L, DPOOL_TYPENAME " (%p)", &dp->tev); return 1; }
/*- -- net:pblock(lua_State* L, int ptag) Get a table with all the pblock info in it. */ static int lnet_pblock(lua_State* L) { libnet_t* ud = checkudata(L); libnet_pblock_t* pblock = checkpblock(L, ud, 2); pushpblock(L, pblock); return 1; }
/* * Arguments: membuf_udata, stream */ static int membuf_assosiate (lua_State *L, int type) { struct membuf *mb = checkudata(L, 1, MEM_TYPENAME); const int idx = (type == MEM_ISTREAM) ? MEM_INPUT : MEM_OUTPUT; lua_settop(L, 2); if (lua_isnoneornil(L, 2)) mb->flags &= ~type; else { mb->flags |= type; lua_getfield(L, -1, SYS_BUFIO_TAG); if (!lua_isnil(L, -1)) { mb->flags |= (type == MEM_ISTREAM) ? MEM_ISTREAM_BUFIO : MEM_OSTREAM_BUFIO; } lua_pop(L, 1); } lua_getfenv(L, 1); if (!lua_istable(L, -1)) { lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -1); lua_setfenv(L, 1); } lua_pushvalue(L, 2); lua_rawseti(L, -2, idx); return 0; }
/* FIXME - we should just have a packet function, this fails on single blocks/ptags, and the :pblock() method is better, anyway. */ static int lnet_block(lua_State* L) { libnet_t* ud = checkudata(L); u_int32_t len; u_int8_t *packet = NULL; u_int8_t *block; int r; r = libnet_pblock_coalesce(ud, &packet, &len); check_error(L, ud, r); block = packet; if(!lua_isnoneornil(L, 2)) { libnet_pblock_t* end = checkpblock(L, ud, 2); libnet_pblock_t* p = ud->pblock_end; while(p != end) { block += p->b_len; p = p->prev; } assert(p == end); len = p->b_len; } lua_pushlstring(L, (char*) block, len); libnet_adv_free_packet(ud, packet); return 1; }
/* * Arguments: thread_udata */ static int thread_done (lua_State *L) { struct sys_thread *td = checkudata(L, 1, THREAD_TYPENAME); if (td->L) { if (thread_isvm(td)) { thread_critsect_leave(td->vmcsp); thread_critsect_del(td->vmcsp); } else { sys_vm2_leave(td); #ifndef _WIN32 { THREAD_FUNC_RES v; pthread_join(td->tid, &v); } #else WaitForSingleObject(td->tid, INFINITE); CloseHandle(td->tid); #endif sys_vm2_enter(td); } (void) thread_cond_del(&td->cond); lua_rawgetp(L, LUA_REGISTRYINDEX, THREAD_KEY_ADDRESS); lua_pushnil(L); lua_rawsetp(L, -2, td->L); /* coroutine */ lua_pop(L, 1); td->L = NULL; } return 0; }
/* * Arguments: membuf_udata * Returns: size (number) */ static int mem_typesize (lua_State *L) { struct membuf *mb = checkudata(L, 1, MEM_TYPENAME); lua_pushinteger(L, memtypesize(mb)); return 1; }
/* * Arguments: dpool_udata */ static int dpool_done (lua_State *L) { struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); thread_event_del(&dp->tev); return 0; }
static int channel_count (lua_State *L) { struct channel *chan = checkudata(L, 1, CHANNEL_TYPENAME); lua_pushinteger(L, chan->n); return 1; }
/* * Arguments: thread_udata */ static int thread_resume_wrap (lua_State *L) { struct sys_thread *td = checkudata(L, 1, THREAD_TYPENAME); sys_thread_resume(td); return 0; }
/* * Arguments: thread_udata * Returns: string */ static int thread_tostring (lua_State *L) { struct sys_thread *td = checkudata(L, 1, THREAD_TYPENAME); lua_pushfstring(L, THREAD_TYPENAME " (%p)", td); return 1; }
/* * Arguments: dpool_udata * Returns: number */ static int dpool_count (lua_State *L) { struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); lua_pushinteger(L, dp->n); return 1; }
/* * Arguments: ..., dpool_udata */ static sys_trigger_t * dpool_get_trigger (lua_State *L, struct sys_thread **tdp) { struct data_pool *dp = checkudata(L, -1, DPOOL_TYPENAME); *tdp = NULL; return &dp->trigger; }
/* * Arguments: dpool_udata, data_items (any) ... */ static int dpool_put (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); int nput = lua_gettop(L) - 1; if (!td) luaL_argerror(L, 0, "Threading not initialized"); if (!nput) luaL_argerror(L, 2, "data expected"); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if (dp->n >= dp->max) { if (dp->flags & DPOOL_PUTONFULL) { lua_rawgetp(L, 1, (void *) DPOOL_PUTONFULL); lua_insert(L, 2); lua_call(L, 1 + nput, LUA_MULTRET); nput = lua_gettop(L) - 1; if (!nput) return 0; } else { do { const int res = thread_event_wait(&dp->tev, td, TIMEOUT_INFINITE); sys_thread_check(td); if (res) return sys_seterror(L, 0); } while (dp->n >= dp->max); } } /* Try directly move data between threads */ if (dp->nwaits && !dp->td) { dp->td = td; dp->nput = nput; thread_event_signal(&dp->tev); sys_thread_switch(0); dp->td = NULL; if (!dp->nput) return 0; /* moved to thread */ dp->nput = 0; } /* Keep data in the storage */ { int top = dp->top; lua_pushinteger(L, nput); do { lua_rawseti(L, 1, ++top); } while (nput--); dp->top = top; if (!dp->n++) { thread_event_signal(&dp->tev); } } return 0; }
/* * Arguments: thread_udata * Returns: boolean */ static int thread_interrupted (lua_State *L) { struct sys_thread *td = checkudata(L, 1, THREAD_TYPENAME); td = thread_unfake(td); lua_pushboolean(L, (td->flags == SYS_THREAD_INTERRUPT)); return 1; }
/*- -- net = net:clear() Clear the current packet and all it's protocol blocks. Return self. */ static int lnet_clear(lua_State* L) { libnet_t* ud = checkudata(L); libnet_clear_packet(ud); /* TODO - these bugs are fixed in libnet head */ ud->n_pblocks = 0; ud->ptag_state = 0; return 1; }
/* * Arguments: fd_udata, [prefix (string), persistent (boolean)] * Returns: [filename] */ static int sys_tempfile (lua_State *L) { fd_t fd, *fdp = checkudata(L, 1, FD_TYPENAME); const char *prefix = lua_tostring(L, 2); const int persist = lua_isboolean(L, -1) && lua_toboolean(L, -1); #ifndef _WIN32 static const char template[] = "XXXXXX";