From 2ec67c8ed1f88034fc0555542c3194686962ca4a Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 21 Sep 2010 06:26:49 -0700 Subject: [PATCH 1/5] finish rq to work with current format; add to makefile --- xwords4/relay/Makefile | 2 +- xwords4/relay/rq.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xwords4/relay/Makefile b/xwords4/relay/Makefile index b30821e05..7d4e94827 100644 --- a/xwords4/relay/Makefile +++ b/xwords4/relay/Makefile @@ -55,7 +55,7 @@ xwrelay: $(OBJ) rq: rq.c clean: - rm -f xwrelay $(OBJ) + rm -f xwrelay $(OBJ) rq tags: etags *.cpp *.h diff --git a/xwords4/relay/rq.c b/xwords4/relay/rq.c index 3c46b8f9b..201de62c1 100644 --- a/xwords4/relay/rq.c +++ b/xwords4/relay/rq.c @@ -70,7 +70,7 @@ do_rooms( int sockfd, int lang, int nPlayers ) write( sockfd, &len, sizeof(len) ); write( sockfd, msg, sizeof(msg) ); - fprintf( stderr, "Waiting for response...." ); + fprintf( stderr, "Waiting for response....\n" ); ssize_t nRead = recv( sockfd, &len, sizeof(len), MSG_WAITALL ); assert( nRead == sizeof(len) ); @@ -89,7 +89,7 @@ do_rooms( int sockfd, int lang, int nPlayers ) char* saveptr; for ( ii = 0; ii < nRooms; ++ii ) { char* str = strtok_r( ptr, "\n", &saveptr ); - fprintf( stdout, "%s", str ); + fprintf( stdout, "%s\n", str ); ptr = NULL; } } From e7b5923883c6b3dfe816702cc4cdc5ff2fffc8de Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 21 Sep 2010 06:27:31 -0700 Subject: [PATCH 2/5] finish first pass at sending open public room names -- but with actual list harvesting stubbed out. --- xwords4/relay/dbmgr.cpp | 8 ++++++++ xwords4/relay/dbmgr.h | 10 ++++++++++ xwords4/relay/xwrelay.cpp | 25 ++++++++++++++++++++----- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/xwords4/relay/dbmgr.cpp b/xwords4/relay/dbmgr.cpp index b0b46b9b2..677a587ea 100644 --- a/xwords4/relay/dbmgr.cpp +++ b/xwords4/relay/dbmgr.cpp @@ -225,6 +225,14 @@ DBMgr::ClearCIDs( void ) execSql( "UPDATE " TABLE_NAME " set cid = null" ); } +void +DBMgr::PublicRooms( int lang, int nPlayers, int* nNames, string& names ) +{ + *nNames = 2; + names.append( "hello world/2\n" ); + names.append( "Room 222/1\n" ); +} + void DBMgr::execSql( const char* query ) { diff --git a/xwords4/relay/dbmgr.h b/xwords4/relay/dbmgr.h index 621333ab4..d46d70612 100644 --- a/xwords4/relay/dbmgr.h +++ b/xwords4/relay/dbmgr.h @@ -21,9 +21,13 @@ #ifndef _DBMGR_H_ #define _DBMGR_H_ +#include + #include "xwrelay.h" #include +using namespace std; + class DBMgr { public: static DBMgr* Get(); @@ -46,6 +50,12 @@ class DBMgr { void AddCID( const char* connName, CookieID cid ); void ClearCID( const char* connName ); + /* Return list of roomName/playersStillWanted for open public games + matching this language and total game size. Will probably want to cache + lists locally and only update them every few seconds to avoid to many + queries.*/ + void PublicRooms( int lang, int nPlayers, int* nNames, string& names ); + private: DBMgr(); void execSql( const char* query ); /* no-results query */ diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index 894525a38..b9608d9d3 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -74,6 +74,7 @@ #include "timermgr.h" #include "permid.h" #include "lstnrmgr.h" +#include "dbmgr.h" static int s_nSpawns = 0; #define MAX_PROXY_LEN 64 @@ -645,18 +646,20 @@ handlePipe( int sig ) logf( XW_LOGINFO, "%s", __func__ ); } -bool +int read_packet( int sock, unsigned char* buf, int buflen ) { - bool result = false; + int result = -1; ssize_t nread; unsigned short msgLen; nread = recv( sock, &msgLen, sizeof(msgLen), MSG_WAITALL ); if ( nread == sizeof(msgLen) ) { msgLen = ntohs( msgLen ); - if ( msgLen >= buflen ) { + if ( msgLen <= buflen ) { nread = recv( sock, buf, msgLen, MSG_WAITALL ); - result = nread == msgLen; + if ( nread == msgLen ) { + result = nread; + } } } return result; @@ -677,7 +680,19 @@ handle_proxy_tproc( void* closure ) case PRX_NONE: break; case PRX_PUBROOMS: - logf( XW_LOGINFO, "%s: PRX_PUBROOMS", __func__ ); + if ( len >= 4 ) { + int lang = *bufp++; + int nPlayers = *bufp++; + string names; + int nNames; + DBMgr::Get()->PublicRooms( lang, nPlayers, &nNames, names ); + unsigned short netshort = htons( names.size() + + sizeof(unsigned short) ); + write( sock, &netshort, sizeof(netshort) ); + netshort = htons( (unsigned short)nNames ); + write( sock, &netshort, sizeof(netshort) ); + write( sock, names.c_str(), names.size() ); + } break; } } From be23e06b60fcee64eb8321af4ca3bcbf89303b10 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 21 Sep 2010 06:38:43 -0700 Subject: [PATCH 3/5] use read_packet to replace duplicate code --- xwords4/relay/tpool.cpp | 27 ++++++--------------------- xwords4/relay/xwrelay_priv.h | 2 ++ 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/xwords4/relay/tpool.cpp b/xwords4/relay/tpool.cpp index 8766d367e..7f21bd4d3 100644 --- a/xwords4/relay/tpool.cpp +++ b/xwords4/relay/tpool.cpp @@ -181,28 +181,13 @@ XWThreadPool::get_process_packet( int socket ) short packetSize; assert( sizeof(packetSize) == 2 ); - ssize_t nRead = recv( socket, &packetSize, - sizeof(packetSize), MSG_WAITALL ); - if ( nRead != 2 ) { - EnqueueKill( socket, "nRead != 2" ); + unsigned char buf[MAX_MSG_LEN]; + int nRead = read_packet( socket, buf, sizeof(buf) ); + if ( nRead < 0 ) { + EnqueueKill( socket, "bad packet" ); } else { - packetSize = ntohs( packetSize ); - - if ( packetSize < 0 || packetSize > MAX_MSG_LEN ) { - EnqueueKill( socket, "packetSize wrong" ); - } else { - unsigned char buf[MAX_MSG_LEN]; - nRead = recv( socket, buf, packetSize, MSG_WAITALL ); - - if ( nRead != packetSize ) { - EnqueueKill( socket, "nRead != packetSize" ); - } else { - logf( XW_LOGINFO, "read %d bytes", nRead ); - - logf( XW_LOGINFO, "calling m_pFunc" ); - success = (*m_pFunc)( buf, packetSize, socket ); - } - } + logf( XW_LOGINFO, "calling m_pFunc" ); + success = (*m_pFunc)( buf, nRead, socket ); } return success; } /* get_process_packet */ diff --git a/xwords4/relay/xwrelay_priv.h b/xwords4/relay/xwrelay_priv.h index 50f10a8a2..b021871bc 100644 --- a/xwords4/relay/xwrelay_priv.h +++ b/xwords4/relay/xwrelay_priv.h @@ -27,6 +27,8 @@ int GetNSpawns(void); int make_socket( unsigned long addr, unsigned short port ); +int read_packet( int sock, unsigned char* buf, int buflen ); + const char* cmdToStr( XWRELAY_Cmd cmd ); extern class ListenerMgr g_listeners; From e06baf566ff79d7403df794c8ecde305c518aec5 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 21 Sep 2010 06:54:47 -0700 Subject: [PATCH 4/5] get public rooms from the db rather than stubbing it out. --- xwords4/relay/dbmgr.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/xwords4/relay/dbmgr.cpp b/xwords4/relay/dbmgr.cpp index 677a587ea..03c7c14e8 100644 --- a/xwords4/relay/dbmgr.cpp +++ b/xwords4/relay/dbmgr.cpp @@ -228,9 +228,27 @@ DBMgr::ClearCIDs( void ) void DBMgr::PublicRooms( int lang, int nPlayers, int* nNames, string& names ) { - *nNames = 2; - names.append( "hello world/2\n" ); - names.append( "Room 222/1\n" ); + int ii; + int nTuples; + + const char* fmt = "SELECT room, nTotal-nJoined FROM " TABLE_NAME + " WHERE ispublic = TRUE AND lang = %d AND ntotal =% d"; + + char query[256]; + snprintf( query, sizeof(query), fmt, lang, nPlayers ); + logf( XW_LOGINFO, "%s: query: %s", __func__, query ); + + MutexLock ml( &m_dbMutex ); + + PGresult* result = PQexec( m_pgconn, query ); + nTuples = PQntuples( result ); + for ( ii = 0; ii < nTuples; ++ii ) { + names.append( PQgetvalue( result, ii, 0 ) ); + names.append( "/" ); + names.append( PQgetvalue( result, ii, 1 ) ); + } + PQclear( result ); + *nNames = nTuples; } void From 1d0c2075214d250c10ef88c6a976fe14cb7aa681 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 21 Sep 2010 18:28:31 -0700 Subject: [PATCH 5/5] add test command for proxy feature to fetch for connNames whether there are messages pending for them. Not handled yet on relay. --- xwords4/relay/rq.c | 48 +++++++++++++++++++++++++++++++++------ xwords4/relay/xwrelay.cpp | 4 +++- xwords4/relay/xwrelay.h | 3 ++- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/xwords4/relay/rq.c b/xwords4/relay/rq.c index 201de62c1..a749c1fbc 100644 --- a/xwords4/relay/rq.c +++ b/xwords4/relay/rq.c @@ -38,6 +38,8 @@ # define DEFAULT_HOST "localhost" #endif +#define MAX_CONN_NAMES 32 + /* * Query: * list of all public games by language and number of players @@ -52,10 +54,11 @@ usage( const char * const argv0 ) fprintf( stderr, "usage: %s \\\n", argv0 ); fprintf( stderr, "\t[-p ] # (default %d)\\\n", DEFAULT_PORT ); fprintf( stderr, "\t[-a ] # (default: %s)\\\n", DEFAULT_HOST ); - fprintf( stderr, "\t-r # list open public rooms\\\n" ); + fprintf( stderr, "\t -r # list open public rooms\\\n" ); fprintf( stderr, "\t[-l ] # language for rooms " "(1=English default)\\\n" ); - fprintf( stderr, "\t[-n ] # number of players (1 default)\\\n" ); + fprintf( stderr, "\t[-n ] # number of players (2 default)\\\n" ); + fprintf( stderr, "\t[-m # list msg count\\\n" ); exit( 1 ); } @@ -63,7 +66,7 @@ static void do_rooms( int sockfd, int lang, int nPlayers ) { unsigned char msg[] = { 0, /* protocol */ - PRX_PUBROOMS, + PRX_PUB_ROOMS, lang, nPlayers }; unsigned short len = htons( sizeof(msg) ); @@ -94,17 +97,42 @@ do_rooms( int sockfd, int lang, int nPlayers ) } } +static void +do_msgs( int sockfd, const char** connNames, int nConnNames ) +{ + unsigned short len, netlen; + int ii; + for ( len = 0, ii = 0; ii < nConnNames; ++ii ) { + len += 1 + strlen( connNames[ii] ); + } + + unsigned char hdr[] = { 0, PRX_HAS_MSGS }; + unsigned short netNConnNames = htons( nConnNames ); + netlen = sizeof(hdr) + sizeof( netNConnNames ) + len; + netlen = htons( netlen ); + write( sockfd, &netlen, sizeof(netlen) ); + write( sockfd, &hdr, sizeof(hdr) ); + write( sockfd, &netNConnNames, sizeof(netNConnNames) ); + for ( len = 0, ii = 0; ii < nConnNames; ++ii ) { + write( sockfd, connNames[ii], strlen(connNames[ii]) ); + write( sockfd, "\n", 1 ); + } +} /* do_msgs */ + int main( int argc, char * const argv[] ) { int port = DEFAULT_PORT; int lang = 1; - int nPlayers = 1; + int nPlayers = 2; bool doRooms = false; + bool doMgs = false; const char* host = DEFAULT_HOST; + char const* connNames[MAX_CONN_NAMES]; + int nConnNames = 0; for ( ; ; ) { - int opt = getopt( argc, argv, "a:p:rl:n:" ); + int opt = getopt( argc, argv, "a:p:rl:n:m:" ); if ( opt < 0 ) { break; } @@ -115,6 +143,11 @@ main( int argc, char * const argv[] ) case 'l': lang = atoi(optarg); break; + case 'm': + assert( nConnNames < MAX_CONN_NAMES - 1 ); + connNames[nConnNames++] = optarg; + doMgs = true; + break; case 'n': nPlayers = atoi(optarg); break; @@ -151,8 +184,9 @@ main( int argc, char * const argv[] ) if ( doRooms ) { do_rooms( sockfd, lang, nPlayers ); - } else { - usage( argv[0] ); + } + if ( doMgs ) { + do_msgs( sockfd, connNames, nConnNames ); } close( sockfd ); diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index b9608d9d3..78ca33244 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -679,7 +679,7 @@ handle_proxy_tproc( void* closure ) switch( cmd ) { case PRX_NONE: break; - case PRX_PUBROOMS: + case PRX_PUB_ROOMS: if ( len >= 4 ) { int lang = *bufp++; int nPlayers = *bufp++; @@ -694,6 +694,8 @@ handle_proxy_tproc( void* closure ) write( sock, names.c_str(), names.size() ); } break; + case PRX_HAS_MSGS: + break; } } } diff --git a/xwords4/relay/xwrelay.h b/xwords4/relay/xwrelay.h index eae63af07..d437ce46f 100644 --- a/xwords4/relay/xwrelay.h +++ b/xwords4/relay/xwrelay.h @@ -147,7 +147,8 @@ XWREASON typedef #endif enum { PRX_NONE /* 0 is an illegal value */ - ,PRX_PUBROOMS + ,PRX_PUB_ROOMS /* list all public rooms for lang/nPlayers */ + ,PRX_HAS_MSGS /* return message counts for connName/devid array */ } #ifndef CANT_DO_TYPEDEF XWPRXYCMD