// Queue an interrupt and set the Lua hook // Returns PLATFORM_OK or PLATFORM_ERR int elua_int_add( elua_int_id inttype, elua_int_resnum resnum ) { if( inttype < ELUA_INT_FIRST_ID || inttype > INT_ELUA_LAST ) return PLATFORM_ERR; // If Lua is not running (no Lua state), or no Lua interrupt handler is set, // or the interrupt is not enabled, don't do anything if( lua_getstate() == NULL || !elua_int_is_enabled( inttype ) ) return PLATFORM_ERR; // If there's no more room in the queue, set the overflow flag and return if( elua_int_queue[ elua_int_write_idx ].id != ELUA_INT_EMPTY_SLOT ) { printf( "ERROR in elua_int_add: buffer overflow, interrupt not queued\n" ); return PLATFORM_ERR; } // Queue the interrupt elua_int_queue[ elua_int_write_idx ].id = inttype; elua_int_queue[ elua_int_write_idx ].resnum = resnum; elua_int_write_idx = ( elua_int_write_idx + 1 ) & INT_IDX_MASK; // Set the Lua hook (it's OK to set it even if it's already set) lua_sethook( lua_getstate(), elua_int_hook, LUA_MASKCOUNT, 2 ); // All OK return PLATFORM_OK; }
static void net_dns_cb(const char *name, ip_addr_t *ipaddr, void *arg) { ip_addr_t addr; if (ipaddr != NULL) addr = *ipaddr; else addr.addr = 0xFFFFFFFF; lnet_userdata *ud = (lnet_userdata*)arg; if (!ud) return; lua_State *L = lua_getstate(); if (ud->self_ref != LUA_NOREF && ud->client.cb_dns_ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_dns_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); if (addr.addr != 0xFFFFFFFF) { char iptmp[16]; bzero(iptmp, 16); ets_sprintf(iptmp, IPSTR, IP2STR(&addr.addr)); lua_pushstring(L, iptmp); } else { lua_pushnil(L); } lua_call(L, 2, 0); } ud->client.wait_dns --; if (ud->pcb && ud->type == TYPE_TCP_CLIENT && ud->tcp_pcb->state == CLOSED) { tcp_connect(ud->tcp_pcb, &addr, ud->tcp_pcb->remote_port, net_connected_cb); } else if (!ud->pcb && ud->client.wait_dns == 0) { lua_gc(L, LUA_GCSTOP, 0); luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref); ud->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); } }
static void alarm_timer_common(void* arg){ timer_t tmr = (timer_t)arg; lua_State* L = lua_getstate(); if(tmr->lua_ref == LUA_NOREF) return; lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref); if (tmr->self_ref == LUA_REFNIL) { uint32_t id = tmr - alarm_timers; lua_pushinteger(L, id); } else { lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref); } //if the timer was set to single run we clean up after it if(tmr->mode == TIMER_MODE_SINGLE){ luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); tmr->lua_ref = LUA_NOREF; tmr->mode = TIMER_MODE_OFF; }else if(tmr->mode == TIMER_MODE_SEMI){ tmr->mode |= TIMER_IDLE_FLAG; } if (tmr->mode != TIMER_MODE_AUTO && tmr->self_ref != LUA_REFNIL) { luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref); tmr->self_ref = LUA_NOREF; } lua_call(L, 1, 0); }
static void net_recv_cb(lnet_userdata *ud, struct pbuf *p, ip_addr_t *addr, u16_t port) { if (ud->client.cb_receive_ref == LUA_NOREF) { pbuf_free(p); return; } int num_args = 2; char iptmp[16] = { 0, }; if (ud->type == TYPE_UDP_SOCKET) { num_args += 2; ets_sprintf(iptmp, IPSTR, IP2STR(&addr->addr)); } lua_State *L = lua_getstate(); struct pbuf *pp = p; while (pp) { lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_receive_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_pushlstring(L, pp->payload, pp->len); if (ud->type == TYPE_UDP_SOCKET) { lua_pushinteger(L, port); lua_pushstring(L, iptmp); } lua_call(L, num_args, 0); pp = pp->next; } pbuf_free(p); }
static err_t net_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) { lnet_userdata *ud = (lnet_userdata*)arg; if (!ud || ud->type != TYPE_TCP_SERVER || !ud->pcb) return ERR_ABRT; if (ud->self_ref == LUA_NOREF || ud->server.cb_accept_ref == LUA_NOREF) return ERR_ABRT; lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->server.cb_accept_ref); lnet_userdata *nud = net_create(L, TYPE_TCP_CLIENT); lua_pushvalue(L, 2); nud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); nud->tcp_pcb = newpcb; tcp_arg(nud->tcp_pcb, nud); tcp_err(nud->tcp_pcb, net_err_cb); tcp_recv(nud->tcp_pcb, net_tcp_recv_cb); tcp_sent(nud->tcp_pcb, net_sent_cb); nud->tcp_pcb->so_options |= SOF_KEEPALIVE; nud->tcp_pcb->keep_idle = ud->server.timeout * 1000; nud->tcp_pcb->keep_cnt = 1; tcp_accepted(ud->tcp_pcb); lua_call(L, 1, 0); return net_connected_cb(nud, nud->tcp_pcb, ERR_OK); }
static void tls_socket_onreconnect( struct espconn *pesp_conn, s8 err ) { tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_reconnect_ref != LUA_NOREF) { const char* reason = NULL; switch (err) { case(ESPCONN_MEM): reason = "Out of memory"; break; case(ESPCONN_TIMEOUT): reason = "Timeout"; break; case(ESPCONN_RTE): reason = "Routing problem"; break; case(ESPCONN_ABRT): reason = "Connection aborted"; break; case(ESPCONN_RST): reason = "Connection reset"; break; case(ESPCONN_CLSD): reason = "Connection closed"; break; case(ESPCONN_HANDSHAKE): reason = "SSL handshake failed"; break; case(ESPCONN_SSL_INVALID_DATA): reason = "SSL application invalid"; break; } lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->cb_reconnect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); if (reason != NULL) { lua_pushstring(L, reason); } else { lua_pushnil(L); } tls_socket_cleanup(ud); lua_call(L, 2, 0); } else tls_socket_cleanup(ud); }
static void tls_socket_dns_cb( const char* domain, const ip_addr_t *ip_addr, tls_socket_ud *ud ) { if (ud->self_ref == LUA_NOREF) return; ip_addr_t addr; if (ip_addr) addr = *ip_addr; else addr.addr = 0xFFFFFFFF; lua_State *L = lua_getstate(); if (ud->cb_dns_ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, ud->cb_dns_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); if (addr.addr == 0xFFFFFFFF) { lua_pushnil(L); } else { char tmp[20]; c_sprintf(tmp, IPSTR, IP2STR(&addr.addr)); lua_pushstring(L, tmp); } lua_call(L, 2, 0); } if (addr.addr == 0xFFFFFFFF) { lua_gc(L, LUA_GCSTOP, 0); luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref); ud->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); } else { os_memcpy(ud->pesp_conn->proto.tcp->remote_ip, &addr.addr, 4); espconn_secure_connect(ud->pesp_conn); } }
static void do_node_task (task_param_t task_fn_ref, uint8_t prio) { lua_State* L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref); luaL_unref(L, LUA_REGISTRYINDEX, (int)task_fn_ref); lua_pushinteger(L, prio); lua_call(L, 1, 0); }
static err_t net_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) { lnet_userdata *ud = (lnet_userdata*)arg; if (!ud || !ud->pcb || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return ERR_ABRT; if (ud->client.cb_sent_ref == LUA_NOREF) return ERR_OK; lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_sent_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_call(L, 1, 0); return ERR_OK; }
static void key_short_press(void *arg) { lua_State *L = lua_getstate(); NODE_DBG("key_short_press is called.\n"); if (short_key_ref == LUA_NOREF) { default_short_press(arg); return; } lua_rawgeti(L, LUA_REGISTRYINDEX, short_key_ref); lua_call(L, 0, 0); }
static void tls_socket_onconnect( struct espconn *pesp_conn ) { tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_connect_ref != LUA_NOREF) { lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->cb_connect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_call(L, 1, 0); } }
static void on_timeout (void *arg) { (void)arg; sntp_dbg("sntp: timer\n"); lua_State *L = lua_getstate (); if (state->attempts >= MAX_ATTEMPTS) handle_error (L, NTP_TIMEOUT_ERR); else sntp_dosend (L); }
static void tls_socket_onrecv( struct espconn *pesp_conn, char *buf, u16 length ) { tls_socket_ud *ud = (tls_socket_ud *)pesp_conn->reverse; if (!ud || ud->self_ref == LUA_NOREF) return; if (ud->cb_receive_ref != LUA_NOREF) { lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->cb_receive_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_pushlstring(L, buf, length); lua_call(L, 2, 0); } }
static err_t net_connected_cb(void *arg, struct tcp_pcb *tpcb, err_t err) { lnet_userdata *ud = (lnet_userdata*)arg; if (!ud || ud->pcb != tpcb) return ERR_ABRT; if (err != ERR_OK) { net_err_cb(arg, err); return ERR_ABRT; } lua_State *L = lua_getstate(); if (ud->self_ref != LUA_NOREF && ud->client.cb_connect_ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, ud->client.cb_connect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_call(L, 1, 0); } return ERR_OK; }
static void sntp_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { (void)arg; lua_State *L = lua_getstate (); if (ipaddr == NULL) { sntp_dbg("DNS Fail!\n"); handle_error(L, NTP_DNS_ERR); } else { server = *ipaddr; sntp_dosend(L); } }
static void pcm_start_play_task( task_param_t param, uint8 prio ) { lua_State *L = lua_getstate(); pud_t *pud = (pud_t *)param; cfg_t *cfg = &(pud->cfg); // stop driver before starting it in case it hasn't been stopped from Lua pud->drv->stop( cfg ); if (!pud->drv->play( cfg )) { luaL_error( L, "pcm driver start" ); } // unthrottle ISR and reader pud->cfg.isr_throttled = 0; }
static void tls_socket_cleanup(tls_socket_ud *ud) { if (ud->pesp_conn) { espconn_secure_disconnect(ud->pesp_conn); if (ud->pesp_conn->proto.tcp) { c_free(ud->pesp_conn->proto.tcp); ud->pesp_conn->proto.tcp = NULL; } c_free(ud->pesp_conn); ud->pesp_conn = NULL; } lua_State *L = lua_getstate(); lua_gc(L, LUA_GCSTOP, 0); luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref); ud->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); }
static void websocketclient_onConnectionCallback(ws_info *ws) { NODE_DBG("websocketclient_onConnectionCallback\n"); lua_State *L = lua_getstate(); if (ws == NULL || ws->reservedData == NULL) { luaL_error(L, "Client websocket is nil.\n"); return; } ws_data *data = (ws_data *) ws->reservedData; if (data->onConnection != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onConnection); // load the callback function lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument lua_call(L, 1, 0); } }
static void websocketclient_onReceiveCallback(ws_info *ws, char *message, int opCode) { NODE_DBG("websocketclient_onReceiveCallback\n"); lua_State *L = lua_getstate(); if (ws == NULL || ws->reservedData == NULL) { luaL_error(L, "Client websocket is nil.\n"); return; } ws_data *data = (ws_data *) ws->reservedData; if (data->onReceive != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onReceive); // load the callback function lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument lua_pushstring(L, message); // #2 callback argument lua_pushnumber(L, opCode); // #3 callback argument lua_call(L, 3, 0); } }
static void wifi_status_cb(int arg) { lua_State* L = lua_getstate(); if (wifi_get_opmode() == SOFTAP_MODE) { os_timer_disarm(&wifi_sta_status_timer); return; } int wifi_status = wifi_station_get_connect_status(); if (wifi_status != prev_wifi_status) { if(wifi_station_status_cb_ref[wifi_status] != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, wifi_station_status_cb_ref[wifi_status]); lua_pushnumber(L, prev_wifi_status); lua_call(L, 1, 0); } } prev_wifi_status = wifi_status; }
void output_redirect(const char *str) { lua_State *L = lua_getstate(); // if(c_strlen(str)>=TX_BUFF_SIZE){ // NODE_ERR("output too long.\n"); // return; // } if (output_redir_ref == LUA_NOREF || !L) { uart0_sendStr(str); return; } if (serial_debug != 0) { uart0_sendStr(str); } lua_rawgeti(L, LUA_REGISTRYINDEX, output_redir_ref); lua_pushstring(L, str); lua_call(L, 1, 0); // this call back function should never user output. }
static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callback_arg) { ip_addr_t addr; if (ipaddr != NULL) addr = *ipaddr; else addr.addr = 0xFFFFFFFF; int cb_ref = ((int*)callback_arg)[0]; c_free(callback_arg); lua_State *L = lua_getstate(); lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref); lua_pushnil(L); if (addr.addr != 0xFFFFFFFF) { char iptmp[20]; size_t ipl = c_sprintf(iptmp, IPSTR, IP2STR(&addr.addr)); lua_pushlstring(L, iptmp, ipl); } else { lua_pushnil(L); } lua_call(L, 2, 0); luaL_unref(L, LUA_REGISTRYINDEX, cb_ref); }
static void net_err_cb(void *arg, err_t err) { lnet_userdata *ud = (lnet_userdata*)arg; if (!ud || ud->type != TYPE_TCP_CLIENT || ud->self_ref == LUA_NOREF) return; ud->pcb = NULL; // Will be freed at LWIP level lua_State *L = lua_getstate(); int ref; if (err != ERR_OK && ud->client.cb_reconnect_ref != LUA_NOREF) ref = ud->client.cb_reconnect_ref; else ref = ud->client.cb_disconnect_ref; if (ref != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ud->self_ref); lua_pushinteger(L, err); lua_call(L, 2, 0); } if (ud->client.wait_dns == 0) { lua_gc(L, LUA_GCSTOP, 0); luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref); ud->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); } }
static void websocketclient_onCloseCallback(ws_info *ws, int errorCode) { NODE_DBG("websocketclient_onCloseCallback\n"); lua_State *L = lua_getstate(); if (ws == NULL || ws->reservedData == NULL) { luaL_error(L, "Client websocket is nil.\n"); return; } ws_data *data = (ws_data *) ws->reservedData; if (data->onClose != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, data->onClose); // load the callback function lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument lua_pushnumber(L, errorCode); // pass the error code, #2 callback argument lua_call(L, 2, 0); } // free self-reference to allow gc (no futher callback will be called until next ws:connect()) lua_gc(L, LUA_GCSTOP, 0); // required to avoid freeing ws_data luaL_unref(L, LUA_REGISTRYINDEX, data->self_ref); data->self_ref = LUA_NOREF; lua_gc(L, LUA_GCRESTART, 0); }
static void on_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, uint16_t port) { (void)port; sntp_dbg("sntp: on_recv\n"); lua_State *L = lua_getstate(); if (!state || state->pcb != pcb) { // "impossible", but don't leak if it did happen somehow... udp_remove (pcb); pbuf_free (p); return; } if (!p) return; if (p->len < sizeof (ntp_frame_t)) { pbuf_free (p); return; // not an ntp frame, ignore } // make sure we have an aligned copy to work from ntp_frame_t ntp; os_memcpy (&ntp, p->payload, sizeof (ntp)); pbuf_free (p); sntp_dbg("sntp: transmit timestamp: %u, %u\n", ntp.xmit.sec, ntp.xmit.frac); // sanity checks before we touch our clocks ip_addr_t anycast; NTP_ANYCAST_ADDR(&anycast); if (server.addr != anycast.addr && server.addr != addr->addr) return; // unknown sender, ignore if (ntp.origin.sec != state->cookie.sec || ntp.origin.frac != state->cookie.frac) return; // unsolicited message, ignore if (ntp.LI == 3) return; // server clock not synchronized (why did it even respond?!) server.addr = addr->addr; ntp.origin.sec = ntohl (ntp.origin.sec); ntp.origin.frac = ntohl (ntp.origin.frac); ntp.recv.sec = ntohl (ntp.recv.sec); ntp.recv.frac = ntohl (ntp.recv.frac); ntp.xmit.sec = ntohl (ntp.xmit.sec); ntp.xmit.frac = ntohl (ntp.xmit.frac); const uint32_t UINT32_MAXI = (uint32_t)-1; const uint64_t MICROSECONDS = 1000000ull; const uint32_t NTP_TO_UNIX_EPOCH = 2208988800ul; bool have_cb = (state->sync_cb_ref != LUA_NOREF); // if we have rtctime, do higher resolution delta calc, else just use // the transmit timestamp #ifdef LUA_USE_MODULES_RTCTIME struct rtc_timeval tv; rtctime_gettimeofday (&tv); ntp_timestamp_t dest; dest.sec = tv.tv_sec; dest.frac = (MICROSECONDS * tv.tv_usec) / UINT32_MAXI; // Compensation as per RFC2030 int64_t delta_s = (((int64_t)ntp.recv.sec - ntp.origin.sec) + ((int64_t)ntp.xmit.sec - dest.sec)) / 2; int64_t delta_f = (((int64_t)ntp.recv.frac - ntp.origin.frac) + ((int64_t)ntp.xmit.frac - dest.frac)) / 2; dest.sec += delta_s; if (delta_f + dest.frac < 0) { delta_f += UINT32_MAXI; --dest.sec; } else if (delta_f + dest.frac > UINT32_MAXI) { delta_f -= UINT32_MAXI; ++dest.sec; } dest.frac += delta_f; tv.tv_sec = dest.sec - NTP_TO_UNIX_EPOCH; tv.tv_usec = (MICROSECONDS * dest.frac) / UINT32_MAXI; rtctime_settimeofday (&tv); if (have_cb) { lua_rawgeti (L, LUA_REGISTRYINDEX, state->sync_cb_ref); lua_pushnumber (L, tv.tv_sec); lua_pushnumber (L, tv.tv_usec); } #else if (have_cb) { lua_rawgeti (L, LUA_REGISTRYINDEX, state->sync_cb_ref); lua_pushnumber (L, ntp.xmit.sec - NTP_TO_UNIX_EPOCH); lua_pushnumber (L, (MICROSECONDS * ntp.xmit.frac) / UINT32_MAXI); } #endif cleanup (L); if (have_cb) { lua_pushstring (L, ipaddr_ntoa (&server)); lua_call (L, 3, 0); } }