From 30145deba7c585872a9b93ab7177db149bae6389 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 16 Aug 2011 19:41:33 -0700 Subject: [PATCH] add new proxy message handler for no-conn message, and feed into existing store-and-forward system. With this checkin a robot-vs-robot game plays for quite a few moves without either game every loaded into the foreground (via a BoardActivity instance on Android), with all moves transmitted as a result of relay checks. One of the games refuses to open later, however, and there are certainly other bugs. And I'm not sure what happens when a message sent no-conn (without a cookie ID) is received in the foreground. But this is progress. --- xwords4/relay/cref.cpp | 25 ++++++++++++++++- xwords4/relay/cref.h | 1 + xwords4/relay/crefmgr.h | 9 ++++++ xwords4/relay/states.cpp | 5 ++++ xwords4/relay/states.h | 4 +++ xwords4/relay/xwrelay.cpp | 59 +++++++++++++++++++++++++++++++++++++++ xwords4/relay/xwrelay.h | 37 ++++++++++++------------ 7 files changed, 121 insertions(+), 19 deletions(-) diff --git a/xwords4/relay/cref.cpp b/xwords4/relay/cref.cpp index e697bc947..fe3bab6ad 100644 --- a/xwords4/relay/cref.cpp +++ b/xwords4/relay/cref.cpp @@ -241,6 +241,19 @@ CookieRef::_HandleAck( HostID hostID ) handleEvents(); } +void +CookieRef::_PutMsg( HostID srcID, HostID destID, unsigned char* buf, int buflen ) +{ + CRefEvent evt( XWE_PROXYMSG ); + evt.u.fwd.src = srcID; + evt.u.fwd.dest = destID; + evt.u.fwd.buf = buf; + evt.u.fwd.buflen = buflen; + + m_eventQueue.push_back( evt ); + handleEvents(); +} + void CookieRef::_Disconnect( int socket, HostID hostID ) { @@ -659,6 +672,10 @@ CookieRef::handleEvents() forward_or_store( &evt ); break; + case XWA_PROXYMSG: + forward_or_store/*_proxy*/( &evt ); + break; + case XWA_TIMERDISCONN: disconnectSockets( XWRELAY_ERROR_TIMEOUT ); break; @@ -1037,7 +1054,13 @@ CookieRef::forward_or_store( const CRefEvent* evt ) int destSocket = SocketForHost( dest ); /* This is an ugly hack!!!! */ - *buf = XWRELAY_MSG_FROMRELAY; + if ( *buf == XWRELAY_MSG_TORELAY ) { + *buf = XWRELAY_MSG_FROMRELAY; + } else if ( *buf == XWRELAY_MSG_TORELAY_NOCONN ) { + *buf = XWRELAY_MSG_FROMRELAY_NOCONN; + } else { + assert( 0 ); /* don't ship this */ + } if ( 0 < m_delayMicros && destSocket != -1 ) { usleep( m_delayMicros ); diff --git a/xwords4/relay/cref.h b/xwords4/relay/cref.h index 1158feb67..b382b66d3 100644 --- a/xwords4/relay/cref.h +++ b/xwords4/relay/cref.h @@ -124,6 +124,7 @@ class CookieRef { bool _Reconnect( int socket, HostID srcID, int nPlayersH, int nPlayersS, int seed, bool gameDead ); void _HandleAck( HostID hostID ); + void _PutMsg( HostID srcID, HostID destID, unsigned char* buf, int buflen ); void _Disconnect(int socket, HostID hostID ); void _DeviceGone( HostID hostID, int seed ); void _Shutdown(); diff --git a/xwords4/relay/crefmgr.h b/xwords4/relay/crefmgr.h index 58534f3fc..a15e0b748 100644 --- a/xwords4/relay/crefmgr.h +++ b/xwords4/relay/crefmgr.h @@ -195,6 +195,15 @@ class SafeCref { return false; } } + + void PutMsg( HostID srcID, HostID destID, unsigned char* buf, int buflen ) { + if ( IsValid() ) { + CookieRef* cref = m_cinfo->GetRef(); + assert( 0 != cref->GetCid() ); + cref->_PutMsg( srcID, destID, buf, buflen ); + } + } + bool Connect( int socket, int nPlayersH, int nPlayersS, int seed ) { if ( IsValid() ) { CookieRef* cref = m_cinfo->GetRef(); diff --git a/xwords4/relay/states.cpp b/xwords4/relay/states.cpp index dbc435b23..8a416b7b1 100644 --- a/xwords4/relay/states.cpp +++ b/xwords4/relay/states.cpp @@ -75,6 +75,9 @@ static StateTable g_stateTable[] = { { XWS_ALLCONND, XWE_REMOVESOCKET, XWA_REMOVESOCK_1, XWS_ALLCONND }, { XWS_ALLCONND, XWE_GOTONEACK, XWA_NONE, XWS_ALLCONND }, +{ XWS_EMPTY, XWE_PROXYMSG, XWA_PROXYMSG, XWS_SAME }, +{ XWS_ALLCONND, XWE_PROXYMSG, XWA_PROXYMSG, XWS_SAME }, + /* { XWS_WAITMORE, XWE_GAMEFULL, XWA_SENDALLHERE, XWS_ALLCONND }, */ /* { XWS_WAITMORE, XWE_CHECKFULL, XWA_, XWS_WAITMORE }, */ /* { XWS_INITED, XWE_DEVCONNECT, XWA_SEND_NO_ROOM, XWS_DEAD }, */ @@ -224,6 +227,7 @@ eventString( XW_RELAY_EVENT evt ) CASESTR(XWE_DEVCONNECT); CASESTR(XWE_RECONNECT); CASESTR(XWE_GOTONEACK); + CASESTR(XWE_PROXYMSG); CASESTR(XWE_GOTLASTACK); CASESTR(XWE_ACKTIMEOUT); CASESTR(XWE_DISCONN); @@ -270,6 +274,7 @@ actString( XW_RELAY_ACTION act ) CASESTR(XWA_DROPDEVICE); CASESTR(XWA_SNDALLHERE_2); CASESTR(XWA_FWD); + CASESTR(XWA_PROXYMSG); CASESTR(XWA_NOTEHEART); CASESTR(XWA_TIMERDISCONN); CASESTR(XWA_DISCONNECT); diff --git a/xwords4/relay/states.h b/xwords4/relay/states.h index 2b13dfadf..2171a54eb 100644 --- a/xwords4/relay/states.h +++ b/xwords4/relay/states.h @@ -85,6 +85,8 @@ typedef enum { ,XWE_RECONNECT /* A device is re-connecting using the connID for this object */ + ,XWE_PROXYMSG /* msg when game may not be connected */ + ,XWE_GOTONEACK ,XWE_GOTLASTACK ,XWE_ACKTIMEOUT @@ -143,6 +145,8 @@ typedef enum { ,XWA_FWD /* Forward a message */ + ,XWA_PROXYMSG /* out-of-band message */ + ,XWA_NOTEHEART /* Record heartbeat received */ ,XWA_NOTE_EMPTY /* No sockets left; check if can delete */ diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index 67e8aae28..1215442db 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -782,6 +782,61 @@ handleMsgsMsg( int sock, bool sendFull, } } +static void +handleProxyMsgs( int sock, unsigned char* bufp, unsigned char* end ) +{ + logf( XW_LOGINFO, "%s()", __func__ ); + unsigned short nameCount; + int ii; + if ( getNetShort( &bufp, end, &nameCount ) ) { + vector out(4); /* space for len and n_msgs */ + assert( out.size() == 4 ); + for ( ii = 0; ii < nameCount && bufp < end; ++ii ) { + + // See NetUtils.java for reply format + // message-length: 2 + // nameCount: 2 + // name count reps of: + // counts-this-name: 2 + // counts-this-name reps of + // len: 2 + // msg: + + // pack msgs for one game + HostID hid; + char connName[MAX_CONNNAME_LEN+1]; + if ( !parseRelayID( &bufp, end, connName, sizeof(connName), + &hid ) ) { + break; + } + unsigned short nMsgs; + if ( getNetShort( &bufp, end, &nMsgs ) ) { + SafeCref scr( connName ); + while ( nMsgs-- > 0 ) { + unsigned short len; + HostID src; + HostID dest; + XWRELAY_Cmd cmd; + if ( getNetShort( &bufp, end, &len ) ) { + unsigned char* start = bufp; + if ( getNetByte( &bufp, end, &cmd ) + && getNetByte( &bufp, end, &src ) + && getNetByte( &bufp, end, &dest ) ) { + assert( cmd == XWRELAY_MSG_TORELAY_NOCONN ); + assert( hid == dest ); + scr.PutMsg( src, dest, start, len ); + bufp = start + len; + continue; + } + } + break; + } + } + } + assert( bufp == end ); // don't ship with this!!! + } +} // handleProxyMsgs + void handle_proxy_packet( unsigned char* buf, int len, int sock ) { @@ -818,6 +873,10 @@ handle_proxy_packet( unsigned char* buf, int len, int sock ) } break; /* PRX_HAS_MSGS */ + case PRX_PUT_MSGS: + handleProxyMsgs( sock, bufp, end ); + break; + case PRX_DEVICE_GONE: logf( XW_LOGINFO, "%s: got PRX_DEVICE_GONE", __func__ ); if ( len >= 2 ) { diff --git a/xwords4/relay/xwrelay.h b/xwords4/relay/xwrelay.h index b63de84dd..4bad2a6ee 100644 --- a/xwords4/relay/xwrelay.h +++ b/xwords4/relay/xwrelay.h @@ -37,29 +37,29 @@ enum { XWRELAY_NONE /* 0 is an illegal value */ flags: 1; cookieLen: 1; cookie: ; hostID: 1; nPlayers: 1; nPlayersTotal: 1 */ - , XWRELAY_GAME_RECONNECT + , XWRELAY_GAME_RECONNECT /* 1 */ /* Connect using connName as well as cookie. Used by a device that's lost its connection to a game in progress. Once a game is locked this is the only way a host can get (back) in. Format: flags: 1; cookieLen: 1; cookie: ; hostID: 1; nPlayers: 1; nPlayersTotal: 1; connNameLen: 1; connName*/ - , XWRELAY_ACK + , XWRELAY_ACK /* 2 */ - , XWRELAY_GAME_DISCONNECT + , XWRELAY_GAME_DISCONNECT /* 3 */ /* Tell the relay that we're gone for this game. After this message is sent, the host can reconnect on the same socket for a new game. Format: cookieID: 2; srcID: 1 */ - , XWRELAY_CONNECT_RESP + , XWRELAY_CONNECT_RESP /* 4 */ /* Sent from relay to device in response to XWRELAY_CONNECT. Format: heartbeat_seconds: 2; players_here: 1; players_sought: 1; */ - , XWRELAY_RECONNECT_RESP + , XWRELAY_RECONNECT_RESP /* 5 */ /* Sent from relay to device in response to XWRELAY_RECONNECT. Format: same as for XWRELAY_CONNECT_RESP */ - , XWRELAY_ALLHERE + , XWRELAY_ALLHERE /* 6 */ /* Sent from relay when it enters the state where all expected devices are here (at start of new game or after having been gone for a while). Devices should not attempt to forward messages before this @@ -67,36 +67,38 @@ enum { XWRELAY_NONE /* 0 is an illegal value */ Format: hostID: 1; connectionID: 2; connNameLen: 1; connName; */ - , XWRELAY_ALLBACK__UNUSED + , XWRELAY_ALLBACK__UNUSED /* 7 */ /* Like XWRELAY_ALLHERE, but indicates a return to all devices being present rather than the first time that's achieved. Has no real purpose now that the relay does store-and-forward, but at least lets devices tell users everybody's home. */ - , XWRELAY_DISCONNECT_YOU + , XWRELAY_DISCONNECT_YOU /* 8 */ /* Sent from relay when existing connection is terminated. Format: errorCode: 1 */ - , XWRELAY_DISCONNECT_OTHER + , XWRELAY_DISCONNECT_OTHER /* 9 */ /* Another device has left the game. Format: errorCode: 1; lostHostId: 1 */ - , XWRELAY_CONNECTDENIED + , XWRELAY_CONNECTDENIED /* 10 */ /* The relay says go away. Format: reason code: 1 */ - , XWRELAY_HEARTBEAT + , XWRELAY_HEARTBEAT /* 11 */ /* Sent in either direction. Format: cookieID: 2; srcID: 1 */ - , XWRELAY_MSG_FROMRELAY + , XWRELAY_MSG_FROMRELAY /* 12 */ /* Sent from relay to device. Format: cookieID: 2; src_hostID: 1; dest_hostID: 1; data */ - , XWRELAY_MSG_TORELAY + , XWRELAY_MSG_TORELAY /* 13 */ /* Sent from device to relay. Format: connectionID: 2; src_hostID: 1; dest_hostID: 1 */ - , XWRELAY_MSG_STATUS /* message conveying status of some sort. + , XWRELAY_MSG_STATUS /* 14 message conveying status of some sort. Format: msgCode: 1; varies after that */ + , XWRELAY_MSG_TORELAY_NOCONN /* 15 same as above, but no cookieID */ + , XWRELAY_MSG_FROMRELAY_NOCONN /* 16 same as above, but no cookieID */ } #ifndef CANT_DO_TYPEDEF XWRelayMsg @@ -111,7 +113,7 @@ typedef unsigned char XWRELAY_Cmd; #define HOST_ID_SERVER 1 #define MAX_INVITE_LEN 31 -#define MAX_MSG_LEN 256 /* 100 is more like it */ +#define MAX_MSG_LEN 1024 /* Used for proxy too! */ #define MAX_CONNNAME_LEN 48 /* host ID, boot time, and seeds as hex? */ #define XWRELAY_PROTO_VERSION_ORIG 0x01 @@ -157,6 +159,7 @@ enum { PRX_NONE /* 0 is an illegal value */ ,PRX_HAS_MSGS /* return message counts for connName/devid array */ ,PRX_DEVICE_GONE /* return message counts for connName/devid array */ ,PRX_GET_MSGS /* return full messages for connName/devid array */ + ,PRX_PUT_MSGS /* incoming set of messages with connName/devid header */ } #ifndef CANT_DO_TYPEDEF XWPRXYCMD @@ -167,8 +170,6 @@ XWPRXYCMD typedef unsigned short CookieID; #endif -#define MAX_PROXY_MSGLEN 128 - -#define COOKIE_ID_NONE 0L +#define COOKIE_ID_NONE 0 #endif