Closed ThibaudCognat closed 7 years ago
Have spent some time and realized it (with some code usage from PR #1233). Try out this patch:
diff --git a/app/lwip/app/espconn_udp.c b/app/lwip/app/espconn_udp.c
index 77ef471..9c8bc8e 100644
--- a/app/lwip/app/espconn_udp.c
+++ b/app/lwip/app/espconn_udp.c
@@ -308,6 +308,11 @@ espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
wifi_get_ip_info(0, &ipconfig);
}
+ precv->pespconn->proto.udp->remote_ip[0] = ip4_addr1_16(addr);
+ precv->pespconn->proto.udp->remote_ip[1] = ip4_addr2_16(addr);
+ precv->pespconn->proto.udp->remote_ip[2] = ip4_addr3_16(addr);
+ precv->pespconn->proto.udp->remote_ip[3] = ip4_addr4_16(addr);
+ precv->pespconn->proto.udp->remote_port = port;
precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
diff --git a/app/modules/net.c b/app/modules/net.c
index 8181b94..c515269 100644
--- a/app/modules/net.c
+++ b/app/modules/net.c
@@ -1067,26 +1067,44 @@ static int net_send( lua_State* L, const char* mt )
NODE_DBG(" sending data.\n");
#endif
- const char *payload = luaL_checklstring( L, 2, &l );
+ size_t stack = 2;
+
+ const char *payload = luaL_checklstring( L, stack, &l );
if (l>1460 || payload == NULL)
return luaL_error( L, "need <1460 payload" );
+ stack++;
- if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION){
- lua_pushvalue(L, 3); // copy argument (func) to the top of stack
- if(nud->cb_send_ref != LUA_NOREF)
- luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_send_ref);
- nud->cb_send_ref = luaL_ref(L, LUA_REGISTRYINDEX);
- }
// SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port
if (isserver && pesp_conn->type == ESPCONN_UDP)
{
- remot_info *pr = 0;
- if (espconn_get_connection_info (pesp_conn, &pr, 0) != ESPCONN_OK)
- return luaL_error (L, "remote ip/port unavailable");
- pesp_conn->proto.udp->remote_port = pr->remote_port;
- os_memmove (pesp_conn->proto.udp->remote_ip, pr->remote_ip, 4);
+
+ if ( lua_isnumber(L,stack) && lua_isstring(L,stack+1) )
+ {
+ size_t il = 16;
+ const unsigned short port = luaL_checkinteger( L, stack );
+ const char *domain = luaL_checklstring( L, stack+1, &il );
+
+ ip_addr_t ipaddr;
+ pesp_conn->proto.udp->remote_port = port;
+ ipaddr.addr = ipaddr_addr(domain);
+ os_memmove (pesp_conn->proto.udp->remote_ip, &ipaddr.addr, 4);
+ stack += 2;
+ } else {
+ remot_info *pr = 0;
+ if (espconn_get_connection_info (pesp_conn, &pr, 0) != ESPCONN_OK)
+ return luaL_error (L, "remote ip/port unavailable");
+ pesp_conn->proto.udp->remote_port = pr->remote_port;
+ os_memmove (pesp_conn->proto.udp->remote_ip, pr->remote_ip, 4);
+ }
+
// The remot_info apparently should *not* be os_free()d, fyi
}
+ if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
+ lua_pushvalue(L, stack); // copy argument (func) to the top of stack
+ if(nud->cb_send_ref != LUA_NOREF)
+ luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_send_ref);
+ nud->cb_send_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
#ifdef CLIENT_SSL_ENABLE
if(nud->secure)
espconn_secure_sent(pesp_conn, (unsigned char *)payload, l);
@@ -1355,28 +1373,45 @@ static int net_socket_unhold( lua_State* L )
}
// Lua: ip,port = sk:getpeer()
-static int net_socket_getpeer( lua_State* L )
+static int net_getpeer( lua_State* L, const char *mt)
{
lnet_userdata *nud;
- const char *mt = "net.socket";
+ int remote_port = 0;
+ uint8 *remote_ip;
+
nud = (lnet_userdata *)luaL_checkudata(L, 1, mt);
luaL_argcheck(L, nud, 1, "Server/Socket expected");
- if(nud!=NULL && nud->pesp_conn!=NULL ){
+ if (nud->pesp_conn!=NULL){
+ if (nud->pesp_conn->type == ESPCONN_UDP) {
+ remote_ip = nud->pesp_conn->proto.udp->remote_ip;
+ remote_port = nud->pesp_conn->proto.udp->remote_port;
+ } else if (nud->pesp_conn->type == ESPCONN_TCP) {
+ luaL_argcheck(L, c_strcmp(mt, "net.socket")==0, 1, "Cannot getpeer() a TCP server");
+ remote_ip = nud->pesp_conn->proto.tcp->remote_ip;
+ remote_port = nud->pesp_conn->proto.tcp->remote_port;
+ }
+ if (remote_port != 0) {
char temp[20] = {0};
- c_sprintf(temp, IPSTR, IP2STR( &(nud->pesp_conn->proto.tcp->remote_ip) ) );
- if ( nud->pesp_conn->proto.tcp->remote_port != 0 ) {
- lua_pushstring( L, temp );
- lua_pushinteger( L, nud->pesp_conn->proto.tcp->remote_port );
- } else {
- lua_pushnil( L );
- lua_pushnil( L );
- }
- } else {
- lua_pushnil( L );
- lua_pushnil( L );
+ c_sprintf(temp, IPSTR, IP2STR(remote_ip));
+ lua_pushstring( L, temp );
+ lua_pushinteger( L, remote_port );
+ return 2;
+ }
}
- return 2;
+ return 0;
+}
+
+// Lua: ip,port = sk:getpeer()
+static int net_udpserver_getpeer( lua_State* L )
+{
+ return net_getpeer(L, "net.server");
+}
+
+// Lua: ip,port = sk:getpeer()
+static int net_socket_getpeer( lua_State* L )
+{
+ return net_getpeer(L, "net.socket");
}
// Lua: socket:dns( string, function(ip) )
@@ -1708,6 +1743,7 @@ static const LUA_REG_TYPE net_server_map[] = {
{ LSTRKEY( "close" ), LFUNCVAL( net_server_close ) },
{ LSTRKEY( "on" ), LFUNCVAL( net_udpserver_on ) },
{ LSTRKEY( "send" ), LFUNCVAL( net_udpserver_send ) },
+ { LSTRKEY( "getpeer" ), LFUNCVAL( net_udpserver_getpeer ) },
//{ LSTRKEY( "delete" ), LFUNCVAL( net_server_delete ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_server_delete ) },
{ LSTRKEY( "__index" ), LROVAL( net_server_map ) },
Thanks for the quick and effective response
@djphoenix @ThibaudCognat can one of you prepare a PR for that?
@marcelstoer Part of this (got from #1233) was rejected (actually, not understood why). :sendto
method was discussed in another place and closed because deprecation of espconn layer (maybe at "net module reorganization" or "RTOS SDK", not remember...)
Diff above is from my local repository, it has many patches that not merged till now (with rboot and another enhancements).
@djphoenix I too would like to see a PR. And some documentation in the PR.
I think this issue was resolved with #1379 -> closed.
@ThibaudCognat @robertfoss feel free to try latest dev
so.
Missing feature
In the net module, it is impossible, or seems to be to keep a track on the UDP clients connected to the UDP server. A call to the method send actually sends a message to the last client from which it received a message. An interesting feature would be to be able to get the IP and port of a sender, and this way, select which client to send an response to.
Justification
This feature would be useful in a case where a server listens to requests, and must be able to answer to multiple clients, not necessarily in the order of the requests reception.
Workarounds
There is no apparent workaround, and that's why we are blocked in our implementations.