mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
Fixed elua_uip.c behaviour for accept calls
Allow new incomming connections to be queued between accept calls. This allows to build servers which accept several connection and server them all with the help of coroutines.
This commit is contained in:
parent
1c744f03eb
commit
13a633b5ca
131
src/elua_uip.c
131
src/elua_uip.c
@ -259,9 +259,22 @@ static elua_net_size elua_uip_telnet_prep_send( const char* src, elua_net_size s
|
||||
// eLua UIP application (used to implement the eLua TCP/IP services)
|
||||
|
||||
// Special handling for "accept"
|
||||
volatile static u8 elua_uip_accept_request;
|
||||
volatile static int elua_uip_accept_sock;
|
||||
volatile static elua_net_ip elua_uip_accept_remote;
|
||||
//volatile static u8 elua_uip_accept_request;
|
||||
//volatile static int elua_uip_accept_sock;
|
||||
//volatile static elua_net_ip elua_uip_accept_remote;
|
||||
|
||||
typedef struct {
|
||||
u8 accept_request; // 0=accepted 1=pending, 255=not used
|
||||
int sock; // socket number when accepted
|
||||
elua_net_ip remote; // remote IP
|
||||
int port; // local port bound to
|
||||
|
||||
} elua_uip_accept_pending_t;
|
||||
|
||||
static elua_uip_accept_pending_t elua_uip_accept_pending[UIP_CONF_MAX_CONNECTIONS];
|
||||
|
||||
static struct uip_conn *elua_net_connecting=NULL;
|
||||
|
||||
|
||||
void elua_uip_appcall()
|
||||
{
|
||||
@ -282,8 +295,14 @@ void elua_uip_appcall()
|
||||
|
||||
if( uip_connected() )
|
||||
{
|
||||
// check if we are currenty in a conncet call and the socket
|
||||
// is the connection is the right one...
|
||||
if ( s->state == ELUA_UIP_STATE_CONNECT && uip_conn==elua_net_connecting )
|
||||
s->state = ELUA_UIP_STATE_IDLE;
|
||||
|
||||
|
||||
#ifdef BUILD_CON_TCP
|
||||
if( uip_conn->lport == HTONS( ELUA_NET_TELNET_PORT ) ) // special case: telnet server
|
||||
else if( uip_conn->lport == HTONS( ELUA_NET_TELNET_PORT ) ) // special case: telnet server
|
||||
{
|
||||
if( elua_uip_telnet_socket != -1 )
|
||||
{
|
||||
@ -293,17 +312,29 @@ void elua_uip_appcall()
|
||||
else
|
||||
elua_uip_telnet_socket = sockno;
|
||||
}
|
||||
else
|
||||
|
||||
#endif
|
||||
if( elua_uip_accept_request )
|
||||
else { // add to list of pending accepts
|
||||
int i;
|
||||
BOOL found=FALSE;
|
||||
for(i=0;i<UIP_CONF_MAX_CONNECTIONS && !found;i++)
|
||||
{
|
||||
elua_uip_accept_sock = sockno;
|
||||
elua_uip_accept_remote.ipwords[ 0 ] = uip_conn->ripaddr[ 0 ];
|
||||
elua_uip_accept_remote.ipwords[ 1 ] = uip_conn->ripaddr[ 1 ];
|
||||
elua_uip_accept_request = 0;
|
||||
if (elua_uip_accept_pending[i].accept_request!=1) {// free slot
|
||||
elua_uip_accept_pending[i].sock=sockno;
|
||||
elua_uip_accept_pending[i].remote.ipwords[0]=uip_conn->ripaddr[ 0 ];
|
||||
elua_uip_accept_pending[i].remote.ipwords[1]=uip_conn->ripaddr[ 1 ];
|
||||
elua_uip_accept_pending[i].accept_request=1;
|
||||
elua_uip_accept_pending[i].port= HTONS(uip_conn->lport);
|
||||
//printk("Pending accept for port %d, index %d\n", elua_uip_accept_pending[i].port,i);
|
||||
found=TRUE;
|
||||
}
|
||||
else if( s->state == ELUA_UIP_STATE_CONNECT )
|
||||
s->state = ELUA_UIP_STATE_IDLE;
|
||||
}
|
||||
if (!found) { // no free slot
|
||||
uip_close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uip_stop();
|
||||
return;
|
||||
}
|
||||
@ -465,6 +496,12 @@ void elua_uip_init( const struct uip_eth_addr *paddr )
|
||||
uip_init();
|
||||
uip_arp_init();
|
||||
|
||||
int i;
|
||||
for(i=0;i<UIP_CONF_MAX_CONNECTIONS;i++) {
|
||||
elua_uip_accept_pending[i].accept_request=255;
|
||||
}
|
||||
|
||||
|
||||
#ifdef BUILD_DHCPC
|
||||
dhcpc_init( paddr->addr, sizeof( *paddr ) );
|
||||
dhcpc_request();
|
||||
@ -625,10 +662,10 @@ int elua_net_get_last_err( int s )
|
||||
return pstate->res;
|
||||
}
|
||||
|
||||
// Accept a connection on the given port, return its socket id (and the IP of the remote host by side effect)
|
||||
int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip* pfrom )
|
||||
|
||||
// New TH: listen/unlistens a port
|
||||
int elua_listen(u16 port,BOOL flisten)
|
||||
{
|
||||
timer_data_type tmrstart = 0;
|
||||
int old_status;
|
||||
|
||||
if( !elua_uip_configured )
|
||||
@ -637,28 +674,72 @@ int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip
|
||||
if( port == ELUA_NET_TELNET_PORT )
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE );
|
||||
|
||||
uip_unlisten( htons( port ) );
|
||||
if (flisten)
|
||||
uip_listen( htons( port ) );
|
||||
|
||||
platform_cpu_set_global_interrupts( old_status );
|
||||
elua_uip_accept_sock = -1;
|
||||
elua_uip_accept_request = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int elua_net_find_pending(u16 port)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for(i=0;i<UIP_CONF_MAX_CONNECTIONS;i++)
|
||||
{
|
||||
if (elua_uip_accept_pending[i].accept_request==1
|
||||
&& elua_uip_accept_pending[i].port==port )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Accept a connection on the given port, return its socket id (and the IP of the remote host by side effect)
|
||||
int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip* pfrom )
|
||||
{
|
||||
timer_data_type tmrstart = 0;
|
||||
int old_status;
|
||||
|
||||
int i;
|
||||
|
||||
if( !elua_uip_configured )
|
||||
return -1;
|
||||
|
||||
elua_listen(port,TRUE); // Need to be changed....
|
||||
|
||||
if( to_us > 0 )
|
||||
tmrstart = platform_timer_start( timer_id );
|
||||
while( 1 )
|
||||
{
|
||||
if( elua_uip_accept_request == 0 )
|
||||
break;
|
||||
i=elua_net_find_pending(port);
|
||||
if( i >= 0 ) {
|
||||
*pfrom = elua_uip_accept_pending[i].remote;
|
||||
old_status=platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE );
|
||||
elua_uip_accept_pending[i].accept_request=0;
|
||||
platform_cpu_set_global_interrupts( old_status );
|
||||
return elua_uip_accept_pending[i].sock;
|
||||
}
|
||||
|
||||
if( to_us > 0 && platform_timer_get_diff_crt( timer_id, tmrstart ) >= to_us )
|
||||
{
|
||||
elua_uip_accept_request = 0;
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*pfrom = elua_uip_accept_remote;
|
||||
return elua_uip_accept_sock;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Connect to a specified machine
|
||||
int elua_net_connect( int s, elua_net_ip addr, u16 port )
|
||||
{
|
||||
@ -673,10 +754,12 @@ int elua_net_connect( int s, elua_net_ip addr, u16 port )
|
||||
// Initiate the connect call
|
||||
uip_ipaddr( ipaddr, addr.ipbytes[ 0 ], addr.ipbytes[ 1 ], addr.ipbytes[ 2 ], addr.ipbytes[ 3 ] );
|
||||
elua_prep_socket_state( pstate, NULL, 0, ELUA_NET_NO_LASTCHAR, ELUA_NET_ERR_OK, ELUA_UIP_STATE_CONNECT );
|
||||
if( uip_connect_socket( s, &ipaddr, htons( port ) ) == NULL )
|
||||
elua_net_connecting=uip_connect_socket( s, &ipaddr, htons( port ) ) ;
|
||||
if( elua_net_connecting == NULL )
|
||||
return -1;
|
||||
// And wait for it to finish
|
||||
while( pstate->state != ELUA_UIP_STATE_IDLE );
|
||||
elua_net_connecting=NULL;
|
||||
return pstate->res == ELUA_NET_ERR_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user