modify how devids are handled on the relay and the protocol through

which they're communicated to the device.  Device is expected to have
a platform-specific notion of ID which the relay stores in a new
devices table and indexes with a 32-bit number which is returned to
the device -- which is encouraged but not required to use it in lieu
of the longer ID in future communications.  Modify linux client and
test script to use the relay-supplied id.  Some of this is commented
out for now.
This commit is contained in:
Eric House 2012-11-03 10:58:01 -07:00
parent a73a5e8077
commit 59937b8514
16 changed files with 300 additions and 54 deletions

View file

@ -1330,6 +1330,16 @@ got_connect_cmd( CommsCtxt* comms, XWStreamCtxt* stream,
sizeof(comms->r.connName) );
#endif
#ifdef XWFEATURE_DEVID
if ( !reconnected ) {
XP_UCHAR devID[MAX_DEVID_LEN + 1];
stringFromStreamHere( stream, devID, sizeof(devID) );
if ( devID[0] != '\0' ) {
util_deviceRegistered( comms->util, devID );
}
}
#endif
(*comms->procs.rconnd)( comms->procs.closure,
comms->addr.u.ip_relay.invite, reconnected,
comms->r.myHostID, XP_FALSE, nSought - nHere );

View file

@ -55,12 +55,6 @@ typedef enum {
, COMMS_RELAYSTATE_ALLCONNECTED
} CommsRelayState;
typedef enum {
ID_TYPE_NONE
,ID_TYPE_LINUX
,ID_TYPE_ANDROID_GCM
} DevIDType;
#ifdef XWFEATURE_BLUETOOTH
# define XW_BT_UUID "7be0d084-ff89-4d6d-9c78-594773a6f963"

View file

