mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
Add support to gtk app for tranport over "sms", with files containing
base64-encoded data as the messages. Make necessary changes to comms. This is the foundation for doing real SMS transport on handhelds. Currently a full robot game works for two gtk clients provided the server is launched first.
This commit is contained in:
parent
270006f47b
commit
1755267d55
8 changed files with 402 additions and 22 deletions
|
@ -330,6 +330,11 @@ addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
|||
addr.u.ip_relay.ipAddr = stream_getU32( stream );
|
||||
addr.u.ip_relay.port = stream_getU16( stream );
|
||||
break;
|
||||
case COMMS_CONN_SMS:
|
||||
stringFromStreamHere( stream, addr.u.sms.phone,
|
||||
sizeof(addr.u.sms.phone) );
|
||||
addr.u.sms.port = stream_getU16( stream );
|
||||
break;
|
||||
default:
|
||||
/* shut up, compiler */
|
||||
break;
|
||||
|
@ -435,13 +440,24 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
|||
return comms;
|
||||
} /* comms_makeFromStream */
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
static void
|
||||
setDoHeartbeat( CommsCtxt* comms )
|
||||
{
|
||||
CommsConnType conType = comms->addr.conType;
|
||||
comms->doHeartbeat = XP_FALSE
|
||||
|| COMMS_CONN_IP_DIRECT == conType
|
||||
|| COMMS_CONN_BT == conType
|
||||
;
|
||||
}
|
||||
#else
|
||||
# define setDoHeartbeat(c)
|
||||
#endif
|
||||
|
||||
void
|
||||
comms_start( CommsCtxt* comms )
|
||||
{
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||
#endif
|
||||
|
||||
setDoHeartbeat( comms );
|
||||
sendConnect( comms );
|
||||
} /* comms_start */
|
||||
|
||||
|
@ -502,6 +518,10 @@ addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addrP )
|
|||
stream_putU32( stream, addr.u.ip_relay.ipAddr );
|
||||
stream_putU16( stream, addr.u.ip_relay.port );
|
||||
break;
|
||||
case COMMS_CONN_SMS:
|
||||
stringToStream( stream, addr.u.sms.phone );
|
||||
stream_putU16( stream, addr.u.sms.port );
|
||||
break;
|
||||
}
|
||||
} /* addrToStream */
|
||||
|
||||
|
@ -583,7 +603,7 @@ comms_setAddr( CommsCtxt* comms, const CommsAddrRec* addr )
|
|||
XP_MEMCPY( &comms->addr, addr, sizeof(comms->addr) );
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||
setDoHeartbeat( comms );
|
||||
#endif
|
||||
sendConnect( comms );
|
||||
|
||||
|
@ -1063,6 +1083,13 @@ getRecordFor( CommsCtxt* comms, const CommsAddrRec* addr,
|
|||
break;
|
||||
case COMMS_CONN_IR: /* no way to test */
|
||||
break;
|
||||
case COMMS_CONN_SMS: /* no way to test */
|
||||
if ( ( 0 == XP_MEMCMP( &addr->u.sms.phone, &rec->addr.u.sms.phone,
|
||||
sizeof(addr->u.sms.phone) ) )
|
||||
&& addr->u.sms.port == rec->addr.u.sms.port ) {
|
||||
matched = XP_TRUE;
|
||||
}
|
||||
break;
|
||||
case COMMS_CONN_NONE:
|
||||
matched = channelNo == rec->channelNo;
|
||||
break;
|
||||
|
@ -1218,8 +1245,8 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
|||
payloadSize = stream_getSize( stream ) > 0; /* anything left? */
|
||||
if ( connID == CONN_ID_NONE ) {
|
||||
/* special case: initial message from client */
|
||||
rec = validateInitialMessage( comms, payloadSize > 0, addr, senderID,
|
||||
&channelNo );
|
||||
rec = validateInitialMessage( comms, payloadSize > 0, addr,
|
||||
senderID, &channelNo );
|
||||
} else if ( comms->connID == connID ) {
|
||||
rec = validateChannelMessage( comms, addr, channelNo, msgID,
|
||||
lastMsgRcd );
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef enum {
|
|||
,COMMS_CONN_IP_DIRECT
|
||||
,COMMS_CONN_RELAY
|
||||
,COMMS_CONN_BT
|
||||
,COMMS_CONN_SMS
|
||||
} CommsConnType;
|
||||
|
||||
/* WHAT SHOULD THIS BE? Copied from Whiteboard.... PENDING */
|
||||
|
@ -60,6 +61,8 @@ typedef struct XP_BtAddrStr { XP_UCHAR chars[18]; } XP_BtAddrStr;
|
|||
#endif
|
||||
|
||||
#define MAX_HOSTNAME_LEN 63
|
||||
#define MAX_PHONE_LEN 31
|
||||
|
||||
typedef struct CommsAddrRec {
|
||||
CommsConnType conType;
|
||||
|
||||
|
@ -84,6 +87,10 @@ typedef struct CommsAddrRec {
|
|||
XP_UCHAR hostName[MAX_HOSTNAME_LEN + 1];
|
||||
XP_BtAddr btAddr;
|
||||
} bt;
|
||||
struct {
|
||||
XP_UCHAR phone[MAX_PHONE_LEN + 1];
|
||||
XP_U16 port;
|
||||
} sms;
|
||||
} u;
|
||||
} CommsAddrRec;
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ endif
|
|||
# DEFINES += -DXWFEATURE_IR
|
||||
DEFINES += ${BLUETOOTH}
|
||||
DEFINES += -DXWFEATURE_RELAY
|
||||
DEFINES += -DXWFEATURE_SMS
|
||||
|
||||
# Support device-to-device connection via UDP, e.g. using wifi on a
|
||||
# LAN or where the host/server isn't behind a firewall.
|
||||
|
@ -136,6 +137,7 @@ OBJ = \
|
|||
$(PLATFORM)/filestream.o \
|
||||
$(PLATFORM)/linuxbt.o \
|
||||
$(PLATFORM)/linuxudp.o \
|
||||
$(PLATFORM)/linuxsms.o \
|
||||
$(PLATFORM)/linuxdict.o \
|
||||
$(PLATFORM)/linuxutl.o \
|
||||
$(CURSES_OBJS) $(GTK_OBJS) $(MAIN_OBJS)
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "linuxutl.h"
|
||||
#include "linuxbt.h"
|
||||
#include "linuxudp.h"
|
||||
#include "linuxsms.h"
|
||||
/* #include "gtkmain.h" */
|
||||
|
||||
#include "draw.h"
|
||||
|
@ -363,6 +364,12 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
|||
XP_STRNCPY( addr.u.ip.hostName_ip, params->connInfo.ip.hostName,
|
||||
sizeof(addr.u.ip.hostName_ip) - 1 );
|
||||
addr.u.ip.port_ip = params->connInfo.ip.port;
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
} else if ( addr.conType == COMMS_CONN_SMS ) {
|
||||
XP_STRNCPY( addr.u.sms.phone, params->connInfo.sms.serverPhone,
|
||||
sizeof(addr.u.sms.phone) - 1 );
|
||||
addr.u.sms.port = params->connInfo.sms.port;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -549,6 +556,9 @@ quit( void* XP_UNUSED(dunno), GtkAppGlobals* globals )
|
|||
#ifdef XWFEATURE_BLUETOOTH
|
||||
linux_bt_close( &globals->cGlobals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
linux_sms_close( &globals->cGlobals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
linux_udp_close( &globals->cGlobals );
|
||||
#endif
|
||||
|
@ -1617,6 +1627,12 @@ newConnectionInput( GIOChannel *source,
|
|||
} else if ( globals->cGlobals.params->conType == COMMS_CONN_BT ) {
|
||||
nRead = linux_bt_receive( sock, buf, sizeof(buf) );
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
} else if ( globals->cGlobals.params->conType == COMMS_CONN_SMS ) {
|
||||
addrp = &addr;
|
||||
nRead = linux_sms_receive( &globals->cGlobals, sock,
|
||||
buf, sizeof(buf), addrp );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( globals->cGlobals.params->conType == COMMS_CONN_IP_DIRECT ) {
|
||||
addrp = &addr;
|
||||
|
@ -1680,7 +1696,8 @@ gtk_socket_changed( void* closure, int oldSock, int newSock, void** storage )
|
|||
g_io_channel_unref( info->channel );
|
||||
XP_FREE( globals->cGlobals.params->util->mpool, info );
|
||||
*storage = NULL;
|
||||
XP_LOGF( "Removed socket %d from gtk's list of listened-to sockets", oldSock );
|
||||
XP_LOGF( "Removed socket %d from gtk's list of listened-to sockets",
|
||||
oldSock );
|
||||
}
|
||||
if ( newSock != -1 ) {
|
||||
info = (SockInfo*)XP_MALLOC( globals->cGlobals.params->util->mpool,
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "linuxmain.h"
|
||||
#include "linuxutl.h"
|
||||
#include "linuxbt.h"
|
||||
#include "linuxsms.h"
|
||||
#include "linuxudp.h"
|
||||
#include "main.h"
|
||||
#ifdef PLATFORM_NCURSES
|
||||
|
@ -186,6 +187,9 @@ usage( char* appName, char* msg )
|
|||
"\t [-U] # call 'Undo' after game ends\n"
|
||||
#ifdef XWFEATURE_RELAY
|
||||
"\t [-H] # Don't send heartbeats to relay\n"
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
"\t [-M phone] # Server phone number for SMS\n"
|
||||
#endif
|
||||
"\t [-r name]* # same-process robot\n"
|
||||
"\t [-n name]* # same-process player (no network used)\n"
|
||||
|
@ -445,6 +449,16 @@ linux_send( const XP_U8* buf, XP_U16 buflen,
|
|||
comms_getAddr( globals->game.comms, &addr );
|
||||
linux_udp_open( globals, &addr );
|
||||
nSent = linux_udp_send( buf, buflen, addrRec, globals );
|
||||
#endif
|
||||
#if defined XWFEATURE_SMS
|
||||
} else if ( COMMS_CONN_SMS == conType ) {
|
||||
CommsAddrRec addr;
|
||||
if ( !addrRec ) {
|
||||
comms_getAddr( globals->game.comms, &addr );
|
||||
addrRec = &addr;
|
||||
}
|
||||
nSent = linux_sms_send( globals, buf, buflen,
|
||||
addrRec->u.sms.phone, addrRec->u.sms.port );
|
||||
#endif
|
||||
} else {
|
||||
XP_ASSERT(0);
|
||||
|
@ -545,23 +559,26 @@ linuxFireTimer( CommonGlobals* cGlobals, XWTimerReason why )
|
|||
(*proc)( closure, why );
|
||||
} /* fireTimer */
|
||||
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_RELAY
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
static void
|
||||
linux_util_addrChange( XW_UtilCtxt* uc,
|
||||
const CommsAddrRec* XP_UNUSED(oldAddr),
|
||||
const CommsAddrRec* newAddr )
|
||||
{
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( newAddr->conType == COMMS_CONN_BT ) {
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
XP_Bool isServer = comms_getIsServer( cGlobals->game.comms );
|
||||
linux_bt_open( cGlobals, isServer );
|
||||
#endif
|
||||
#if defined XWFEATURE_IP_DIRECT
|
||||
} else if ( newAddr->conType == COMMS_CONN_IP_DIRECT ) {
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
linux_udp_open( cGlobals, newAddr );
|
||||
#endif
|
||||
#if defined XWFEATURE_SMS
|
||||
} else if ( COMMS_CONN_SMS == newAddr->conType ) {
|
||||
linux_sms_init( cGlobals, newAddr );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -625,8 +642,9 @@ main( int argc, char** argv )
|
|||
int opt;
|
||||
int totalPlayerCount = 0;
|
||||
XP_Bool isServer = XP_FALSE;
|
||||
char* portNum = "10999";
|
||||
char* portNum = NULL;
|
||||
char* hostName = "localhost";
|
||||
char* serverPhone = NULL; /* sms */
|
||||
unsigned int seed = defaultRandomSeed();
|
||||
LaunchParams mainParams;
|
||||
XP_U16 robotCount = 0;
|
||||
|
@ -708,6 +726,9 @@ main( int argc, char** argv )
|
|||
"h:I"
|
||||
#endif
|
||||
"kKf:ln:Nsd:e:r:b:q:w:Sit:Umvc"
|
||||
#ifdef XWFEATURE_SMS
|
||||
"M:"
|
||||
#endif
|
||||
#ifdef XWFEATURE_RELAY
|
||||
"a:p:C:H"
|
||||
#endif
|
||||
|
@ -767,6 +788,13 @@ main( int argc, char** argv )
|
|||
mainParams.gi.players[mainParams.nLocalPlayers-1].password
|
||||
= (XP_UCHAR*)optarg;
|
||||
break;
|
||||
#ifdef XWFEATURE_SMS
|
||||
case 'M': /* SMS phone number */
|
||||
XP_ASSERT( COMMS_CONN_NONE == conType );
|
||||
serverPhone = optarg;
|
||||
conType = COMMS_CONN_SMS;
|
||||
break;
|
||||
#endif
|
||||
case 'm': /* dumb robot */
|
||||
mainParams.gi.robotSmartness = DUMB_ROBOT;
|
||||
break;
|
||||
|
@ -787,7 +815,7 @@ main( int argc, char** argv )
|
|||
++mainParams.info.serverInfo.nRemotePlayers;
|
||||
break;
|
||||
case 'p':
|
||||
/* could be RELAY or IP_DIRECT */
|
||||
/* could be RELAY or IP_DIRECT or SMS */
|
||||
portNum = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
|
@ -908,19 +936,26 @@ main( int argc, char** argv )
|
|||
#ifdef XWFEATURE_RELAY
|
||||
} else if ( conType == COMMS_CONN_RELAY ) {
|
||||
mainParams.connInfo.relay.relayName = hostName;
|
||||
|
||||
/* convert strings to whatever */
|
||||
if ( portNum != NULL ) {
|
||||
mainParams.connInfo.relay.defaultSendPort =
|
||||
atoi( portNum );
|
||||
if ( NULL == portNum ) {
|
||||
portNum = "10999";
|
||||
}
|
||||
mainParams.connInfo.relay.defaultSendPort = atoi( portNum );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( conType == COMMS_CONN_IP_DIRECT ) {
|
||||
mainParams.connInfo.ip.hostName = hostName;
|
||||
if ( portNum != NULL ) {
|
||||
mainParams.connInfo.ip.port = atoi( portNum );
|
||||
if ( NULL == portNum ) {
|
||||
portNum = "10999";
|
||||
}
|
||||
mainParams.connInfo.ip.port = atoi( portNum );
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
} else if ( conType == COMMS_CONN_SMS ) {
|
||||
mainParams.connInfo.sms.serverPhone = serverPhone;
|
||||
if ( !portNum ) {
|
||||
portNum = "1";
|
||||
}
|
||||
mainParams.connInfo.sms.port = atoi(portNum);
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( conType == COMMS_CONN_BT ) {
|
||||
|
|
245
xwords4/linux/linuxsms.c
Normal file
245
xwords4/linux/linuxsms.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* -*-mode: C; compile-command: "make -j MEMDEBUG=TRUE";-*- */
|
||||
/*
|
||||
* Copyright 2006-2008 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) any later version.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef XWFEATURE_SMS
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
#include "linuxsms.h"
|
||||
|
||||
#define SMS_DIR "/tmp/xw_sms"
|
||||
#define LOCK_FILE ".lock"
|
||||
|
||||
/* The idea here is to mimic an SMS-based transport using files. We'll use a
|
||||
* directory in /tmp to hold "messages", in files with names based on phone
|
||||
* number and port. Servers and clients will listen for changes in that
|
||||
* directory and "receive" messages when a change is noted to a file with
|
||||
* their phone number and on the port they listen to.
|
||||
*
|
||||
* Server's phone number is known to both server and client and passed on the
|
||||
* commandline. Client's "phone number" is the PID of the client process.
|
||||
* When the client sends to the server the phone number is passed in and its
|
||||
* return (own) number is included in the "message".
|
||||
*
|
||||
* If I'm the server, I create an empty file for each port I listen on. (Only
|
||||
* one now....). Clients will append to that. Likewise, a client creates a
|
||||
* file that it will listen on.
|
||||
*
|
||||
* Data is encoded using the same mechanism so size constraints can be
|
||||
* checked.
|
||||
*/
|
||||
|
||||
struct LinSMSData {
|
||||
XP_UCHAR myPhone[MAX_PHONE_LEN+1];
|
||||
XP_UCHAR myQueue[256];
|
||||
FILE* lock;
|
||||
int wd, fd; /* for inotify */
|
||||
void* storage;
|
||||
XP_U16 count;
|
||||
XP_U16 port;
|
||||
XP_Bool amServer;
|
||||
};
|
||||
|
||||
static void
|
||||
makeQueuePath( const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_UCHAR* path, XP_U16 pathlen )
|
||||
{
|
||||
snprintf( path, pathlen, "%s/%s_%d", SMS_DIR, phone, port );
|
||||
}
|
||||
|
||||
static void
|
||||
lock_queue( LinSMSData* data )
|
||||
{
|
||||
char lock[256];
|
||||
snprintf( lock, sizeof(lock), "%s/%s", data->myQueue, LOCK_FILE );
|
||||
FILE* fp = fopen( lock, "w" );
|
||||
XP_ASSERT( NULL == data->lock );
|
||||
data->lock = fp;
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_queue( LinSMSData* data )
|
||||
{
|
||||
XP_ASSERT( NULL != data->lock );
|
||||
fclose( data->lock );
|
||||
data->lock = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
linux_sms_init( CommonGlobals* globals, const CommsAddrRec* addr )
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
LinSMSData* data = globals->smsData;
|
||||
if ( !data ) {
|
||||
data = XP_MALLOC( globals->params->util->mpool, sizeof(*data) );
|
||||
XP_ASSERT( !!data );
|
||||
XP_MEMSET( data, 0, sizeof(*data) );
|
||||
globals->smsData = data;
|
||||
|
||||
data->amServer = comms_getIsServer( globals->game.comms );
|
||||
|
||||
if ( data->amServer ) {
|
||||
XP_STRNCPY( data->myPhone, addr->u.sms.phone,
|
||||
sizeof(data->myPhone) );
|
||||
} else {
|
||||
snprintf( data->myPhone, sizeof(data->myPhone), "%.6d", getpid() );
|
||||
}
|
||||
|
||||
makeQueuePath( data->myPhone, addr->u.sms.port,
|
||||
data->myQueue, sizeof(data->myQueue) );
|
||||
data->port = addr->u.sms.port;
|
||||
|
||||
XP_LOGF( "creating %s", data->myQueue );
|
||||
(void)g_mkdir_with_parents( data->myQueue, 0777 );
|
||||
|
||||
int fd = inotify_init();
|
||||
data->fd = fd;
|
||||
data->wd = inotify_add_watch( fd, data->myQueue, IN_MODIFY );
|
||||
(*globals->socketChanged)( globals, -1, fd, &data->storage );
|
||||
}
|
||||
} /* linux_sms_init */
|
||||
|
||||
void
|
||||
linux_sms_close( CommonGlobals* globals )
|
||||
{
|
||||
LinSMSData* data = globals->smsData;
|
||||
if ( !!data ) {
|
||||
XP_FREE( globals->params->util->mpool, data );
|
||||
globals->smsData = NULL;
|
||||
}
|
||||
} /* linux_sms_close */
|
||||
|
||||
XP_S16
|
||||
linux_sms_send( CommonGlobals* globals,
|
||||
const XP_U8* buf, XP_U16 buflen,
|
||||
const XP_UCHAR* phone, XP_U16 port )
|
||||
{
|
||||
XP_S16 nSent = -1;
|
||||
LinSMSData* data = globals->smsData;
|
||||
XP_ASSERT( !!data );
|
||||
char path[256];
|
||||
|
||||
lock_queue( data );
|
||||
|
||||
makeQueuePath( phone, port, path, sizeof(path) );
|
||||
g_mkdir_with_parents( path, 0777 ); /* just in case */
|
||||
int len = strlen( path );
|
||||
snprintf( &path[len], sizeof(path)-len, "/%d", ++data->count );
|
||||
|
||||
gchar* str = g_base64_encode( buf, buflen );
|
||||
XP_LOGF( "%s: base64 size of message: %d", __func__, strlen(str ) );
|
||||
|
||||
FILE* fp = fopen( path, "w" );
|
||||
XP_ASSERT( !!fp );
|
||||
(void)fprintf( fp, "from: %s\n", data->myPhone );
|
||||
(void)fprintf( fp, "%s\n", str );
|
||||
fclose( fp );
|
||||
|
||||
unlock_queue( data );
|
||||
|
||||
g_free( str );
|
||||
nSent = buflen;
|
||||
|
||||
LOG_RETURNF( "%d", nSent );
|
||||
return nSent;
|
||||
} /* linux_sms_send */
|
||||
|
||||
static XP_S16
|
||||
decodeAndDelete( LinSMSData* data, const gchar* name,
|
||||
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr )
|
||||
{
|
||||
XP_S16 nRead = -1;
|
||||
char path[256];
|
||||
snprintf( path, sizeof(path), "%s/%s", data->myQueue, name );
|
||||
|
||||
gchar* contents;
|
||||
gsize length;
|
||||
gboolean success = g_file_get_contents( path, &contents, &length, NULL );
|
||||
XP_ASSERT( success );
|
||||
unlink( path );
|
||||
|
||||
if ( 0 == strncmp( "from: ", contents, 6 ) ) {
|
||||
gchar* eol = strstr( contents, "\n" );
|
||||
*eol = '\0';
|
||||
XP_STRNCPY( addr->u.sms.phone, &contents[6], sizeof(addr->u.sms.phone) );
|
||||
++eol; /* skip NULL */
|
||||
|
||||
gsize out_len;
|
||||
guchar* out = g_base64_decode( eol, &out_len );
|
||||
if ( out_len <= buflen ) {
|
||||
XP_MEMCPY( buf, out, out_len );
|
||||
nRead = out_len;
|
||||
addr->conType = COMMS_CONN_SMS;
|
||||
addr->u.sms.port = data->port;
|
||||
}
|
||||
g_free( out );
|
||||
}
|
||||
|
||||
g_free( contents );
|
||||
|
||||
return nRead;
|
||||
} /* decodeAndDelete */
|
||||
|
||||
XP_S16
|
||||
linux_sms_receive( CommonGlobals* globals, int sock,
|
||||
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr )
|
||||
{
|
||||
XP_S16 nRead = -1;
|
||||
LinSMSData* data = globals->smsData;
|
||||
|
||||
XP_ASSERT( sock == data->fd );
|
||||
|
||||
lock_queue( data );
|
||||
|
||||
/* read required or we'll just get the event again */
|
||||
XP_U8 buffer[sizeof(struct inotify_event) + 16];
|
||||
(void)read( sock, buffer, sizeof(buffer) );
|
||||
|
||||
char shortest[256] = { '\0' };
|
||||
GDir* dir = g_dir_open( data->myQueue, 0, NULL );
|
||||
for ( ; ; ) {
|
||||
const gchar* name = g_dir_read_name( dir );
|
||||
if ( NULL == name ) {
|
||||
break;
|
||||
} else if ( 0 == strcmp( name, LOCK_FILE ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( !shortest[0] || 0 < strcmp( shortest, name ) ) {
|
||||
snprintf( shortest, sizeof(shortest), "%s", name );
|
||||
}
|
||||
}
|
||||
g_dir_close( dir );
|
||||
|
||||
if ( !!shortest[0] ) {
|
||||
nRead = decodeAndDelete( data, shortest, buf, buflen, addr );
|
||||
}
|
||||
|
||||
unlock_queue( data );
|
||||
|
||||
return nRead;
|
||||
} /* linux_sms_receive */
|
||||
|
||||
#endif /* XWFEATURE_SMS */
|
36
xwords4/linux/linuxsms.h
Normal file
36
xwords4/linux/linuxsms.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE";-*- */
|
||||
/*
|
||||
* Copyright 2006-2008 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) any later version.
|
||||
*
|
||||
* 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 _LINUXSMS_H_
|
||||
#define _LINUXSMS_H_
|
||||
|
||||
#ifdef XWFEATURE_SMS
|
||||
|
||||
#include "main.h"
|
||||
|
||||
void linux_sms_init( CommonGlobals* globals, const CommsAddrRec* addr );
|
||||
void linux_sms_close( CommonGlobals* globals );
|
||||
|
||||
XP_S16 linux_sms_send( CommonGlobals* globals, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port );
|
||||
XP_S16 linux_sms_receive( CommonGlobals* globals, int sock,
|
||||
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr );
|
||||
|
||||
#endif /* XWFEATURE_SMS */
|
||||
#endif /* #ifndef _LINUXSMS_H_ */
|
|
@ -86,6 +86,12 @@ typedef struct LaunchParams {
|
|||
const char* hostName;
|
||||
int port;
|
||||
} ip;
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
struct {
|
||||
const char* serverPhone;
|
||||
int port;
|
||||
} sms;
|
||||
#endif
|
||||
} connInfo;
|
||||
|
||||
|
@ -104,6 +110,10 @@ typedef XP_Bool (*Acceptor)( int sock, void* ctxt );
|
|||
typedef void (*AddAcceptorFunc)(int listener, Acceptor func,
|
||||
CommonGlobals* globals, void** storage );
|
||||
|
||||
#ifdef XWFEATURE_SMS
|
||||
typedef struct LinSMSData LinSMSData;
|
||||
#endif
|
||||
|
||||
struct CommonGlobals {
|
||||
LaunchParams* params;
|
||||
|
||||
|
@ -130,11 +140,12 @@ struct CommonGlobals {
|
|||
#if defined XWFEATURE_IP_DIRECT
|
||||
struct LinUDPStuff* udpStuff;
|
||||
#endif
|
||||
#ifdef XWFEATURE_SMS
|
||||
LinSMSData* smsData;
|
||||
#endif
|
||||
|
||||
XWTimerProc timerProcs[NUM_TIMERS_PLUS_ONE];
|
||||
void* timerClosures[NUM_TIMERS_PLUS_ONE];
|
||||
|
||||
MPSLOT
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue