mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
Do a better job of handling failure to connect or loss of connection:
look for errors coming with FD_CONNECT message, look for FD_CLOSE message, and inform relay when connection is lost so its reconnect logic is triggered. This seems at least to handle the case where I kill the relay mid-game.
This commit is contained in:
parent
cd2da3b1c3
commit
a3b326205a
3 changed files with 44 additions and 18 deletions
|
@ -3026,11 +3026,15 @@ got_data_proc( XP_U8* data, XP_U16 len, void* closure )
|
||||||
} /* got_data_proc */
|
} /* got_data_proc */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sock_state_change( void* closure, CeConnState state )
|
sock_state_change( void* closure, CeConnState oldState, CeConnState newState )
|
||||||
{
|
{
|
||||||
CEAppGlobals* globals = (CEAppGlobals*)closure;
|
CEAppGlobals* globals = (CEAppGlobals*)closure;
|
||||||
globals->socketState = state;
|
globals->socketState = newState;
|
||||||
InvalidateRect( globals->hWnd, &globals->relayStatusR, TRUE /* erase */ );
|
InvalidateRect( globals->hWnd, &globals->relayStatusR, TRUE /* erase */ );
|
||||||
|
|
||||||
|
if ( newState < oldState ) {
|
||||||
|
comms_transportFailed( globals->game.comms );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3174,6 +3178,7 @@ ce_util_userError( XW_UtilCtxt* uc, UtilErrID id )
|
||||||
break;
|
break;
|
||||||
case ERR_RELAY_BASE + XWRELAY_ERROR_HEART_OTHER:
|
case ERR_RELAY_BASE + XWRELAY_ERROR_HEART_OTHER:
|
||||||
case ERR_RELAY_BASE + XWRELAY_ERROR_LOST_OTHER:
|
case ERR_RELAY_BASE + XWRELAY_ERROR_LOST_OTHER:
|
||||||
|
case ERR_RELAY_BASE + XWRELAY_ERROR_OTHER_DISCON:
|
||||||
resID = IDS_XWRELAY_ERROR_HEART_OTHER;
|
resID = IDS_XWRELAY_ERROR_HEART_OTHER;
|
||||||
break;
|
break;
|
||||||
/* Same string as above for now */
|
/* Same string as above for now */
|
||||||
|
|
|
@ -137,7 +137,9 @@ send_packet_if( CeSocketWrapper* self )
|
||||||
{
|
{
|
||||||
const XP_U8* packet;
|
const XP_U8* packet;
|
||||||
XP_U16 len;
|
XP_U16 len;
|
||||||
if ( self->socket != -1 && bqGet( &self->queueOut, &packet, &len ) ) {
|
if ( self->socket == -1 ) {
|
||||||
|
XP_LOGF( "%s: have no socket", __func__ );
|
||||||
|
} else if ( bqGet( &self->queueOut, &packet, &len ) ) {
|
||||||
if ( sendLenAndData( self, packet, len ) ) {
|
if ( sendLenAndData( self, packet, len ) ) {
|
||||||
/* successful send. Remove our copy */
|
/* successful send. Remove our copy */
|
||||||
bqRemoveOne( &self->queueOut );
|
bqRemoveOne( &self->queueOut );
|
||||||
|
@ -154,7 +156,7 @@ stateChanged( CeSocketWrapper* self, CeConnState newState )
|
||||||
XP_LOGF( "%s: %s -> %s", __func__, ConnState2Str( curState ),
|
XP_LOGF( "%s: %s -> %s", __func__, ConnState2Str( curState ),
|
||||||
ConnState2Str( newState ) );
|
ConnState2Str( newState ) );
|
||||||
|
|
||||||
(*self->stateProc)( self->closure, newState );
|
(*self->stateProc)( self->closure, curState, newState );
|
||||||
|
|
||||||
switch( newState ) {
|
switch( newState ) {
|
||||||
case CE_IPST_START:
|
case CE_IPST_START:
|
||||||
|
@ -188,7 +190,8 @@ connectSocket( CeSocketWrapper* self )
|
||||||
/* Put socket in non-blocking mode */
|
/* Put socket in non-blocking mode */
|
||||||
if ( 0 != WSAAsyncSelect( sock, self->hWnd,
|
if ( 0 != WSAAsyncSelect( sock, self->hWnd,
|
||||||
XWWM_SOCKET_EVT,
|
XWWM_SOCKET_EVT,
|
||||||
FD_READ | FD_WRITE | FD_CONNECT ) ) {
|
FD_READ | FD_WRITE | FD_CONNECT
|
||||||
|
| FD_CLOSE ) ) {
|
||||||
XP_WARNF( "WSAAsyncSelect failed" );
|
XP_WARNF( "WSAAsyncSelect failed" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +204,7 @@ connectSocket( CeSocketWrapper* self )
|
||||||
sizeof(name), NULL, NULL,
|
sizeof(name), NULL, NULL,
|
||||||
NULL, NULL ) ) {
|
NULL, NULL ) ) {
|
||||||
self->socket = sock;
|
self->socket = sock;
|
||||||
stateChanged( self, CE_IPST_CONNECTED );
|
stateChanged( self, CE_IPST_CONNECTING );
|
||||||
} else if ( WSAEWOULDBLOCK == WSAGetLastError() ) {
|
} else if ( WSAEWOULDBLOCK == WSAGetLastError() ) {
|
||||||
stateChanged( self, CE_IPST_CONNECTING );
|
stateChanged( self, CE_IPST_CONNECTING );
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,9 +242,12 @@ closeConnection( CeSocketWrapper* self )
|
||||||
closesocket( self->socket );
|
closesocket( self->socket );
|
||||||
self->socket = -1;
|
self->socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
stateChanged( self, CE_IPST_START );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bqRemoveAll( &self->queueOut );
|
||||||
|
|
||||||
|
XP_ASSERT( self->socket == -1 );
|
||||||
|
stateChanged( self, CE_IPST_START );
|
||||||
} /* closeConnection */
|
} /* closeConnection */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -438,17 +444,28 @@ ce_sockwrap_event( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 0 != (FD_CONNECT & event) ) {
|
if ( 0 != (FD_CONNECT & event) ) {
|
||||||
XP_LOGF( "%s: got FD_CONNECT", __func__ );
|
int err = WSAGETSELECTERROR(lParam);
|
||||||
|
XP_LOGF( "%s: got FD_CONNECT; err=%d", __func__, err );
|
||||||
event &= ~FD_CONNECT;
|
event &= ~FD_CONNECT;
|
||||||
self->socket = socket;
|
if ( 0 == err ) {
|
||||||
stateChanged( self, CE_IPST_CONNECTED );
|
XP_ASSERT( self->socket == -1 || self->socket == socket );
|
||||||
|
self->socket = socket;
|
||||||
|
stateChanged( self, CE_IPST_CONNECTED );
|
||||||
|
} else {
|
||||||
|
closeConnection( self );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 != (FD_CLOSE & event) ) {
|
||||||
|
event &= ~FD_CLOSE;
|
||||||
|
closeConnection( self );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 0 != event ) {
|
if ( 0 != event ) {
|
||||||
XP_WARNF( "%s: unexpected bits left: 0x%lx", __func__, event );
|
XP_WARNF( "%s: unexpected bits left: 0x%lx", __func__, event );
|
||||||
}
|
}
|
||||||
return draw;
|
return draw;
|
||||||
}
|
} /* ce_sockwrap_event */
|
||||||
|
|
||||||
XP_S16
|
XP_S16
|
||||||
ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len,
|
ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len,
|
||||||
|
@ -457,8 +474,8 @@ ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len,
|
||||||
XP_S16 nSent = -1; /* error */
|
XP_S16 nSent = -1; /* error */
|
||||||
XP_LOGF( "%s(len=%d)", __func__, len );
|
XP_LOGF( "%s(len=%d)", __func__, len );
|
||||||
|
|
||||||
/* If the address has changed, we need to close the connection. Send
|
/* If the address has changed, we need to close the connection, then call
|
||||||
thread will take care of opening it again. */
|
getHostAddr() to kick off the async reconnect process. */
|
||||||
XP_ASSERT( addr->conType == COMMS_CONN_RELAY );
|
XP_ASSERT( addr->conType == COMMS_CONN_RELAY );
|
||||||
if ( 0 != XP_STRCMP( addr->u.ip_relay.hostName,
|
if ( 0 != XP_STRCMP( addr->u.ip_relay.hostName,
|
||||||
self->addrRec.u.ip_relay.hostName )
|
self->addrRec.u.ip_relay.hostName )
|
||||||
|
@ -468,9 +485,13 @@ ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len,
|
||||||
closeConnection( self );
|
closeConnection( self );
|
||||||
XP_MEMCPY( &self->addrRec, addr, sizeof(self->addrRec) );
|
XP_MEMCPY( &self->addrRec, addr, sizeof(self->addrRec) );
|
||||||
|
|
||||||
getHostAddr( self );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( CE_IPST_START == self->connState ) {
|
||||||
|
getHostAddr( self ); /* kicks off connection process */
|
||||||
|
}
|
||||||
|
/* What if we're stuck in some other state? Kick those here too? */
|
||||||
|
|
||||||
if ( bqAdd( &self->queueOut, buf, len ) ) {
|
if ( bqAdd( &self->queueOut, buf, len ) ) {
|
||||||
send_packet_if( self );
|
send_packet_if( self );
|
||||||
nSent = len;
|
nSent = len;
|
||||||
|
|
|
@ -34,11 +34,11 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct CeSocketWrapper CeSocketWrapper; /* forward */
|
typedef struct CeSocketWrapper CeSocketWrapper; /* forward */
|
||||||
typedef XP_Bool (*DataRecvProc)( XP_U8* data, XP_U16 len, void* closure );
|
typedef XP_Bool (*DataRecvProc)( XP_U8* data, XP_U16 len, void* closure );
|
||||||
typedef void (*StateChangeProc)( void* closure, CeConnState state );
|
typedef void (*StateChangeProc)( void* closure, CeConnState oldState,
|
||||||
|
CeConnState newState );
|
||||||
|
|
||||||
CeSocketWrapper* ce_sockwrap_new( MPFORMAL HWND hWnd, DataRecvProc dataCB,
|
CeSocketWrapper* ce_sockwrap_new( MPFORMAL HWND hWnd, DataRecvProc dataCB,
|
||||||
StateChangeProc stateCB,
|
StateChangeProc stateCB, void* globals );
|
||||||
void* globals );
|
|
||||||
void ce_sockwrap_delete( CeSocketWrapper* self );
|
void ce_sockwrap_delete( CeSocketWrapper* self );
|
||||||
|
|
||||||
void ce_sockwrap_hostname( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam );
|
void ce_sockwrap_hostname( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam );
|
||||||
|
|
Loading…
Reference in a new issue