@ -154,6 +154,7 @@ typedef struct UtilVtable {
XP_U32 (*m_util_getCurSeconds)( XW_UtilCtxt* uc );
#ifdef XWFEATURE_DEVID
const XP_UCHAR* (*m_util_getDevID)( XW_UtilCtxt* uc, DevIDType* typ );
void (*m_util_deviceRegistered)( XW_UtilCtxt* uc, const XP_UCHAR* idRelay );
#endif
DictionaryCtxt* (*m_util_makeEmptyDict)( XW_UtilCtxt* uc );
@ -285,6 +286,8 @@ struct XW_UtilCtxt {
#ifdef XWFEATURE_DEVID
# define util_getDevID( uc, t ) \
(uc)->vtable->m_util_getDevID((uc),(t))
# define util_deviceRegistered( uc, id ) \
(uc)->vtable->m_util_deviceRegistered( (uc), (id) )
#endif
#define util_makeEmptyDict( uc ) \

View file

@ -505,6 +505,7 @@ typedef enum {
,CMD_SEED
#ifdef XWFEATURE_DEVID
,CMD_DEVID
,CMD_RDEVID
#endif
,CMD_GAMESEED
,CMD_GAMEFILE
@ -601,6 +602,7 @@ static CmdInfoRec CmdInfoRecs[] = {
,{ CMD_SEED, true, "seed", "random seed" }
#ifdef XWFEATURE_DEVID
,{ CMD_DEVID, true, "devid", "device ID (for testing GCM stuff)" }
,{ CMD_RDEVID, true, "rdevid", "relay's converted device ID (for testing GCM stuff)" }
#endif
,{ CMD_GAMESEED, true, "game-seed", "game seed (for relay play)" }
,{ CMD_GAMEFILE, true, "file", "file to save to/read from" }
@ -1683,6 +1685,9 @@ main( int argc, char** argv )
case CMD_DEVID:
mainParams.devID = optarg;
break;
case CMD_RDEVID:
mainParams.rDevID = optarg;
break;
#endif
case CMD_GAMESEED:
mainParams.gameSeed = atoi(optarg);

View file

@ -348,9 +348,25 @@ linux_util_getUserString( XW_UtilCtxt* XP_UNUSED(uc), XP_U16 code )
static const XP_UCHAR*
linux_util_getDevID( XW_UtilCtxt* uc, DevIDType* typ )
{
XP_UCHAR* result;
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
if ( !!cGlobals->params->rDevID ) {
*typ = ID_TYPE_RELAY;
result = cGlobals->params->rDevID;
} else {
*typ = ID_TYPE_LINUX;
return cGlobals->params->devID;
result = cGlobals->params->devID;
}
return result;
}
static void
linux_util_deviceRegistered( XW_UtilCtxt* XP_UNUSED(uc),
const XP_UCHAR* idRelay )
{
/* Script discon_ok2.sh is grepping for this in logs, so don't change
it! */
XP_LOGF( "%s: new id: %s", __func__, idRelay );
}
#endif
@ -365,6 +381,7 @@ linux_util_vt_init( MPFORMAL XW_UtilCtxt* util )
util->vtable->m_util_getUserString = linux_util_getUserString;
#ifdef XWFEATURE_DEVID
util->vtable->m_util_getDevID = linux_util_getDevID;
util->vtable->m_util_deviceRegistered = linux_util_deviceRegistered;
#endif
}

View file

@ -61,6 +61,7 @@ typedef struct LaunchParams {
char* bonusFile;
#ifdef XWFEATURE_DEVID
char* devID;
char* rDevID;
#endif
VTableMgr* vtMgr;
XP_U16 nLocalPlayers;

View file

@ -190,6 +190,7 @@ build_cmds() {
PARAMS="$PARAMS --drop-nth-packet $DROP_N $PLAT_PARMS"
# PARAMS="$PARAMS --savefail-pct 10"
[ -n "$SEED" ] && PARAMS="$PARAMS --seed $RANDOM"
# PARAMS="$PARAMS --devid LINUX_TEST_$(printf %.5d ${COUNTER})"
PARAMS="$PARAMS $PUBLIC"
ARGS[$COUNTER]=$PARAMS
ROOMS[$COUNTER]=$ROOM
@ -380,6 +381,19 @@ increment_drop() {
fi
}
set_relay_devid() {
KEY=$1
CMD=${ARGS[$KEY]}
if [ "$CMD" != "${CMD/--devid //}" ]; then
RELAY_ID=$(grep 'deviceRegistered: new id: ' ${LOGS[$KEY]} | tail -n 1)
if [ -n "$RELAY_ID" ]; then
RELAY_ID=$(echo $RELAY_ID | sed 's,^.*new id: ,,')
# turn --devid <whatever> into --rdevid $RELAY_ID
ARGS[$KEY]=$(echo $CMD | sed 's,^\(.*\)--devid[ ]\+[^ ]\+\(.*\)$,\1--rdevid $RELAY_ID\2,')
fi
fi
}
run_cmds() {
ENDTIME=$(($(date +%s) + TIMEOUT))
while :; do
@ -409,6 +423,7 @@ run_cmds() {
PIDS[$KEY]=0
ROOM_PIDS[$ROOM]=0
[ "$DROP_N" -ge 0 ] && increment_drop $KEY
# set_relay_devid $KEY
check_game $KEY
fi
done

View file

@ -27,6 +27,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -641,9 +642,10 @@ CookieRef::handleEvents()
case XWA_SEND_CONNRSP:
{
HostID hid;
if ( increasePlayerCounts( &evt, false, &hid ) ) {
DBMgr::DevIDRelay devID;
if ( increasePlayerCounts( &evt, false, &hid, &devID ) ) {
setAllConnectedTimer();
sendResponse( &evt, true );
sendResponse( &evt, true, &devID );
setAckTimer( hid );
}
}
@ -666,8 +668,8 @@ CookieRef::handleEvents()
/* break; */
case XWA_SEND_RERSP:
increasePlayerCounts( &evt, true, NULL );
sendResponse( &evt, false );
increasePlayerCounts( &evt, true, NULL, NULL );
sendResponse( &evt, false, NULL );
sendAnyStored( &evt );
postCheckAllHere();
break;
@ -855,8 +857,10 @@ CookieRef::send_stored_messages( HostID dest, int socket )
} /* send_stored_messages */
bool
CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp )
CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp,
DBMgr::DevIDRelay* devIDp )
{
DBMgr::DevIDRelay devID = DBMgr::DEVID_NONE;
int nPlayersH = evt->u.con.nPlayersH;
int socket = evt->u.con.socket;
int seed = evt->u.con.seed;
@ -883,10 +887,25 @@ CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp )
assert( m_nPlayersHere <= m_nPlayersSought );
}
if ( !!devIDp ) {
DevIDType devIDType = evt->u.con.devID->m_devIDType;
// does client support devID
if ( ID_TYPE_NONE != devIDType ) {
// have we not already converted it?
if ( ID_TYPE_RELAY == devIDType ) {
devID = (DBMgr::DevIDRelay)strtoul( evt->u.con.devID->m_devIDString.c_str(),
NULL, 16 );
} else {
devID = DBMgr::Get()->RegisterDevice( evt->u.con.devID );
}
}
*devIDp = devID;
}
evt->u.con.srcID =
DBMgr::Get()->AddDevice( ConnName(), evt->u.con.srcID,
evt->u.con.clientVersion, nPlayersH, seed,
evt->u.con.addr, evt->u.con.devID, reconn );
evt->u.con.addr, devID, reconn );
HostID hostid = evt->u.con.srcID;
if ( NULL != hidp ) {
@ -1016,7 +1035,8 @@ CookieRef::cancelAllConnectedTimer()
}
void
CookieRef::sendResponse( const CRefEvent* evt, bool initial )
CookieRef::sendResponse( const CRefEvent* evt, bool initial,
const DBMgr::DevIDRelay* devID )
{
int socket = evt->u.con.socket;
@ -1028,6 +1048,7 @@ CookieRef::sendResponse( const CRefEvent* evt, bool initial )
+ sizeof(unsigned char) /* total here */
+ sizeof(unsigned char) /* total expected */
+ 1 + MAX_CONNNAME_LEN
+ 1 + 1 + MAX_DEVID_LEN
];
unsigned char* bufp = buf;
@ -1043,12 +1064,33 @@ CookieRef::sendResponse( const CRefEvent* evt, bool initial )
const char* connName = ConnName();
assert( !!connName && connName[0] );
int len = strlen( connName );
size_t len = strlen( connName );
assert( len < MAX_CONNNAME_LEN );
*bufp++ = (char)len;
memcpy( bufp, connName, len );
bufp += len;
if ( initial ) {
// we always write at least empty string
char idbuf[MAX_DEVID_LEN + 1] = {0};
// If client supports devid, and we have one (response case), write it as
// 8-byte hex string plus a length byte -- but only if we didn't already
// receive it.
if ( !!devID && ID_TYPE_RELAY < evt->u.con.devID->m_devIDType ) {
len = snprintf( idbuf, sizeof(idbuf), "%.8X", *devID );
assert( len < sizeof(idbuf) );
}
len = strlen( idbuf );
assert( len <= MAX_DEVID_LEN );
*bufp++ = (char)len;
if ( 0 < len ) {
memcpy( bufp, idbuf, len );
bufp += len;
}
}
send_with_length( socket, buf, bufp - buf, true );
logf( XW_LOGVERBOSE0, "sent %s", cmdToStr( XWRELAY_Cmd(buf[0]) ) );
} /* sendResponse */

View file

@ -30,6 +30,8 @@
#include <pthread.h>
#include "xwrelay_priv.h"
#include "xwrelay.h"
#include "devid.h"
#include "dbmgr.h"
#include "states.h"
typedef vector<unsigned char> MsgBuffer;
@ -63,13 +65,6 @@ public:
class CookieRef* m_this;
};
class DevID {
public:
DevID() { m_devIDType = 0; }
string m_devIDString;
unsigned char m_devIDType;
};
class CookieRef {
public:
set<int> GetSockets();
@ -224,10 +219,12 @@ class CookieRef {
void handleEvents();
void sendResponse( const CRefEvent* evt, bool initial );
void sendResponse( const CRefEvent* evt, bool initial,
const DBMgr::DevIDRelay* devID );
void sendAnyStored( const CRefEvent* evt );
void initPlayerCounts( const CRefEvent* evt );
bool increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp );
bool increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp,
DBMgr::DevIDRelay* devID );
void updateAck( HostID hostID, bool keep );
void dropPending( int seed );

View file

@ -34,6 +34,7 @@
#define GAMES_TABLE "games"
#define MSGS_TABLE "msgs"
#define DEVICES_TABLE "devices"
#define ARRAYSUM "sum_array(nPerDevice)"
@ -243,10 +244,59 @@ DBMgr::AllDevsAckd( const char* const connName )
return full;
}
// Return DevIDRelay for device, adding it to devices table IFF it's not
// already there.
DBMgr::DevIDRelay
DBMgr::RegisterDevice( const DevID* host )
{
DBMgr::DevIDRelay devID;
assert( host->m_devIDType != ID_TYPE_RELAY );
int ii;
bool success;
// if it's already present, just return
devID = getDevID( host );
if ( DEVID_NONE == devID ) {
// loop until we're successful inserting the unique key. Ship with this
// coming from random, but test with increasing values initially to make
// sure duplicates are detected.
for ( success = false, ii = 0; !success; ++ii ) {
assert( 10 > ii ); // better to check that we're looping BECAUSE
// of uniqueness problem.
devID = (DBMgr::DevIDRelay)random();
if ( DEVID_NONE == devID ) {
continue;
}
const char* command = "INSERT INTO " DEVICES_TABLE
" (id, devType, devid)"
" VALUES( $1, $2, $3 )";
int nParams = 3;
char* paramValues[nParams];
char buf[512];
formatParams( paramValues, nParams,
"%d"DELIM"%d"DELIM"%s",
buf, sizeof(buf), devID, host->m_devIDType,
host->m_devIDString.c_str() );
PGresult* result = PQexecParams( getThreadConn(), command,
nParams, NULL,
paramValues,
NULL, NULL, 0 );
success = PGRES_COMMAND_OK == PQresultStatus(result);
if ( !success ) {
logf( XW_LOGERROR, "PQexec=>%s;%s", PQresStatus(PQresultStatus(result)),
PQresultErrorMessage(result) );
}
PQclear( result );
}
}
return devID;
}
HostID
DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion,
int nToAdd, unsigned short seed, const in_addr& addr,
const DevID* devID, bool ackd )
DevIDRelay devID, bool ackd )
{
HostID newID = curID;
@ -262,11 +312,9 @@ DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion,
assert( newID <= 4 );
char devIDBuf[512] = {0};
if ( !!devID ) {
if ( DEVID_NONE != devID ) {
snprintf( devIDBuf, sizeof(devIDBuf),
"devids[%d] = \'%s\', devTypes[%d] = %d,",
newID, devID->m_devIDString.c_str(),
newID, devID->m_devIDType );
"devids[%d] = %d, ", newID, devID );
}
const char* fmt = "UPDATE " GAMES_TABLE " SET nPerDevice[%d] = %d,"
@ -569,20 +617,45 @@ DBMgr::readArray( const char* const connName, int arr[] ) /* len 4 */
PQclear( result );
}
void
DBMgr::getDevID( const char* connName, int hid, DevID& devID )
DBMgr::DevIDRelay
DBMgr::getDevID( const char* connName, int hid )
{
const char* fmt = "SELECT devids[%d], devTypes[%d] FROM " GAMES_TABLE " WHERE connName='%s'";
DBMgr::DevIDRelay devID;
const char* fmt = "SELECT devids[%d] FROM " GAMES_TABLE " WHERE connName='%s'";
char query[256];
snprintf( query, sizeof(query), fmt, hid, hid, connName );
snprintf( query, sizeof(query), fmt, hid, connName );
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
PGresult* result = PQexec( getThreadConn(), query );
assert( 1 == PQntuples( result ) );
devID.m_devIDString = PQgetvalue( result, 0, 0 );
devID.m_devIDType = (unsigned char)atoi( PQgetvalue( result, 0, 1 ) );
assert( devID.m_devIDType <= 2 ); // for now!!!
devID = (DBMgr::DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
PQclear( result );
return devID;
}
DBMgr::DevIDRelay
DBMgr::getDevID( const DevID* devID )
{
DBMgr::DevIDRelay rDevID = DEVID_NONE;
DevIDType devIDType = devID->m_devIDType;
assert( ID_TYPE_NONE < devIDType );
const char* asStr = devID->m_devIDString.c_str();
if ( ID_TYPE_RELAY == devIDType ) {
rDevID = strtoul( asStr, NULL, 16 );
} else {
const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE devtype=%d and devid = '%s'";
char query[512];
snprintf( query, sizeof(query), fmt, devIDType, asStr );
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
PGresult* result = PQexec( getThreadConn(), query );
assert( 1 >= PQntuples( result ) );
if ( 1 == PQntuples( result ) ) {
rDevID = (DBMgr::DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
}
PQclear( result );
}
return rDevID;
}
/*
@ -625,13 +698,12 @@ void
DBMgr::StoreMessage( const char* const connName, int hid,
const unsigned char* buf, int len )
{
DevID devID;
getDevID( connName, hid, devID );
DevIDRelay devID = getDevID( connName, hid );
size_t newLen;
const char* fmt = "INSERT INTO " MSGS_TABLE
" (connname, hid, devid, devType, msg, msglen)"
" VALUES( '%s', %d, '%s', %d, E'%s', %d)";
" (connname, hid, devid, msg, msglen)"
" VALUES( '%s', %d, %d, E'%s', %d)";
unsigned char* bytes = PQescapeByteaConn( getThreadConn(), buf,
len, &newLen );
@ -639,8 +711,7 @@ DBMgr::StoreMessage( const char* const connName, int hid,
char query[1024];
size_t siz = snprintf( query, sizeof(query), fmt, connName, hid,
devID.m_devIDString.c_str(),
devID.m_devIDType, bytes, len );
devID, bytes, len );
PQfreemem( bytes );

View file

@ -26,13 +26,19 @@
#include "xwrelay.h"
#include "xwrelay_priv.h"
#include "cref.h"
#include "devid.h"
#include <libpq-fe.h>
using namespace std;
class DBMgr {
public:
/* DevIDs on various platforms are stored in devices table. This is the
key, and used in msgs and games tables as a shorter way to refer to
them. */
typedef unsigned int DevIDRelay;
static const DevIDRelay DEVID_NONE = 0;
static DBMgr* Get();
~DBMgr();
@ -56,9 +62,11 @@ class DBMgr {
char* connNameBuf, int bufLen, int* nPlayersHP );
bool AllDevsAckd( const char* const connName );
DevIDRelay RegisterDevice( const DevID* hosts );
HostID AddDevice( const char* const connName, HostID curID, int clientVersion,
int nToAdd, unsigned short seed, const in_addr& addr,
const DevID* devID, bool unAckd );
DevIDRelay devID, bool unAckd );
void NoteAckd( const char* const connName, HostID id );
HostID HIDForSeed( const char* const connName, unsigned short seed );
bool RmDeviceByHid( const char* const connName, HostID id );
@ -99,7 +107,8 @@ class DBMgr {
DBMgr();
bool execSql( const char* const query ); /* no-results query */
void readArray( const char* const connName, int arr[] );
void getDevID( const char* connName, int hid, DevID& devID );
DevIDRelay getDevID( const char* connName, int hid );
DevIDRelay getDevID( const DevID* devID );
PGconn* getThreadConn( void );

64
xwords4/relay/devid.h Normal file
View file

@ -0,0 +1,64 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2005-2012 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DEVID_H_
#define _DEVID_H_
#include <string>
#include "xwrelay.h"
/* DevID protocol.
*
* There are two types. The first, with a DevIDType greater than
* ID_TYPE_RELAY, is platform-specific and meaningless to the relay (though as
* with GCM-based IDs on Android there may be server code that uses it.) The
* second, with type of ID_TYPE_RELAY, is specific to the relay. When the
* relay sees one of the first type, it creates an entry in the devices table
* with a new random 32-bit index that is then used in the msgs and games
* tables. This index is the second type.
*
* A device always includes a DevID when creating a new game. It may be of
* either type, and generally should use the latter when possible. Since the
* latter comes from the relay, the first time a device connects (after
* whatever local event, e.g. registration with GCM, causes it to have an ID of
* the first type that it wants to share) it will have to send the first type.
* When replying to a registration message that included a DevID of the first
* type, the relay always sends the corresponding DevID of the second type,
* which it expects the device to remember. But when replying after receiving a
* DevID of the second type the relay does not echo that value (sends an empty
* string).
*
* Devices or platforms not providing a DevID will return ID_TYPE_NONE as the
* type via util_getDevID(). That single byte will be transmitted to the relay
* which will then skip the registration process and will return an empty
* string as the relay-type DevID in the connection response.
*
*/
using namespace std;
class DevID {
public:
DevID() { m_devIDType = ID_TYPE_NONE; }
string m_devIDString;
DevIDType m_devIDType;
};
#endif

View file

@ -26,12 +26,15 @@ QUERY="WHERE NOT -NTOTAL = sum_array(nperdevice)"
echo "Device (pid) count: $(pidof xwords | wc | awk '{print $2}')"
echo "Row count:" $(psql -t xwgames -c "select count(*) FROM games $QUERY;")
echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,devTypes,devids,ack,nsent "\
echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,devids,ack,nsent "\
"FROM games $QUERY ORDER BY NOT dead, connname LIMIT $LIMIT;" \
| psql xwgames
echo "SELECT connname, hid, devType, devid, count(*), sum(msglen) "\
echo "SELECT connname, hid, devid, count(*), sum(msglen) "\
"FROM msgs where connname in (SELECT connname from games where not games.dead group by connname)" \
"GROUP BY connname, hid, devType, devid ORDER BY connname;" \
"GROUP BY connname, hid, devid ORDER BY connname;" \
| psql xwgames
echo "SELECT * from devices;" \
| psql xwgames

View file

@ -386,7 +386,7 @@ processConnect( unsigned char* bufp, int bufLen, int socket, in_addr& addr )
if ( getNetByte( &bufp, end, &devIDType )
&& 0 != devIDType ) {
getNetString( &bufp, end, devID.m_devIDString );
devID.m_devIDType = devIDType;
devID.m_devIDType = (DevIDType)devIDType;
}
}

View file

@ -105,6 +105,13 @@ enum { XWRELAY_NONE /* 0 is an illegal value */
#endif
;
typedef enum {
ID_TYPE_NONE
,ID_TYPE_RELAY /* assigned by relay as replacement for one of the below */
,ID_TYPE_LINUX
,ID_TYPE_ANDROID_GCM
} DevIDType;
#ifndef CANT_DO_TYPEDEF
typedef unsigned char XWRELAY_Cmd;
#endif
@ -115,6 +122,7 @@ typedef unsigned char XWRELAY_Cmd;
#define MAX_INVITE_LEN 31
#define MAX_MSG_LEN 1024 /* Used for proxy too! */
#define MAX_CONNNAME_LEN 48 /* host ID, boot time, and seeds as hex? */
#define MAX_DEVID_LEN 8 /* 32-bit number as hex */
#define XWRELAY_PROTO_VERSION_ORIG 0x01
#define XWRELAY_PROTO_VERSION_LATE_NAME 0x02

View file

@ -58,8 +58,7 @@ cid integer
,ctime TIMESTAMP (0) DEFAULT CURRENT_TIMESTAMP
,mtimes TIMESTAMP(0)[]
,addrs INET[]
,devTypes INTEGER[]
,devids TEXT[]
,devids INTEGER[]
);
EOF
@ -69,12 +68,20 @@ id SERIAL
,connName VARCHAR(64)
,hid INTEGER
,ctime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
,devType INTEGER
,devid TEXT
,devid INTEGER
,msg BYTEA
,msglen INTEGER
,UNIQUE ( connName, hid, msg )
);
EOF
cat | psql $DBNAME --file - <<EOF
CREATE TABLE devices (
id INTEGER UNIQUE PRIMARY KEY
,devType INTEGER
,devid TEXT
,ctime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
EOF
}