From 36d80f19de58c5387c7c5b1286cb730f7e62d1ae Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Sun, 4 Dec 2011 17:29:27 +0200 Subject: [PATCH] continuing the integration, compiling on LM3S now, not tested --- src/modules/net.c | 282 +++++++++++++++++++++++++++++------ src/platform/lm3s/platform.c | 8 + 2 files changed, 247 insertions(+), 43 deletions(-) diff --git a/src/modules/net.c b/src/modules/net.c index 34a358d0..17000be4 100644 --- a/src/modules/net.c +++ b/src/modules/net.c @@ -1,80 +1,141 @@ // Module for interfacing with network functions (elua_net.h) + #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "platform.h" #include "auxmods.h" #include "elua_net.h" -#include "common.h" #include #include #include #include "lrotable.h" +#include "common.h" #include "platform_conf.h" -//#ifdef BUILD_UIP -#if 0 +#ifdef BUILD_UIP -// Lua: sock, remoteip, err = accept( port, [timeout], [timer_id] ) +#define lua_puship( L, ip ) lua_pushnumber( L, ( lua_Number )ip ) + +#define NET_META_NAME "eLua.net" +#define sock_check( L ) ( sock_t* )luaL_checkudata( L, 1, NET_META_NAME ) + +typedef struct +{ + int sock; +} sock_t; + +// Lua: sock, remoteip, err = accept( port, [bufsize], [timeout], [timer_id] ) static int net_accept( lua_State *L ) { u16 port = ( u16 )luaL_checkinteger( L, 1 ); + unsigned bufsize = ( unsigned )luaL_optinteger( L, 2, 0 ); unsigned timer_id = PLATFORM_TIMER_SYS_ID; timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; elua_net_ip remip; - int sock; + int res; + sock_t *s; - cmn_get_timeout_data( L, 2, &timeout, &timer_id ); - lua_pushinteger( L, sock = elua_accept( port, timer_id, timeout, &remip ) ); - lua_pushinteger( L, remip.ipaddr ); - lua_pushinteger( L, elua_net_get_last_err( sock ) ); - return 3; + cmn_get_timeout_data( L, 3, &timeout, &timer_id ); + if( ( res = elua_net_accept( port, bufsize, timer_id, timeout, &remip ) ) != -1 ) + { + s = ( sock_t* )lua_newuserdata( L, sizeof( sock_t ) ); + s->sock = res; + luaL_getmetatable( L, NET_META_NAME ); + lua_setmetatable( L, -2 ); + lua_puship( L, remip.ipaddr ); + lua_pushinteger( L, elua_net_get_last_err( res ) ); + return 3; + } + else + return 0; } // Lua: sock = socket( type ) static int net_socket( lua_State *L ) { int type = ( int )luaL_checkinteger( L, 1 ); + int res; + sock_t *s; - lua_pushinteger( L, elua_net_socket( type ) ); + res = elua_net_socket( type ); + if( res != ELUA_NET_INVALID_SOCKET ) + { + s = ( sock_t* )lua_newuserdata( L, sizeof( sock_t ) ); + s->sock = res; + luaL_getmetatable( L, NET_META_NAME ); + lua_setmetatable( L, -2 ); + return 1; + } + else + return 0; +} + +// Lua: set_buffer( sock, size ) +// Use '0' to disable buffering +static int net_set_buffer( lua_State *L ) +{ + sock_t *s = sock_check( L ); + unsigned bufsize = ( unsigned )luaL_checkinteger( L, 2 ); + + if( elua_net_set_buffer( s->sock, bufsize ) == 0 ) + return luaL_error( L, "unable to set buffer on socket %d", s->sock ); + return 0; +} + +// Lua: res = set_split( sock, [split_char]) +// Defaults to 'no split' if not specified +static int net_set_split( lua_State *L ) +{ + sock_t *s = sock_check( L ); + int schar = luaL_optinteger( L, 2, ELUA_NET_NO_SPLIT ); + + lua_pushboolean( L, elua_net_set_split( s->sock, schar ) ); return 1; } // Lua: res = close( socket ) static int net_close( lua_State* L ) { - int sock = ( int )luaL_checkinteger( L, 1 ); - - lua_pushinteger( L, elua_net_close( sock ) ); + sock_t *s = sock_check( L ); + int res; + + if( ( res = elua_net_close( s->sock ) ) != 0 ) + s->sock = -1; + lua_pushinteger( L, res ); return 1; } // Lua: res, err = send( sock, str ) static int net_send( lua_State* L ) { - int sock = ( int )luaL_checkinteger( L, 1 ); + sock_t *s = sock_check( L ); const char *buf; size_t len; luaL_checktype( L, 2, LUA_TSTRING ); buf = lua_tolstring( L, 2, &len ); - lua_pushinteger( L, elua_net_send( sock, buf, len ) ); - lua_pushinteger( L, elua_net_get_last_err( sock ) ); + lua_pushinteger( L, elua_net_send( s->sock, buf, len ) ); + lua_pushinteger( L, elua_net_get_last_err( s->sock ) ); return 2; } -// Lua: err = connect( sock, iptype, port ) +// Lua: err = connect( sock, iptype, port, [timeout], [timer_id] ) // "iptype" is actually an int returned by "net.packip" static int net_connect( lua_State *L ) { elua_net_ip ip; - int sock = ( int )luaL_checkinteger( L, 1 ); - u16 port = ( int )luaL_checkinteger( L, 3 ); + sock_t *s = sock_check( L ); + u16 port = ( u16 )luaL_checkinteger( L, 3 ); + unsigned timer_id = PLATFORM_TIMER_SYS_ID; + timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; - ip.ipaddr = ( u32 )luaL_checkinteger( L, 2 ); - elua_net_connect( sock, ip, port ); - lua_pushinteger( L, elua_net_get_last_err( sock ) ); - return 1; + cmn_get_timeout_data( L, 4, &timeout, &timer_id ); + luaL_checkinteger( L, 2 ); + ip.ipaddr = ( u32 )luaL_checknumber( L, 2 ); + elua_net_connect( s->sock, ip, port, timer_id, timeout ); + lua_pushinteger( L, elua_net_get_last_err( s->sock ) ); + return 1; } // Lua: data = packip( ip0, ip1, ip2, ip3 ), or @@ -107,7 +168,7 @@ static int net_packip( lua_State *L ) ip.ipbytes[ i ] = ( u8 )temp[ i ]; } } - lua_pushinteger( L, ip.ipaddr ); + lua_puship( L, ip.ipaddr ); return 1; } @@ -119,7 +180,8 @@ static int net_unpackip( lua_State *L ) unsigned i; const char* fmt; - ip.ipaddr = ( u32 )luaL_checkinteger( L, 1 ); + luaL_checkinteger( L, 1 ); + ip.ipaddr = ( u32 )luaL_checknumber( L, 1 ); fmt = luaL_checkstring( L, 2 ); if( !strcmp( fmt, "*n" ) ) { @@ -137,32 +199,21 @@ static int net_unpackip( lua_State *L ) return luaL_error( L, "invalid format" ); } -// Lua: res, err = recv( sock, maxsize, [timeout], [timer_id] ) or -// res, err = recv( sock, "*l", [timeout], [timer_id] ) +// Lua: res, err = recv( sock, maxsize, [timeout], [timer_id] ) static int net_recv( lua_State *L ) { - int sock = ( int )luaL_checkinteger( L, 1 ); - elua_net_size maxsize; - s16 lastchar = ELUA_NET_NO_LASTCHAR; + sock_t *s = sock_check( L ); + elua_net_size maxsize = ( elua_net_size )luaL_checkinteger( L, 2 ); unsigned timer_id = PLATFORM_TIMER_SYS_ID; timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; luaL_Buffer net_recv_buff; - if( lua_isnumber( L, 2 ) ) // invocation with maxsize - maxsize = ( elua_net_size )luaL_checkinteger( L, 2 ); - else // invocation with line mode - { - if( strcmp( luaL_checkstring( L, 2 ), "*l" ) ) - return luaL_error( L, "invalid second argument to recv" ); - lastchar = '\n'; - maxsize = BUFSIZ; - } cmn_get_timeout_data( L, 3, &timeout, &timer_id ); // Initialize buffer luaL_buffinit( L, &net_recv_buff ); - elua_net_recvbuf( sock, &net_recv_buff, maxsize, lastchar, timer_id, timeout ); + elua_net_recvbuf( s->sock, &net_recv_buff, maxsize, timer_id, timeout ); luaL_pushresult( &net_recv_buff ); - lua_pushinteger( L, elua_net_get_last_err( sock ) ); + lua_pushinteger( L, elua_net_get_last_err( s->sock ) ); return 2; } @@ -173,10 +224,135 @@ static int net_lookup( lua_State* L ) elua_net_ip res; res = elua_net_lookup( name ); - lua_pushinteger( L, res.ipaddr ); + lua_puship( L, res.ipaddr ); return 1; } +// Lua: ip, netmask, dns, gw = netcfg() +// Returns 'nil' if the network isn't initialized yet +static int net_netcfg( lua_State *L ) +{ + elua_net_ip ip; + + ip = elua_net_get_config( ELUA_NET_CFG_IP ); + if( ip.ipaddr == 0 ) + return 0; + lua_puship( L, ip.ipaddr ); + ip = elua_net_get_config( ELUA_NET_CFG_NETMASK ); + lua_puship( L, ip.ipaddr ); + ip = elua_net_get_config( ELUA_NET_CFG_DNS ); + lua_puship( L, ip.ipaddr ); + ip = elua_net_get_config( ELUA_NET_CFG_GW ); + lua_puship( L, ip.ipaddr ); + return 4; +} + +// Lua: res, err = sendto( socket, data, remoteip, remoteport ) +static int net_sendto( lua_State *L ) +{ + sock_t *s = sock_check( L ); + u16 port = ( u16 )luaL_checkinteger( L, 4 ); + elua_net_ip ip; + const char *buf; + size_t len; + + luaL_checktype( L, 2, LUA_TSTRING ); + buf = lua_tolstring( L, 2, &len ); + luaL_checkinteger( L, 3 ); + ip.ipaddr = ( u32 )luaL_checknumber( L, 3 ); + lua_pushinteger( L, elua_net_sendto( s->sock, buf, len, ip, port ) ); + lua_pushinteger( L, elua_net_get_last_err( s->sock ) ); + return 2; +} + +// Lua: res, err, remoteip, remoteport = recvfrom( sock, maxsize, [timeout], [timer_id] ) +static int net_recvfrom( lua_State *L ) +{ + sock_t *s = sock_check( L ); + elua_net_size maxsize = ( elua_net_size )luaL_checkinteger( L, 2 ); + unsigned timer_id = PLATFORM_TIMER_SYS_ID; + timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; + luaL_Buffer net_recv_buff; + elua_net_ip remoteip; + u16 remoteport; + + cmn_get_timeout_data( L, 3, &timeout, &timer_id ); + // Initialize buffer + luaL_buffinit( L, &net_recv_buff ); + elua_net_recvfrombuf( s->sock, &net_recv_buff, maxsize, &remoteip, &remoteport, timer_id, timeout ); + luaL_pushresult( &net_recv_buff ); + lua_pushinteger( L, elua_net_get_last_err( s->sock ) ); + lua_puship( L, remoteip.ipaddr ); + lua_pushinteger( L, remoteport ); + return 4; +} + +// Lua: res = net.expect( sock, s, [timeout], [timer_id] ) +static int net_expect( lua_State *L ) +{ + const char *se; + sock_t *s = sock_check( L ); + size_t len; + timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; + unsigned timer_id = PLATFORM_TIMER_SYS_ID; + + cmn_get_timeout_data( L, 3, &timeout, &timer_id ); + se = luaL_checklstring( L, 2, &len ); + lua_pushboolean( L, elua_net_expect( s->sock, ( const u8* )se, len, timer_id, timeout ) ); + return 1; +} + +// Lua: buf = net.readto( sock, s, [timeout], [timer_id] ) +static int net_readto( lua_State *L ) +{ + const char *se; + size_t len; + timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; + unsigned timer_id = PLATFORM_TIMER_SYS_ID; + sock_t *s = sock_check( L ); + luaL_Buffer b; + + se = luaL_checklstring( L, 2, &len ); + cmn_get_timeout_data( L, 3, &timeout, &timer_id ); + luaL_buffinit( L, &b ); + elua_net_readto( s->sock, &b, ( const u8* )se, len, timer_id, timeout ); + luaL_pushresult( &b ); + return 1; +} + +// Lua: buf = net.read_tags( sock, tag1, tag2, [timeout], [timer_id] ) +static int net_read_tags( lua_State *L ) +{ + const char *tag1, *tag2; + size_t len1, len2; + timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT; + unsigned timer_id = PLATFORM_TIMER_SYS_ID; + luaL_Buffer b; + sock_t *s = sock_check( L ); + + tag1 = luaL_checklstring( L, 2, &len1 ); + tag2 = luaL_checklstring( L, 3, &len2 ); + cmn_get_timeout_data( L, 4, &timeout, &timer_id ); + luaL_buffinit( L, &b ); + if( elua_net_expect( s->sock, ( const u8* )tag1, len1, timer_id, timeout ) ) + elua_net_readto( s->sock, &b, ( const u8* )tag2, len2, timer_id, timeout ); + luaL_pushresult( &b ); + return 1; +} + +// Garbage collection function for sockets +static int socket_gc( lua_State *L ) +{ + sock_t *s = sock_check( L ); + + if( s && s->sock != -1 ) + { + elua_net_close( s->sock ); + s->sock = -1; + } + return 0; +} + // Module function map #define MIN_OPT_LEVEL 2 #include "lrodefs.h" @@ -187,10 +363,18 @@ const LUA_REG_TYPE net_map[] = { LSTRKEY( "unpackip" ), LFUNCVAL( net_unpackip ) }, { LSTRKEY( "connect" ), LFUNCVAL( net_connect ) }, { LSTRKEY( "socket" ), LFUNCVAL( net_socket ) }, + { LSTRKEY( "set_buffer" ), LFUNCVAL( net_set_buffer ) }, + { LSTRKEY( "set_split" ), LFUNCVAL( net_set_split ) }, { LSTRKEY( "close" ), LFUNCVAL( net_close ) }, { LSTRKEY( "send" ), LFUNCVAL( net_send ) }, { LSTRKEY( "recv" ), LFUNCVAL( net_recv ) }, { LSTRKEY( "lookup" ), LFUNCVAL( net_lookup ) }, + { LSTRKEY( "netcfg" ), LFUNCVAL( net_netcfg ) }, + { LSTRKEY( "sendto" ), LFUNCVAL( net_sendto ) }, + { LSTRKEY( "recvfrom" ), LFUNCVAL( net_recvfrom ) }, + { LSTRKEY( "expect" ), LFUNCVAL( net_expect ) }, + { LSTRKEY( "readto" ), LFUNCVAL( net_readto ) }, + { LSTRKEY( "read_tags" ), LFUNCVAL( net_read_tags ) }, #if LUA_OPTIMIZE_MEMORY > 0 { LSTRKEY( "SOCK_STREAM" ), LNUMVAL( ELUA_NET_SOCK_STREAM ) }, { LSTRKEY( "SOCK_DGRAM" ), LNUMVAL( ELUA_NET_SOCK_DGRAM ) }, @@ -201,14 +385,24 @@ const LUA_REG_TYPE net_map[] = { LSTRKEY( "ERR_OVERFLOW" ), LNUMVAL( ELUA_NET_ERR_OVERFLOW ) }, { LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) }, { LSTRKEY( "NO_TIMEOUT" ), LNUMVAL( 0 ) }, + { LSTRKEY( "INVALID_SOCKET" ), LNUMVAL( ELUA_NET_INVALID_SOCKET ) }, { LSTRKEY( "INF_TIMEOUT" ), LNUMVAL( PLATFORM_TIMER_INF_TIMEOUT ) }, + { LSTRKEY( "NO_SPLIT" ), LNUMVAL( ELUA_NET_NO_SPLIT ) }, #endif { LNILKEY, LNILVAL } }; +static const LUA_REG_TYPE socket_mt_map[] = +{ + { LSTRKEY( "__gc" ), LFUNCVAL( socket_gc ) }, + { LNILKEY, LNILVAL } +}; + LUALIB_API int luaopen_net( lua_State *L ) { #if LUA_OPTIMIZE_MEMORY > 0 + // Create default font metatable + luaL_rometatable( L, NET_META_NAME, ( void* )socket_mt_map ); return 0; #else // #if LUA_OPTIMIZE_MEMORY > 0 luaL_register( L, AUXLIB_NET, net_map ); @@ -223,7 +417,9 @@ LUALIB_API int luaopen_net( lua_State *L ) MOD_REG_NUMBER( L, "ERR_OVERFLOW", ELUA_NET_ERR_OVERFLOW ); MOD_REG_NUMBER( L, "SYS_TIMER", PLATFORM_TIMER_SYS_ID ); MOD_REG_NUMBER( L, "NO_TIMEOUT", 0 ); + MOD_REG_NUMBER( L, "INVALID_SOCKET", ELUA_NET_INVALID_SOCKET ); MOD_REG_NUMBER( L, "INF_TIMEOUT", PLATFORM_TIMER_INF_TIMEOUT ); + MOD_REG_NUMEBR( L, "NO_SPLIT", ELUA_NET_NO_SPLIT ); return 1; #endif // #if LUA_OPTIMIZE_MEMORY > 0 diff --git a/src/platform/lm3s/platform.c b/src/platform/lm3s/platform.c index bbc2fa4f..de42bdfc 100644 --- a/src/platform/lm3s/platform.c +++ b/src/platform/lm3s/platform.c @@ -991,6 +991,14 @@ int platform_eth_get_link_status() return ( EthernetPHYRead( ETH_BASE, PHY_MR1 ) & PHY_MR1_LINK ) ? PLATFORM_ETH_LINK_UP : PLATFORM_ETH_LINK_DOWN; } +void platform_eth_set_interrupt( int state ) +{ + if( state == PLATFORM_ETH_INT_ENABLE ) + MAP_IntEnable( INT_ETH ); + else + MAP_IntDisable( INT_ETH ); +} + u32 platform_eth_get_elapsed_time() { if( eth_timer_fired )