From 3b53363e163a53dfc7623656bd20d2296dcc1ae0 Mon Sep 17 00:00:00 2001 From: ehouse Date: Wed, 6 Jul 2005 01:36:52 +0000 Subject: [PATCH] Pass protocol version code with connect request, and return error if it isn't what relay can handle. Report error to user. --- xwords4/common/comms.c | 6 +++- xwords4/common/util.h | 4 ++- xwords4/linux/linuxmain.c | 5 +++ xwords4/relay/cref.cpp | 14 ++------- xwords4/relay/xwrelay.cpp | 59 ++++++++++++++++++++++++++++++------ xwords4/relay/xwrelay.h | 13 ++++++++ xwords4/relay/xwrelay_priv.h | 2 ++ 7 files changed, 81 insertions(+), 22 deletions(-) diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index ee4bdfb2e..cbeaf7227 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -691,13 +691,16 @@ relayPreProcess( CommsCtxt* comms, XWStreamCtxt* stream, XWHostID* senderID ) cookieID, srcID, destID ); /* If these values don't check out, drop it */ consumed = cookieID != comms->cookieID - && destID != comms->myHostID; + || destID != comms->myHostID; if ( consumed ) { XP_LOGF( "rejecting data message" ); } else { *senderID = srcID; } break; + case XWRELAY_CONNECTDENIED: + util_userError( comms->util, ERR_RELAY_ERROR ); + /* fallthru */ default: consumed = XP_TRUE; /* drop it */ XP_LOGF( "dropping relay msg with cmd %d", (XP_U16)cmd ); @@ -979,6 +982,7 @@ send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID, } break; case XWRELAY_CONNECT: + stream_putU8( tmpStream, XWRELAY_PROTO_VERSION ); stringToStream( tmpStream, addr.u.ip_relay.cookie ); stream_putU16( tmpStream, comms->myHostID ); XP_LOGF( "writing cookieID of %ld", comms->cookieID ); diff --git a/xwords4/common/util.h b/xwords4/common/util.h index 347af1073..371acf619 100644 --- a/xwords4/common/util.h +++ b/xwords4/common/util.h @@ -50,7 +50,9 @@ typedef enum { /* ERR_CANT_ENGINE_MID_MOVE, */ /* ERR_NOT_YOUR_TURN_TO_TRADE, */ /* ERR_NOT_YOUR_TURN_TO_MOVE, */ - ERR_CANT_UNDO_TILEASSIGN + ERR_CANT_UNDO_TILEASSIGN, + + ERR_RELAY_ERROR } UtilErrID; typedef enum { diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index 484104f36..59d25318e 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -164,6 +164,11 @@ linux_getErrString( UtilErrID id ) case ERR_CANT_UNDO_TILEASSIGN: message = "Tile assignment can't be undone."; break; + case ERR_RELAY_ERROR: + message = "Problem communicating with the relay. Maybe it's " + "overloaded or is expecting a newer version of Crosswords"; + break; + default: message = ""; } diff --git a/xwords4/relay/cref.cpp b/xwords4/relay/cref.cpp index 9df16ac0e..f8f8a142f 100644 --- a/xwords4/relay/cref.cpp +++ b/xwords4/relay/cref.cpp @@ -493,17 +493,9 @@ static void send_with_length( int socket, unsigned char* buf, int bufLen ) { SocketWriteLock slock( socket ); - int ok = 0; - unsigned short len = htons( bufLen ); - ssize_t nSent = send( socket, &len, 2, 0 ); - if ( nSent == 2 ) { - nSent = send( socket, buf, bufLen, 0 ); - if ( nSent == bufLen ) { - logf( "sent %d bytes on socket %d", nSent, socket ); - ok = 1; - } - } - if ( !ok ) { + + if ( !send_with_length_unsafe( socket, buf, bufLen ) ) { + /* ok that the slock above is still in scope */ killSocket( socket, "couldn't send" ); } } diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index 1c71cecab..dedcb8ecc 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -128,6 +128,42 @@ readCookie( unsigned char** bufp, const unsigned char* end, return 0; } /* readCookie */ +static int +flagsOK( unsigned char flags ) +{ + return flags == XWRELAY_PROTO_VERSION; +} /* flagsOK */ + +static void +denyConnection( int socket ) +{ + unsigned char buf[2]; + + buf[0] = XWRELAY_CONNECTDENIED; + buf[1] = XWRELAY_ERROR_BADPROTO; + + send_with_length_unsafe( socket, buf, sizeof(buf) ); +} + +/* No mutex here. Caller better be ensuring no other thread can access this + * socket. */ +int +send_with_length_unsafe( int socket, unsigned char* buf, int bufLen ) +{ + int ok = 0; + unsigned short len = htons( bufLen ); + ssize_t nSent = send( socket, &len, 2, 0 ); + if ( nSent == 2 ) { + nSent = send( socket, buf, bufLen, 0 ); + if ( nSent == bufLen ) { + logf( "sent %d bytes on socket %d", nSent, socket ); + ok = 1; + } + } + return ok; +} /* send_with_length_unsafe */ + + /* A CONNECT message from a device gives us the hostID and socket we'll * associate with one participant in a relayed session. We'll store this * information with the cookie where other participants can find it when they @@ -147,19 +183,24 @@ processConnect( unsigned char* bufp, int bufLen, int socket ) logf( "processConnect" ); - if ( readCookie( &bufp, end, cookie ) ) { + unsigned char flags = *bufp++; + if ( flagsOK( flags ) ) { + if ( readCookie( &bufp, end, cookie ) ) { - HostID srcID; - CookieID cookieID; + HostID srcID; + CookieID cookieID; - if ( bufp + sizeof(srcID) + sizeof(cookieID) == end ) { - srcID = getNetShort( &bufp ); - cookieID = getNetLong( &bufp ); + if ( bufp + sizeof(srcID) + sizeof(cookieID) == end ) { + srcID = getNetShort( &bufp ); + cookieID = getNetLong( &bufp ); - CookieRef* cref = get_make_cookieRef( cookie, cookieID ); - assert( cref != NULL ); - cref->Connect( socket, srcID ); + CookieRef* cref = get_make_cookieRef( cookie, cookieID ); + assert( cref != NULL ); + cref->Connect( socket, srcID ); + } } + } else { + denyConnection( socket ); } } /* processConnect */ diff --git a/xwords4/relay/xwrelay.h b/xwords4/relay/xwrelay.h index b35f8c39b..7fd6629db 100644 --- a/xwords4/relay/xwrelay.h +++ b/xwords4/relay/xwrelay.h @@ -38,6 +38,9 @@ enum { XWRELAY_NONE /* 0 is an illegal value */ /* Sent from relay to device in response to XWRELAY_CONNECT. Format: heartbeat_seconds: 2; connectionID: 2; */ + /* The relay says go away. Format: reason code: 1 */ + , XWRELAY_CONNECTDENIED + , XWRELAY_HEARTBEAT /* Sent in either direction. Format: cookieID: 2; srcID: 2 */ @@ -60,4 +63,14 @@ typedef unsigned char XWRELAY_Cmd; #define MAX_COOKIE_LEN 15 #define MAX_MSG_LEN 256 /* 100 is more like it */ +#define XWRELAY_PROTO_VERSION 0x01 + +/* Errors passed with denied */ +enum { + XWRELAY_ERROR_NONE + ,XWRELAY_ERROR_BADPROTO + ,XWRELAY_ERROR_RELAYBUSY + ,XWRELAY_ERROR_COOKIEINUSE +}; + #endif diff --git a/xwords4/relay/xwrelay_priv.h b/xwords4/relay/xwrelay_priv.h index 2c3982347..2de086ec2 100644 --- a/xwords4/relay/xwrelay_priv.h +++ b/xwords4/relay/xwrelay_priv.h @@ -12,6 +12,8 @@ void logf( const char* format, ... ); void killSocket( int socket, char* why ); +int send_with_length_unsafe( int socket, unsigned char* buf, int bufLen ); + time_t now(); #endif