mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-03 23:04:08 +01:00
Move transision of cmd and gameid and port (pending) into smsproto
common code, simplifying and unifying what the platform-specific code has to do. Seems to work.
This commit is contained in:
parent
a65498c132
commit
9ddc6e4b89
13 changed files with 475 additions and 416 deletions
|
@ -41,6 +41,8 @@ import org.eehouse.android.xw4.MultiService.MultiEvent;
|
|||
import org.eehouse.android.xw4.jni.CommsAddrRec;
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||
import org.eehouse.android.xw4.jni.XwJNI;
|
||||
import org.eehouse.android.xw4.jni.XwJNI.SMSProtoMsg;
|
||||
import org.eehouse.android.xw4.jni.XwJNI.SMS_CMD;
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -82,10 +84,6 @@ public class SMSService extends XWService {
|
|||
|
||||
private static Boolean s_showToasts = null;
|
||||
|
||||
// All messages are base64-encoded byte arrays. The first byte is
|
||||
// always one of these. What follows depends.
|
||||
private enum SMS_CMD { NONE, INVITE, DATA, DEATH, ACK, };
|
||||
|
||||
private BroadcastReceiver m_sentReceiver;
|
||||
private BroadcastReceiver m_receiveReceiver;
|
||||
private OnSharedPreferenceChangeListener m_prefsListener;
|
||||
|
@ -360,7 +358,7 @@ public class SMSService extends XWService {
|
|||
break;
|
||||
case RESEND:
|
||||
phone = intent.getStringExtra( PHONE );
|
||||
resendFor( phone, null, false );
|
||||
resendFor( phone );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,98 +375,62 @@ public class SMSService extends XWService {
|
|||
|
||||
private void inviteRemote( String phone, String nliData )
|
||||
{
|
||||
Log.i( TAG, "inviteRemote()" );
|
||||
ByteArrayOutputStream bas = new ByteArrayOutputStream( 128 );
|
||||
DataOutputStream dos = new DataOutputStream( bas );
|
||||
try {
|
||||
dos.writeUTF( nliData );
|
||||
dos.flush();
|
||||
|
||||
send( SMS_CMD.INVITE, bas.toByteArray(), phone );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
byte[] asBytes = nliData.getBytes( "UTF-8" );
|
||||
resendFor( phone, SMS_CMD.INVITE, 0, asBytes, true );
|
||||
} catch ( java.io.UnsupportedEncodingException uee ) {
|
||||
Log.ex( TAG, uee );
|
||||
}
|
||||
}
|
||||
|
||||
private void ackInvite( String phone, int gameID )
|
||||
{
|
||||
ByteArrayOutputStream bas = new ByteArrayOutputStream( 128 );
|
||||
DataOutputStream dos = new DataOutputStream( bas );
|
||||
try {
|
||||
dos.writeInt( gameID );
|
||||
dos.flush();
|
||||
|
||||
send( SMS_CMD.ACK, bas.toByteArray(), phone );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
}
|
||||
resendFor( phone, SMS_CMD.ACK_INVITE, gameID, null );
|
||||
}
|
||||
|
||||
private void sendDiedPacket( String phone, int gameID )
|
||||
{
|
||||
if ( !s_sentDied.contains(gameID) ) {
|
||||
ByteArrayOutputStream bas = new ByteArrayOutputStream( 32 );
|
||||
DataOutputStream dos = new DataOutputStream( bas );
|
||||
try {
|
||||
dos.writeInt( gameID );
|
||||
dos.flush();
|
||||
send( SMS_CMD.DEATH, bas.toByteArray(), phone );
|
||||
s_sentDied.add( gameID );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
}
|
||||
resendFor( phone, SMS_CMD.DEATH, gameID, null );
|
||||
}
|
||||
}
|
||||
|
||||
public int sendPacket( String phone, int gameID, byte[] bytes )
|
||||
{
|
||||
int nSent = -1;
|
||||
ByteArrayOutputStream bas = new ByteArrayOutputStream( 128 );
|
||||
DataOutputStream dos = new DataOutputStream( bas );
|
||||
try {
|
||||
dos.writeInt( gameID );
|
||||
dos.write( bytes, 0, bytes.length );
|
||||
dos.flush();
|
||||
send( SMS_CMD.DATA, bas.toByteArray(), phone );
|
||||
nSent = bytes.length;
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
}
|
||||
return nSent;
|
||||
resendFor( phone, SMS_CMD.DATA, gameID, bytes );
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
private void send( SMS_CMD cmd, byte[] bytes, String phone )
|
||||
throws java.io.IOException
|
||||
private void sendOrRetry( byte[][] msgs, String toPhone, int waitSecs )
|
||||
{
|
||||
Log.d( TAG, "send(%s, len=%d)", cmd, bytes.length );
|
||||
ByteArrayOutputStream bas = new ByteArrayOutputStream( 128 );
|
||||
DataOutputStream dos = new DataOutputStream( bas );
|
||||
dos.writeByte( SMS_PROTO_VERSION );
|
||||
if ( SMS_PROTO_VERSION_WITHPORT <= SMS_PROTO_VERSION ) {
|
||||
dos.writeShort( getNBSPort() );
|
||||
if ( null != msgs ) {
|
||||
sendBuffers( msgs, toPhone );
|
||||
}
|
||||
dos.writeByte( cmd.ordinal() );
|
||||
dos.write( bytes, 0, bytes.length );
|
||||
dos.flush();
|
||||
|
||||
byte[] data = bas.toByteArray();
|
||||
if ( waitSecs > 0 ) {
|
||||
postResend( toPhone, waitSecs );
|
||||
}
|
||||
}
|
||||
|
||||
private void resendFor( String toPhone, SMS_CMD cmd, int gameID, byte[] data )
|
||||
{
|
||||
boolean newSMSEnabled = XWPrefs.getSMSProtoEnabled( this );
|
||||
boolean forceNow = !newSMSEnabled; // || cmd == SMS_CMD.INVITE;
|
||||
resendFor( phone, data, forceNow );
|
||||
resendFor( toPhone, cmd, gameID, data, forceNow );
|
||||
}
|
||||
|
||||
private void resendFor( String phone, byte[] data, boolean forceNow )
|
||||
private void resendFor( String toPhone )
|
||||
{
|
||||
resendFor( toPhone, SMS_CMD.NONE, 0, null, false );
|
||||
}
|
||||
|
||||
private void resendFor( String toPhone, SMS_CMD cmd, int gameID, byte[] data,
|
||||
boolean forceNow )
|
||||
{
|
||||
int[] waitSecs = { 0 };
|
||||
byte[][] msgs = XwJNI.smsproto_prepOutbound( data, phone, forceNow, waitSecs );
|
||||
if ( null != msgs ) {
|
||||
sendBuffers( msgs, phone );
|
||||
}
|
||||
if ( waitSecs[0] > 0 ) {
|
||||
Assert.assertFalse( forceNow );
|
||||
postResend( phone, waitSecs[0] );
|
||||
}
|
||||
byte[][] msgs = XwJNI.smsproto_prepOutbound( cmd, gameID, data, toPhone,
|
||||
getNBSPort(), forceNow,
|
||||
waitSecs );
|
||||
sendOrRetry( msgs, toPhone, waitSecs[0] );
|
||||
}
|
||||
|
||||
private void postResend( final String phone, final int waitSecs )
|
||||
|
@ -492,51 +454,38 @@ public class SMSService extends XWService {
|
|||
} ).start();
|
||||
}
|
||||
|
||||
private void receive( SMS_CMD cmd, byte[] data, String phone )
|
||||
private void receive( SMSProtoMsg msg, String phone )
|
||||
{
|
||||
Log.i( TAG, "receive(cmd=%s)", cmd.toString() );
|
||||
DataInputStream dis =
|
||||
new DataInputStream( new ByteArrayInputStream(data) );
|
||||
try {
|
||||
switch( cmd ) {
|
||||
case INVITE:
|
||||
String nliData = dis.readUTF();
|
||||
makeForInvite( phone, new NetLaunchInfo( this, nliData ) );
|
||||
break;
|
||||
case DATA:
|
||||
int gameID = dis.readInt();
|
||||
byte[] rest = new byte[dis.available()];
|
||||
dis.readFully( rest );
|
||||
if ( feedMessage( gameID, rest, new CommsAddrRec( phone ) ) ) {
|
||||
SMSResendReceiver.resetTimer( this );
|
||||
}
|
||||
break;
|
||||
case DEATH:
|
||||
gameID = dis.readInt();
|
||||
postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
|
||||
break;
|
||||
case ACK:
|
||||
gameID = dis.readInt();
|
||||
postEvent( MultiEvent.NEWGAME_SUCCESS,
|
||||
gameID );
|
||||
break;
|
||||
default:
|
||||
Log.w( TAG, "unexpected cmd %s", cmd.toString() );
|
||||
break;
|
||||
Log.i( TAG, "receive(cmd=%s)", msg.cmd );
|
||||
switch( msg.cmd ) {
|
||||
case INVITE:
|
||||
NetLaunchInfo nli = new NetLaunchInfo( this, new String(msg.data) );
|
||||
makeForInvite( phone, nli );
|
||||
break;
|
||||
case DATA:
|
||||
if ( feedMessage( msg.gameID, msg.data, new CommsAddrRec( phone ) ) ) {
|
||||
SMSResendReceiver.resetTimer( this );
|
||||
}
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
break;
|
||||
case DEATH:
|
||||
postEvent( MultiEvent.MESSAGE_NOGAME, msg.gameID );
|
||||
break;
|
||||
case ACK_INVITE:
|
||||
postEvent( MultiEvent.NEWGAME_SUCCESS, msg.gameID );
|
||||
break;
|
||||
default:
|
||||
Log.w( TAG, "unexpected cmd %s", msg.cmd );
|
||||
Assert.assertFalse( BuildConfig.DEBUG );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveBuffer( byte[] buffer, String senderPhone )
|
||||
{
|
||||
byte[][] msgs = XwJNI.smsproto_prepInbound( buffer, senderPhone );
|
||||
SMSProtoMsg[] msgs = XwJNI.smsproto_prepInbound( buffer, senderPhone );
|
||||
if ( null != msgs ) {
|
||||
for ( byte[] msg : msgs ) {
|
||||
if ( !disAssemble( senderPhone, msg ) ) {
|
||||
Log.e( TAG, "failed on message from %s", senderPhone );
|
||||
}
|
||||
for ( SMSProtoMsg msg : msgs ) {
|
||||
receive( msg, senderPhone );
|
||||
}
|
||||
postEvent( MultiEvent.SMS_RECEIVE_OK );
|
||||
} else {
|
||||
|
@ -545,44 +494,6 @@ public class SMSService extends XWService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean disAssemble( String senderPhone, byte[] fullMsg )
|
||||
{
|
||||
boolean success = false;
|
||||
DataInputStream dis =
|
||||
new DataInputStream( new ByteArrayInputStream(fullMsg) );
|
||||
try {
|
||||
byte proto = dis.readByte();
|
||||
short myPort = getNBSPort();
|
||||
short gotPort;
|
||||
if ( SMS_PROTO_VERSION_WITHPORT > proto ) {
|
||||
gotPort = myPort;
|
||||
} else {
|
||||
gotPort = dis.readShort();
|
||||
}
|
||||
if ( SMS_PROTO_VERSION < proto ) {
|
||||
Log.w( TAG, "SMSService.disAssemble: bad proto %d from %s;"
|
||||
+ " dropping", proto, senderPhone );
|
||||
postEvent( MultiEvent.BAD_PROTO_SMS, senderPhone );
|
||||
} else if ( gotPort != myPort ) {
|
||||
Log.d( TAG, "disAssemble(): received on port %d"
|
||||
+ " but expected %d", gotPort, myPort );
|
||||
} else {
|
||||
SMS_CMD cmd = SMS_CMD.values()[dis.readByte()];
|
||||
byte[] rest = new byte[dis.available()];
|
||||
dis.readFully( rest );
|
||||
receive( cmd, rest, senderPhone );
|
||||
success = true;
|
||||
}
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Log.ex( TAG, ioe );
|
||||
} catch ( ArrayIndexOutOfBoundsException oob ) {
|
||||
// enum this older code doesn't know about, or just another app's
|
||||
// message; drop it
|
||||
Log.w( TAG, "disAssemble: dropping message with too-new enum" );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postNotification( String phone, int gameID, long rowid )
|
||||
{
|
||||
|
|
|
@ -403,15 +403,22 @@ public class XwJNI {
|
|||
public static native boolean comms_getAddrDisabled( GamePtr gamePtr, CommsConnType typ,
|
||||
boolean send );
|
||||
|
||||
public static byte[][] smsproto_prepOutbound( byte[] buf, String phone, boolean forceNow,
|
||||
/*out*/ int[] waitSecs )
|
||||
{
|
||||
int nowSeconds = (int)(System.currentTimeMillis() / 1000);
|
||||
return smsproto_prepOutbound( getJNI().m_ptr, buf, phone, nowSeconds,
|
||||
forceNow, waitSecs );
|
||||
public enum SMS_CMD { NONE, INVITE, DATA, DEATH, ACK_INVITE, };
|
||||
public static class SMSProtoMsg {
|
||||
public SMS_CMD cmd;
|
||||
public int gameID;
|
||||
public byte[] data; // other cases
|
||||
}
|
||||
|
||||
public static byte[][] smsproto_prepInbound( byte[] data, String fromPhone )
|
||||
public static byte[][]
|
||||
smsproto_prepOutbound( SMS_CMD cmd, int gameID, byte[] buf, String phone,
|
||||
int port, boolean forceNow, /*out*/ int[] waitSecs )
|
||||
{
|
||||
return smsproto_prepOutbound( getJNI().m_ptr, cmd, gameID, buf, phone,
|
||||
port, forceNow, waitSecs );
|
||||
}
|
||||
|
||||
public static SMSProtoMsg[] smsproto_prepInbound( byte[] data, String fromPhone )
|
||||
{
|
||||
return smsproto_prepInbound( getJNI().m_ptr, data, fromPhone );
|
||||
}
|
||||
|
@ -502,13 +509,14 @@ public class XwJNI {
|
|||
private static native int dict_iter_init( int jniState, byte[] dict,
|
||||
String name, String path );
|
||||
|
||||
private static native byte[][] smsproto_prepOutbound( int jniState, byte[] buf,
|
||||
String phone, int nowSeconds,
|
||||
boolean forceNow,
|
||||
/*out*/int[] waitSecs );
|
||||
private static native byte[][]
|
||||
smsproto_prepOutbound( int jniState, SMS_CMD cmd, int gameID, byte[] buf,
|
||||
String phone, int port, boolean forceNow,
|
||||
/*out*/int[] waitSecs );
|
||||
|
||||
private static native byte[][] smsproto_prepInbound( int jniState, byte[] data,
|
||||
String fromPhone );
|
||||
private static native SMSProtoMsg[] smsproto_prepInbound( int jniState,
|
||||
byte[] data,
|
||||
String fromPhone );
|
||||
|
||||
private static native boolean haveEnv( int jniState );
|
||||
}
|
||||
|
|
|
@ -772,10 +772,11 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getTileValue
|
|||
static jobjectArray
|
||||
msgArrayToByteArrays( JNIEnv* env, const SMSMsgArray* arr )
|
||||
{
|
||||
XP_ASSERT( arr->format == FORMAT_NET );
|
||||
jclass clas = (*env)->FindClass( env, "[B" );
|
||||
jobjectArray result = (*env)->NewObjectArray( env, arr->nMsgs, clas, NULL );
|
||||
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
SMSMsg* msg = &arr->msgs[ii];
|
||||
SMSMsgNet* msg = &arr->u.msgsNet[ii];
|
||||
jbyteArray arr = makeByteArray( env, msg->len, (const jbyte*)msg->data );
|
||||
(*env)->SetObjectArrayElement( env, result, ii, arr );
|
||||
deleteLocalRef( env, arr );
|
||||
|
@ -783,15 +784,43 @@ msgArrayToByteArrays( JNIEnv* env, const SMSMsgArray* arr )
|
|||
return result;
|
||||
}
|
||||
|
||||
static jobjectArray
|
||||
msgArrayToJMsgArray( JNIEnv* env, const SMSMsgArray* arr )
|
||||
{
|
||||
XP_ASSERT( arr->format == FORMAT_LOC );
|
||||
jclass clas = (*env)->FindClass( env, PKG_PATH("jni/XwJNI$SMSProtoMsg") );
|
||||
jobjectArray result = (*env)->NewObjectArray( env, arr->nMsgs, clas, NULL );
|
||||
|
||||
jmethodID initId = (*env)->GetMethodID( env, clas, "<init>", "()V" );
|
||||
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
jobject jmsg = (*env)->NewObject( env, clas, initId );
|
||||
|
||||
const SMSMsgLoc* msgsLoc = &arr->u.msgsLoc[ii];
|
||||
intToJenumField( env, jmsg, msgsLoc->cmd, "cmd", PKG_PATH("jni/XwJNI$SMS_CMD") );
|
||||
setInt( env, jmsg, "gameID", msgsLoc->gameID );
|
||||
|
||||
jbyteArray arr = makeByteArray( env, msgsLoc->len,
|
||||
(const jbyte*)msgsLoc->data );
|
||||
setObject( env, jmsg, "data", "[B", arr );
|
||||
deleteLocalRef( env, arr );
|
||||
|
||||
(*env)->SetObjectArrayElement( env, result, ii, jmsg );
|
||||
deleteLocalRef( env, jmsg );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_smsproto_1prepOutbound
|
||||
( JNIEnv* env, jclass C, jint jniGlobalPtr, jbyteArray jData,
|
||||
jstring jToPhone, jint jNow, jboolean jForce, jintArray jWaitSecsArr )
|
||||
( JNIEnv* env, jclass C, jint jniGlobalPtr, jobject jCmd, jint jGameID,
|
||||
jbyteArray jData, jstring jToPhone, jint jPort, jboolean jForce,
|
||||
jintArray jWaitSecsArr )
|
||||
{
|
||||
jobjectArray result = NULL;
|
||||
JNIGlobalState* globalState = (JNIGlobalState*)jniGlobalPtr;
|
||||
map_thread( &globalState->ti, env );
|
||||
|
||||
SMS_CMD cmd = jEnumToInt( env, jCmd );
|
||||
jbyte* data = NULL;
|
||||
int len = 0;
|
||||
if ( NULL != jData ) {
|
||||
|
@ -801,8 +830,9 @@ Java_org_eehouse_android_xw4_jni_XwJNI_smsproto_1prepOutbound
|
|||
const char* toPhone = (*env)->GetStringUTFChars( env, jToPhone, NULL );
|
||||
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( globalState->smsProto, (const XP_U8*)data,
|
||||
len, toPhone, jForce, &waitSecs );
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( globalState->smsProto, cmd, jGameID,
|
||||
(const XP_U8*)data, len,
|
||||
toPhone, jPort, jForce, &waitSecs );
|
||||
if ( !!arr ) {
|
||||
result = msgArrayToByteArrays( env, arr );
|
||||
smsproto_freeMsgArray( globalState->smsProto, arr );
|
||||
|
@ -820,14 +850,14 @@ Java_org_eehouse_android_xw4_jni_XwJNI_smsproto_1prepOutbound
|
|||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_smsproto_1prepInbound
|
||||
( JNIEnv* env, jclass C, jint jniGlobalPtr, jbyteArray jData,
|
||||
jstring jFromPhone )
|
||||
( JNIEnv* env, jclass C, jint jniGlobalPtr, jbyteArray jData, jstring jFromPhone )
|
||||
{
|
||||
jobjectArray result = NULL;
|
||||
JNIGlobalState* globalState = (JNIGlobalState*)jniGlobalPtr;
|
||||
map_thread( &globalState->ti, env );
|
||||
|
||||
if ( !!jData ) {
|
||||
JNIGlobalState* globalState = (JNIGlobalState*)jniGlobalPtr;
|
||||
map_thread( &globalState->ti, env );
|
||||
|
||||
int len = (*env)->GetArrayLength( env, jData );
|
||||
jbyte* data = (*env)->GetByteArrayElements( env, jData, NULL );
|
||||
const char* fromPhone = (*env)->GetStringUTFChars( env, jFromPhone, NULL );
|
||||
|
@ -835,7 +865,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_smsproto_1prepInbound
|
|||
SMSMsgArray* arr = smsproto_prepInbound( globalState->smsProto, fromPhone,
|
||||
(XP_U8*)data, len );
|
||||
if ( !!arr ) {
|
||||
result = msgArrayToByteArrays( env, arr );
|
||||
result = msgArrayToJMsgArray( env, arr );
|
||||
smsproto_freeMsgArray( globalState->smsProto, arr );
|
||||
}
|
||||
|
||||
|
|
|
@ -3,24 +3,31 @@
|
|||
set -e -u
|
||||
|
||||
NODE=xw4
|
||||
VARIANT=xw4
|
||||
CLASSPATH=${CLASSPATH:-""}
|
||||
|
||||
usage() {
|
||||
[ $# -gt 0 ] && echo "Error: $1"
|
||||
echo "usage: $0 "
|
||||
echo "usage: $0 [--variant xw4|xw4d]"
|
||||
exit 1
|
||||
}
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--help) usage
|
||||
;;
|
||||
*) usage "unexpected flag $1"
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
--variant)
|
||||
VARIANT=$2
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
usage "unexpected flag $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cd $(dirname $0)/../app/build/intermediates/classes/${NODE}/debug
|
||||
cd $(dirname $0)/../app/build/intermediates/classes/${VARIANT}/debug
|
||||
|
||||
javah -o /tmp/javah$$.txt org.eehouse.android.${NODE}.jni.XwJNI
|
||||
javap -s org.eehouse.android.${NODE}.jni.XwJNI
|
||||
|
|
|
@ -77,6 +77,7 @@ void nli_makeAddrRec( const NetLaunchInfo* invit, CommsAddrRec* addr );
|
|||
|
||||
void nli_setDevID( NetLaunchInfo* invit, XP_U32 devID );
|
||||
void nli_setInviteID( NetLaunchInfo* invit, const XP_UCHAR* inviteID );
|
||||
void nli_setGameName( NetLaunchInfo* invit, const XP_UCHAR* gameName );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
typedef struct _MsgRec {
|
||||
XP_U32 createSeconds;
|
||||
SMSMsg msg;
|
||||
SMSMsgNet msgNet;
|
||||
} MsgRec;
|
||||
|
||||
typedef struct _ToPhoneRec {
|
||||
|
@ -82,11 +82,13 @@ struct SMSProto {
|
|||
#define KEY_NEXTID PERSIST_KEY("nextID")
|
||||
|
||||
static int nextMsgID( SMSProto* state );
|
||||
static SMSMsgArray* toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld );
|
||||
static XWStreamCtxt* mkStream( SMSProto* state );
|
||||
static SMSMsgArray* toNetMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld );
|
||||
static ToPhoneRec* getForPhone( SMSProto* state, const XP_UCHAR* phone,
|
||||
XP_Bool create );
|
||||
static void addToRec( SMSProto* state, ToPhoneRec* rec, const XP_U8* buf,
|
||||
XP_U16 buflen, XP_U32 nowSeconds );
|
||||
static void addToOutRec( SMSProto* state, ToPhoneRec* rec, SMS_CMD cmd,
|
||||
XP_U32 gameID, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 nowSeconds );
|
||||
static void addMessage( SMSProto* state, const XP_UCHAR* fromPhone, int msgID,
|
||||
int indx, int count, const XP_U8* data, XP_U16 len );
|
||||
static SMSMsgArray* completeMsgs( SMSProto* state, SMSMsgArray* arr,
|
||||
|
@ -149,6 +151,43 @@ smsproto_free( SMSProto* state )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
headerToStream( XWStreamCtxt* stream, SMS_CMD cmd, XP_U32 gameID )
|
||||
{
|
||||
// XP_LOGF( "%s(cmd: %d; gameID: %d)", __func__, cmd, gameID );
|
||||
stream_putU8( stream, cmd );
|
||||
switch ( cmd ) {
|
||||
case NONE:
|
||||
XP_ASSERT(0);
|
||||
break;
|
||||
case INVITE:
|
||||
break;
|
||||
default:
|
||||
stream_putU32( stream, gameID );
|
||||
}
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
headerFromStream( XWStreamCtxt* stream, SMS_CMD* cmd, XP_U32* gameID )
|
||||
{
|
||||
XP_Bool success = XP_FALSE;
|
||||
XP_U8 tmp;
|
||||
|
||||
if ( stream_gotU8( stream, &tmp ) ) {
|
||||
*cmd = tmp;
|
||||
switch( *cmd ) {
|
||||
case INVITE:
|
||||
success = XP_TRUE;
|
||||
break;
|
||||
default:
|
||||
success = stream_gotU32( stream, gameID );
|
||||
break;
|
||||
}
|
||||
}
|
||||
// XP_LOGF( "%s() => cmd: %d; gameID: %d", __func__, *cmd, *gameID );
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Maintain a list of pending messages per phone number. When called and it's
|
||||
* been at least some amount of time since we last added something, or at
|
||||
* least some longer time since the oldest message was added, return an array
|
||||
|
@ -159,26 +198,27 @@ smsproto_free( SMSProto* state )
|
|||
* UtilCtxt around.
|
||||
*/
|
||||
SMSMsgArray*
|
||||
smsproto_prepOutbound( SMSProto* state, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* toPhone,
|
||||
XP_Bool forceOld, XP_U16* waitSecsP )
|
||||
smsproto_prepOutbound( SMSProto* state, SMS_CMD cmd, XP_U32 gameID,
|
||||
const void* buf, XP_U16 buflen, const XP_UCHAR* toPhone,
|
||||
int toPort, XP_Bool forceOld, XP_U16* waitSecsP )
|
||||
{
|
||||
XP_USE( toPort );
|
||||
SMSMsgArray* result = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
XP_UCHAR* checksum = dutil_md5sum( state->dutil, buf, buflen );
|
||||
XP_LOGF( "%s(): len=%d, sum=%s, toPhone=%s", __func__, buflen,
|
||||
checksum, toPhone );
|
||||
XP_LOGF( "%s(cmd=%d, gameID=%d): len=%d, sum=%s, toPhone=%s", __func__, cmd,
|
||||
gameID, buflen, checksum, toPhone );
|
||||
XP_FREEP( state->mpool, &checksum );
|
||||
#endif
|
||||
|
||||
checkThread( state );
|
||||
ToPhoneRec* rec = getForPhone( state, toPhone, !!buf );
|
||||
ToPhoneRec* rec = getForPhone( state, toPhone, cmd != NONE );
|
||||
|
||||
/* First, add the new message (if present) to the array */
|
||||
XP_U32 nowSeconds = dutil_getCurSeconds( state->dutil );
|
||||
if ( !!buf ) {
|
||||
addToRec( state, rec, buf, buflen, nowSeconds );
|
||||
if ( cmd != NONE ) {
|
||||
addToOutRec( state, rec, cmd, gameID, buf, buflen, nowSeconds );
|
||||
}
|
||||
|
||||
/* rec will be non-null if there's something in it */
|
||||
|
@ -191,7 +231,7 @@ smsproto_prepOutbound( SMSProto* state, const XP_U8* buf,
|
|||
}
|
||||
|
||||
if ( doSend ) {
|
||||
result = toMsgs( state, rec, forceOld );
|
||||
result = toNetMsgs( state, rec, forceOld );
|
||||
freeForPhone( state, toPhone );
|
||||
}
|
||||
|
||||
|
@ -207,15 +247,34 @@ smsproto_prepOutbound( SMSProto* state, const XP_U8* buf,
|
|||
}
|
||||
|
||||
static SMSMsgArray*
|
||||
appendMsg( SMSProto* state, SMSMsgArray* arr, SMSMsg* msg )
|
||||
appendLocMsg( SMSProto* state, SMSMsgArray* arr, SMSMsgLoc* msg )
|
||||
{
|
||||
if ( NULL == arr ) {
|
||||
arr = XP_CALLOC( state->mpool, sizeof(*arr) );
|
||||
arr->format = FORMAT_LOC;
|
||||
} else {
|
||||
XP_ASSERT( arr->format == FORMAT_LOC );
|
||||
}
|
||||
|
||||
arr->msgs = XP_REALLOC( state->mpool, arr->msgs,
|
||||
(arr->nMsgs + 1) * sizeof(*arr->msgs) );
|
||||
arr->msgs[arr->nMsgs++] = *msg;
|
||||
arr->u.msgsLoc = XP_REALLOC( state->mpool, arr->u.msgsLoc,
|
||||
(arr->nMsgs + 1) * sizeof(*arr->u.msgsLoc) );
|
||||
arr->u.msgsLoc[arr->nMsgs++] = *msg;
|
||||
return arr;
|
||||
}
|
||||
|
||||
static SMSMsgArray*
|
||||
appendNetMsg( SMSProto* state, SMSMsgArray* arr, SMSMsgNet* msg )
|
||||
{
|
||||
if ( NULL == arr ) {
|
||||
arr = XP_CALLOC( state->mpool, sizeof(*arr) );
|
||||
arr->format = FORMAT_NET;
|
||||
} else {
|
||||
XP_ASSERT( arr->format == FORMAT_NET );
|
||||
}
|
||||
|
||||
arr->u.msgsNet = XP_REALLOC( state->mpool, arr->u.msgsNet,
|
||||
(arr->nMsgs + 1) * sizeof(*arr->u.msgsNet) );
|
||||
arr->u.msgsNet[arr->nMsgs++] = *msg;
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -226,8 +285,7 @@ smsproto_prepInbound( SMSProto* state, const XP_UCHAR* fromPhone,
|
|||
XP_LOGF( "%s(): len=%d, fromPhone=%s", __func__, len, fromPhone );
|
||||
checkThread( state );
|
||||
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(state->mpool)
|
||||
dutil_getVTManager(state->dutil) );
|
||||
XWStreamCtxt* stream = mkStream( state );
|
||||
stream_putBytes( stream, data, len );
|
||||
|
||||
SMSMsgArray* result = NULL;
|
||||
|
@ -253,20 +311,34 @@ smsproto_prepInbound( SMSProto* state, const XP_UCHAR* fromPhone,
|
|||
XP_U8 oneLen, msgID;
|
||||
while ( stream_gotU8( stream, &oneLen )
|
||||
&& stream_gotU8( stream, &msgID ) ) {
|
||||
XP_U8 buf[oneLen];
|
||||
if ( stream_gotBytes( stream, buf, oneLen ) ) {
|
||||
SMSMsg msg = { .len = oneLen,
|
||||
.msgID = msgID,
|
||||
.data = XP_MALLOC( state->mpool, oneLen ),
|
||||
};
|
||||
XP_MEMCPY( msg.data, buf, oneLen );
|
||||
result = appendMsg( state, result, &msg );
|
||||
XP_U8 tmp[oneLen];
|
||||
stream_getBytes( stream, tmp, oneLen );
|
||||
|
||||
XWStreamCtxt* msgStream = mkStream( state );
|
||||
stream_putBytes( msgStream, tmp, oneLen );
|
||||
|
||||
XP_U32 gameID;
|
||||
SMS_CMD cmd;
|
||||
if ( headerFromStream( msgStream, &cmd, &gameID ) ) {
|
||||
XP_U16 msgLen = stream_getSize( msgStream );
|
||||
XP_U8 buf[msgLen];
|
||||
if ( stream_gotBytes( msgStream, buf, msgLen ) ) {
|
||||
SMSMsgLoc msg = { .len = msgLen,
|
||||
.cmd = cmd,
|
||||
.gameID = gameID,
|
||||
.data = XP_MALLOC( state->mpool, msgLen ),
|
||||
};
|
||||
XP_MEMCPY( msg.data, buf, msgLen );
|
||||
result = appendLocMsg( state, result, &msg );
|
||||
}
|
||||
}
|
||||
stream_destroy( msgStream );
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XP_LOGF( "%s(): unexpected proto %d", __func__, proto );
|
||||
XP_ASSERT( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -283,17 +355,31 @@ smsproto_freeMsgArray( SMSProto* state, SMSMsgArray* arr )
|
|||
checkThread( state );
|
||||
|
||||
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
XP_FREEP( state->mpool, &arr->msgs[ii].data );
|
||||
XP_U8** ptr = arr->format == FORMAT_LOC
|
||||
? &arr->u.msgsLoc[ii].data : &arr->u.msgsNet[ii].data;
|
||||
XP_FREEP( state->mpool, ptr );
|
||||
}
|
||||
|
||||
XP_FREEP( state->mpool, &arr->msgs );
|
||||
void** ptr;
|
||||
switch( arr->format ) {
|
||||
case FORMAT_LOC:
|
||||
ptr = (void**)&arr->u.msgsLoc;
|
||||
break;
|
||||
case FORMAT_NET:
|
||||
ptr = (void**)&arr->u.msgsNet;
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
ptr = NULL;
|
||||
}
|
||||
XP_FREEP( state->mpool, ptr );
|
||||
XP_FREEP( state->mpool, &arr );
|
||||
}
|
||||
|
||||
static void
|
||||
freeMsg( SMSProto* state, MsgRec** msgp )
|
||||
{
|
||||
XP_FREEP( state->mpool, &(*msgp)->msg.data );
|
||||
XP_FREEP( state->mpool, &(*msgp)->msgNet.data );
|
||||
XP_FREEP( state->mpool, msgp );
|
||||
}
|
||||
|
||||
|
@ -353,20 +439,28 @@ freeForPhone( SMSProto* state, const XP_UCHAR* phone )
|
|||
}
|
||||
|
||||
static void
|
||||
addToRec( SMSProto* state, ToPhoneRec* rec, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 nowSeconds )
|
||||
addToOutRec( SMSProto* state, ToPhoneRec* rec, SMS_CMD cmd,
|
||||
XP_U32 gameID, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 nowSeconds )
|
||||
{
|
||||
XWStreamCtxt* stream = mkStream( state );
|
||||
headerToStream( stream, cmd, gameID );
|
||||
stream_putBytes( stream, buf, buflen );
|
||||
|
||||
MsgRec* mRec = XP_CALLOC( state->mpool, sizeof(*rec) );
|
||||
mRec->msg.len = buflen;
|
||||
mRec->msg.data = XP_MALLOC( state->mpool, buflen );
|
||||
XP_MEMCPY( mRec->msg.data, buf, buflen );
|
||||
XP_U16 len = stream_getSize( stream );
|
||||
mRec->msgNet.len = len;
|
||||
mRec->msgNet.data = XP_MALLOC( state->mpool, len );
|
||||
XP_MEMCPY( mRec->msgNet.data, stream_getPtr(stream), len );
|
||||
stream_destroy( stream );
|
||||
|
||||
mRec->createSeconds = nowSeconds;
|
||||
|
||||
rec->msgs = XP_REALLOC( state->mpool, rec->msgs, (1 + rec->nMsgs) * sizeof(*rec->msgs) );
|
||||
rec->msgs[rec->nMsgs++] = mRec;
|
||||
rec->totalSize += buflen;
|
||||
rec->totalSize += len;
|
||||
XP_LOGF( "%s(): added msg to %s of len %d; total now %d", __func__, rec->phone,
|
||||
buflen, rec->totalSize );
|
||||
len, rec->totalSize );
|
||||
|
||||
if ( rec->nMsgs == 1 ) {
|
||||
rec->createSeconds = nowSeconds;
|
||||
|
@ -513,9 +607,7 @@ savePartials( SMSProto* state )
|
|||
{
|
||||
checkThread( state );
|
||||
|
||||
XWStreamCtxt* stream
|
||||
= mem_stream_make_raw( MPPARM(state->mpool)
|
||||
dutil_getVTManager(state->dutil) );
|
||||
XWStreamCtxt* stream = mkStream( state );
|
||||
stream_putU8( stream, PARTIALS_FORMAT );
|
||||
|
||||
stream_putU8( stream, state->nFromPhones );
|
||||
|
@ -553,8 +645,8 @@ savePartials( SMSProto* state )
|
|||
static void
|
||||
restorePartials( SMSProto* state )
|
||||
{
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(state->mpool)
|
||||
dutil_getVTManager(state->dutil) );
|
||||
XWStreamCtxt* stream = mkStream( state );
|
||||
|
||||
dutil_loadStream( state->dutil, KEY_PARTIALS, stream );
|
||||
if ( stream_getSize( stream ) >= 1
|
||||
&& PARTIALS_FORMAT == stream_getU8( stream ) ) {
|
||||
|
@ -607,16 +699,24 @@ completeMsgs( SMSProto* state, SMSMsgArray* arr, const XP_UCHAR* fromPhone,
|
|||
}
|
||||
|
||||
if ( haveAll ) {
|
||||
SMSMsg msg = { .len = len,
|
||||
.msgID = msgID,
|
||||
.data = XP_MALLOC( state->mpool, len ),
|
||||
};
|
||||
XP_U8* ptr = msg.data;
|
||||
XWStreamCtxt* stream = mkStream( state );
|
||||
for ( int ii = 0; ii < rec->count; ++ii ) {
|
||||
XP_MEMCPY( ptr, rec->parts[ii].data, rec->parts[ii].len );
|
||||
ptr += rec->parts[ii].len;
|
||||
stream_putBytes( stream, rec->parts[ii].data, rec->parts[ii].len );
|
||||
}
|
||||
arr = appendMsg( state, arr, &msg );
|
||||
|
||||
XP_U32 gameID;
|
||||
SMS_CMD cmd;
|
||||
if ( headerFromStream( stream, &cmd, &gameID ) ) {
|
||||
XP_U16 len = stream_getSize( stream );
|
||||
SMSMsgLoc msg = { .len = len,
|
||||
.cmd = cmd,
|
||||
.gameID = gameID,
|
||||
.data = XP_MALLOC( state->mpool, len ),
|
||||
};
|
||||
stream_getBytes( stream, msg.data, len );
|
||||
arr = appendLocMsg( state, arr, &msg );
|
||||
}
|
||||
stream_destroy( stream );
|
||||
|
||||
freeMsgIDRec( state, rec, fromPhoneIndex, msgIDIndex );
|
||||
}
|
||||
|
@ -625,13 +725,13 @@ completeMsgs( SMSProto* state, SMSMsgArray* arr, const XP_UCHAR* fromPhone,
|
|||
}
|
||||
|
||||
static SMSMsgArray*
|
||||
toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
||||
toNetMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
||||
{
|
||||
SMSMsgArray* result = NULL;
|
||||
|
||||
for ( XP_U16 ii = 0; ii < rec->nMsgs; ) {
|
||||
// XP_LOGF( "%s(): looking at msg %d of %d", __func__, ii, rec->nMsgs );
|
||||
XP_U16 count = (rec->msgs[ii]->msg.len + (MAX_LEN_BINARY-1)) / MAX_LEN_BINARY;
|
||||
XP_U16 count = (rec->msgs[ii]->msgNet.len + (MAX_LEN_BINARY-1)) / MAX_LEN_BINARY;
|
||||
|
||||
/* First, see if this message and some number of its neighbors can be
|
||||
combined */
|
||||
|
@ -639,7 +739,7 @@ toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
|||
int sum = 0;
|
||||
if ( count == 1 && !forceOld ) {
|
||||
for ( ; last < rec->nMsgs; ++last ) {
|
||||
int nextLen = rec->msgs[last]->msg.len;
|
||||
int nextLen = rec->msgs[last]->msgNet.len;
|
||||
if ( sum + nextLen > MAX_LEN_BINARY ) {
|
||||
break;
|
||||
}
|
||||
|
@ -654,23 +754,23 @@ toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
|||
last - 1, nMsgs );
|
||||
}
|
||||
int len = 1 + sum + (nMsgs * 2); /* 1: len & msgID */
|
||||
SMSMsg newMsg = { .len = len,
|
||||
.data = XP_MALLOC( state->mpool, len )
|
||||
SMSMsgNet newMsg = { .len = len,
|
||||
.data = XP_MALLOC( state->mpool, len )
|
||||
};
|
||||
int indx = 0;
|
||||
newMsg.data[indx++] = SMS_PROTO_VERSION_COMBO;
|
||||
for ( int jj = ii; jj < last; ++jj ) {
|
||||
const SMSMsg* msg = &rec->msgs[jj]->msg;
|
||||
const SMSMsgNet* msg = &rec->msgs[jj]->msgNet;
|
||||
newMsg.data[indx++] = msg->len;
|
||||
newMsg.data[indx++] = nextMsgID( state );
|
||||
XP_MEMCPY( &newMsg.data[indx], msg->data, msg->len ); /* bad! */
|
||||
indx += msg->len;
|
||||
}
|
||||
result = appendMsg( state, result, &newMsg );
|
||||
result = appendNetMsg( state, result, &newMsg );
|
||||
ii = last;
|
||||
} else {
|
||||
int msgID = nextMsgID( state );
|
||||
const SMSMsg* msg = &rec->msgs[ii]->msg;
|
||||
const SMSMsgNet* msg = &rec->msgs[ii]->msgNet;
|
||||
XP_U8* nextStart = msg->data;
|
||||
XP_U16 lenLeft = msg->len;
|
||||
for ( XP_U16 indx = 0; indx < count; ++indx ) {
|
||||
|
@ -681,8 +781,8 @@ toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
|||
}
|
||||
lenLeft -= useLen;
|
||||
|
||||
SMSMsg newMsg = { .len = useLen + 4,
|
||||
.data = XP_MALLOC( state->mpool, useLen + 4 )
|
||||
SMSMsgNet newMsg = { .len = useLen + 4,
|
||||
.data = XP_MALLOC( state->mpool, useLen + 4 )
|
||||
};
|
||||
newMsg.data[0] = SMS_PROTO_VERSION;
|
||||
newMsg.data[1] = msgID;
|
||||
|
@ -691,7 +791,7 @@ toMsgs( SMSProto* state, ToPhoneRec* rec, XP_Bool forceOld )
|
|||
XP_MEMCPY( newMsg.data + 4, nextStart, useLen );
|
||||
nextStart += useLen;
|
||||
|
||||
result = appendMsg( state, result, &newMsg );
|
||||
result = appendNetMsg( state, result, &newMsg );
|
||||
}
|
||||
++ii;
|
||||
}
|
||||
|
@ -710,6 +810,14 @@ nextMsgID( SMSProto* state )
|
|||
return result;
|
||||
}
|
||||
|
||||
static XWStreamCtxt*
|
||||
mkStream( SMSProto* state )
|
||||
{
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(state->mpool)
|
||||
dutil_getVTManager(state->dutil) );
|
||||
return stream;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
checkThread( SMSProto* state )
|
||||
|
@ -745,17 +853,19 @@ smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
}
|
||||
|
||||
/* Loop until all the messages are ready. */
|
||||
const XP_U32 gameID = 12344321;
|
||||
const int port = 1;
|
||||
for ( XP_Bool firstTime = XP_TRUE; ; firstTime = XP_FALSE) {
|
||||
XP_Bool allDone = XP_TRUE;
|
||||
for ( int ii = 0; ii < VSIZE(arrs); ++ii ) {
|
||||
XP_U16 waitSecs;
|
||||
if ( firstTime ) {
|
||||
XP_U16 len = (ii + 1) * 30;
|
||||
arrs[ii] = smsproto_prepOutbound( state, (XP_U8*)buf, len, phones[ii],
|
||||
forceOld, &waitSecs );
|
||||
arrs[ii] = smsproto_prepOutbound( state, DATA, gameID, buf, len, phones[ii],
|
||||
port, forceOld, &waitSecs );
|
||||
} else if ( NULL == arrs[ii]) {
|
||||
arrs[ii] = smsproto_prepOutbound( state, NULL, 0, phones[ii],
|
||||
forceOld, &waitSecs );
|
||||
arrs[ii] = smsproto_prepOutbound( state, DATA, gameID, NULL, 0, phones[ii],
|
||||
port, forceOld, &waitSecs );
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
@ -772,13 +882,17 @@ smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
XP_Bool haveOne = XP_FALSE;
|
||||
for ( int ii = 0; ii < VSIZE(arrs); ++ii ) {
|
||||
if (!!arrs[ii] && indx < arrs[ii]->nMsgs) {
|
||||
XP_ASSERT( arrs[ii]->format == FORMAT_NET );
|
||||
haveOne = XP_TRUE;
|
||||
SMSMsgArray* outArr = smsproto_prepInbound( state, phones[ii],
|
||||
arrs[ii]->msgs[indx].data,
|
||||
arrs[ii]->msgs[indx].len );
|
||||
arrs[ii]->u.msgsNet[indx].data,
|
||||
arrs[ii]->u.msgsNet[indx].len );
|
||||
if ( !!outArr ) {
|
||||
SMSMsg* msg = &outArr->msgs[0];
|
||||
XP_LOGF( "%s(): got msgID %d", __func__, msg->msgID );
|
||||
XP_ASSERT( outArr->format == FORMAT_LOC );
|
||||
SMSMsgLoc* msg = &outArr->u.msgsLoc[0];
|
||||
XP_ASSERT( msg->gameID == gameID );
|
||||
XP_ASSERT( msg->cmd == DATA );
|
||||
// XP_LOGF( "%s(): got msgID %d", __func__, msg->msgID );
|
||||
XP_ASSERT( outArr->nMsgs == 1 );
|
||||
XP_ASSERT( 0 == memcmp(buf, msg->data, (ii + 1) * 30) );
|
||||
smsproto_freeMsgArray( state, outArr );
|
||||
|
@ -796,8 +910,8 @@ smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
/* Now let's send a bunch of small messages that should get combined */
|
||||
for ( int nUsed = 0; ; ++nUsed ) {
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* sendArr = smsproto_prepOutbound( state, (XP_U8*)&buf[nUsed],
|
||||
smallSiz, phones[0],
|
||||
SMSMsgArray* sendArr = smsproto_prepOutbound( state, DATA, gameID, &buf[nUsed],
|
||||
smallSiz, phones[0], port,
|
||||
XP_FALSE, &waitSecs );
|
||||
if ( sendArr == NULL ) {
|
||||
XP_LOGF( "%s(): msg[%d] of len %d sent; still not ready", __func__, nUsed, smallSiz );
|
||||
|
@ -805,17 +919,21 @@ smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
}
|
||||
|
||||
XP_ASSERT( waitSecs == 0 );
|
||||
XP_ASSERT( sendArr->format == FORMAT_NET );
|
||||
int totalBack = 0;
|
||||
for ( int jj = 0; jj < sendArr->nMsgs; ++jj ) {
|
||||
SMSMsgArray* recvArr = smsproto_prepInbound( state, phones[0],
|
||||
sendArr->msgs[jj].data,
|
||||
sendArr->msgs[jj].len );
|
||||
sendArr->u.msgsNet[jj].data,
|
||||
sendArr->u.msgsNet[jj].len );
|
||||
|
||||
if ( !!recvArr ) {
|
||||
XP_ASSERT( recvArr->format == FORMAT_LOC );
|
||||
XP_LOGF( "%s(): got %d msgs (from %d)", __func__, recvArr->nMsgs, nUsed + 1 );
|
||||
for ( int kk = 0; kk < recvArr->nMsgs; ++kk ) {
|
||||
SMSMsg* msg = &recvArr->msgs[kk];
|
||||
XP_LOGF( "%s(): got msgID %d", __func__, msg->msgID );
|
||||
SMSMsgLoc* msg = &recvArr->u.msgsLoc[kk];
|
||||
// XP_LOGF( "%s(): got msgID %d", __func__, msg->msgID );
|
||||
XP_ASSERT( msg->gameID == gameID );
|
||||
XP_ASSERT( msg->cmd == DATA );
|
||||
XP_ASSERT( msg->len == smallSiz );
|
||||
XP_ASSERT( 0 == memcmp( msg->data, &buf[totalBack], smallSiz ) );
|
||||
++totalBack;
|
||||
|
@ -833,25 +951,44 @@ smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
|||
/* Now let's add a too-long message and unpack only the first part. Make
|
||||
sure it's cleaned up correctly */
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( state, (XP_U8*)buf, 200, "33333", XP_TRUE, &waitSecs );
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( state, DATA, gameID, buf, 200, "33333",
|
||||
port, XP_TRUE, &waitSecs );
|
||||
XP_ASSERT( !!arr && arr->nMsgs > 1 );
|
||||
/* add only part 1 */
|
||||
SMSMsgArray* out = smsproto_prepInbound( state, "33333", arr->msgs[0].data, arr->msgs[0].len );
|
||||
SMSMsgArray* out = smsproto_prepInbound( state, "33333", arr->u.msgsNet[0].data,
|
||||
arr->u.msgsNet[0].len );
|
||||
XP_ASSERT( !out );
|
||||
smsproto_freeMsgArray( state, arr );
|
||||
|
||||
/* Try the no-buffer messages */
|
||||
XP_LOGF( "%s(): trying DEATH", __func__ );
|
||||
arr = smsproto_prepOutbound( state, DEATH, gameID, NULL, 0, "33333",
|
||||
port, XP_TRUE, &waitSecs );
|
||||
XP_ASSERT( arr->format == FORMAT_NET );
|
||||
out = smsproto_prepInbound( state, "33333",
|
||||
arr->u.msgsNet[0].data,
|
||||
arr->u.msgsNet[0].len );
|
||||
XP_ASSERT( out->format == FORMAT_LOC );
|
||||
XP_ASSERT( out->u.msgsLoc[0].cmd == DEATH );
|
||||
XP_ASSERT( out->u.msgsLoc[0].gameID == gameID );
|
||||
smsproto_freeMsgArray( state, arr );
|
||||
smsproto_freeMsgArray( state, out );
|
||||
XP_LOGF( "%s(): DEATH checked out", __func__ );
|
||||
|
||||
/* now a message that's unpacked across multiple sessions to test store/load */
|
||||
XP_LOGF( "%s(): testing store/restore", __func__ );
|
||||
arr = smsproto_prepOutbound( state, (XP_U8*)buf, 200, "33333", XP_TRUE, &waitSecs );
|
||||
arr = smsproto_prepOutbound( state, DATA, gameID, (XP_U8*)buf, 200, "33333",
|
||||
port, XP_TRUE, &waitSecs );
|
||||
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
SMSMsgArray* out = smsproto_prepInbound( state, "33333", arr->msgs[ii].data,
|
||||
arr->msgs[ii].len );
|
||||
SMSMsgArray* out = smsproto_prepInbound( state, "33333",
|
||||
arr->u.msgsNet[ii].data,
|
||||
arr->u.msgsNet[ii].len );
|
||||
if ( !!out ) {
|
||||
XP_ASSERT( out->nMsgs == 1);
|
||||
XP_ASSERT( out->format == FORMAT_LOC );
|
||||
XP_LOGF( "%s(): got the message on the %dth loop", __func__, ii );
|
||||
XP_ASSERT( out->msgs[0].len == 200 );
|
||||
XP_ASSERT( 0 == memcmp( out->msgs[0].data, buf, 200 ) );
|
||||
XP_ASSERT( out->u.msgsLoc[0].len == 200 );
|
||||
XP_ASSERT( 0 == memcmp( out->u.msgsLoc[0].data, buf, 200 ) );
|
||||
smsproto_freeMsgArray( state, out );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,23 +44,44 @@
|
|||
|
||||
#include "xptypes.h"
|
||||
#include "mempool.h" /* debug only */
|
||||
#include "nli.h"
|
||||
|
||||
typedef struct SMSProto SMSProto;
|
||||
|
||||
typedef struct _SMSMsg {
|
||||
typedef enum { NONE, INVITE, DATA, DEATH, ACK_INVITE, } SMS_CMD;
|
||||
|
||||
/* Unpacked/local format with relevant fields exposed */
|
||||
typedef struct _SMSMsgLoc {
|
||||
// XP_U16 msgID;
|
||||
SMS_CMD cmd;
|
||||
XP_U32 gameID;
|
||||
XP_U16 len;
|
||||
XP_U8* data; // will be NetLaunchInfo* if cmd == INVITE
|
||||
} SMSMsgLoc;
|
||||
|
||||
/* Flattened format suitable for transmission over wire. Encapsulates Loc
|
||||
format data */
|
||||
typedef struct _SMSMsgNet {
|
||||
// XP_U16 msgID;
|
||||
XP_U16 len;
|
||||
XP_U16 msgID;
|
||||
XP_U8* data;
|
||||
} SMSMsg;
|
||||
} SMSMsgNet;
|
||||
|
||||
typedef enum { FORMAT_NONE, FORMAT_LOC, FORMAT_NET } SMS_FORMAT;
|
||||
|
||||
typedef struct _SMSMsgArray {
|
||||
XP_U16 nMsgs;
|
||||
SMSMsg* msgs;
|
||||
SMS_FORMAT format;
|
||||
union {
|
||||
SMSMsgNet* msgsNet;
|
||||
SMSMsgLoc* msgsLoc;
|
||||
} u;
|
||||
} SMSMsgArray;
|
||||
|
||||
struct SMSProto* smsproto_init( MPFORMAL XW_DUtilCtxt* dutil );
|
||||
void smsproto_free( SMSProto* state );
|
||||
|
||||
|
||||
/* Return ptr to structure if one's ready to be sent, otherwise null. Caller *
|
||||
* should interpret null as meaning it's meant to call again. To support that,
|
||||
* null buf is legit.
|
||||
|
@ -68,8 +89,10 @@ void smsproto_free( SMSProto* state );
|
|||
* When send() returns a non-null value, that value must be passed to
|
||||
* freeMsgArray() or there will be leakage.
|
||||
*/
|
||||
SMSMsgArray* smsproto_prepOutbound( SMSProto* state, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* toPhone,
|
||||
|
||||
SMSMsgArray* smsproto_prepOutbound( SMSProto* state, SMS_CMD cmd,
|
||||
XP_U32 gameID, const void* buf, XP_U16 buflen,
|
||||
const XP_UCHAR* toPhone, int port,
|
||||
XP_Bool forceOld, XP_U16* waitSecs );
|
||||
|
||||
/* When a message is received, pass it in for reassambly. Non-null return
|
||||
|
|
|
@ -189,6 +189,26 @@ stream_gotU8( XWStreamCtxt* stream, XP_U8* ptr )
|
|||
return success;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
stream_gotU16( XWStreamCtxt* stream, XP_U16* ptr )
|
||||
{
|
||||
XP_Bool success = sizeof(*ptr) <= stream_getSize( stream );
|
||||
if ( success ) {
|
||||
*ptr = stream_getU16( stream );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
stream_gotU32( XWStreamCtxt* stream, XP_U32* ptr )
|
||||
{
|
||||
XP_Bool success = sizeof(*ptr) <= stream_getSize( stream );
|
||||
if ( success ) {
|
||||
*ptr = stream_getU32( stream );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
stream_gotBytes( XWStreamCtxt* stream, void* ptr, XP_U16 len )
|
||||
{
|
||||
|
|
|
@ -57,6 +57,8 @@ XP_U16 stringFromStreamHere( XWStreamCtxt* stream, XP_UCHAR* buf, XP_U16 len );
|
|||
void stringToStream( XWStreamCtxt* stream, const XP_UCHAR* str );
|
||||
|
||||
XP_Bool stream_gotU8( XWStreamCtxt* stream, XP_U8* ptr );
|
||||
XP_Bool stream_gotU32( XWStreamCtxt* stream, XP_U32* ptr );
|
||||
XP_Bool stream_gotU16( XWStreamCtxt* stream, XP_U16* ptr );
|
||||
XP_Bool stream_gotBytes( XWStreamCtxt* stream, void* ptr, XP_U16 len );
|
||||
|
||||
XP_UCHAR* p_copyString( MPFORMAL const XP_UCHAR* instr
|
||||
|
|
|
@ -1659,8 +1659,7 @@ send_invites( CommonGlobals* cGlobals, XP_U16 nPlayers,
|
|||
gchar gameName[64];
|
||||
snprintf( gameName, VSIZE(gameName), "Game %d", cGlobals->gi->gameID );
|
||||
|
||||
linux_sms_invite( cGlobals->params, cGlobals->gi, &addr, gameName,
|
||||
nPlayers, forceChannel,
|
||||
linux_sms_invite( cGlobals->params, &nli,
|
||||
addrs->u.sms.phone, addrs->u.sms.port );
|
||||
}
|
||||
if ( 0 != devID || !!relayID ) {
|
||||
|
|
|
@ -746,26 +746,29 @@ gtkNoticeRcvd( void* closure )
|
|||
}
|
||||
|
||||
static void
|
||||
smsInviteReceived( void* closure, const XP_UCHAR* XP_UNUSED_DBG(gameName),
|
||||
XP_U32 gameID, XP_U16 dictLang, const XP_UCHAR* dictName,
|
||||
XP_U16 nPlayers, XP_U16 nHere, XP_U16 forceChannel,
|
||||
/* smsInviteReceived( void* closure, const XP_UCHAR* XP_UNUSED_DBG(gameName), */
|
||||
/* XP_U32 gameID, XP_U16 dictLang, const XP_UCHAR* dictName, */
|
||||
/* XP_U16 nPlayers, XP_U16 nHere, XP_U16 forceChannel, */
|
||||
/* const CommsAddrRec* returnAddr ) */
|
||||
smsInviteReceived( void* closure, const NetLaunchInfo* nli,
|
||||
const CommsAddrRec* returnAddr )
|
||||
{
|
||||
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||
LaunchParams* params = apg->params;
|
||||
XP_LOGF( "%s(gameName=%s, gameID=%d, dictName=%s, nPlayers=%d, "
|
||||
"nHere=%d, forceChannel=%d)", __func__, gameName, gameID, dictName,
|
||||
nPlayers, nHere, forceChannel );
|
||||
"nHere=%d, forceChannel=%d)", __func__, nli->gameName,
|
||||
nli->gameID, nli->dict, nli->nPlayersT,
|
||||
nli->nPlayersH, nli->forceChannel );
|
||||
|
||||
CurGameInfo gi = {0};
|
||||
gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi );
|
||||
|
||||
gi_setNPlayers( &gi, nPlayers, nHere );
|
||||
gi.gameID = gameID;
|
||||
gi.dictLang = dictLang;
|
||||
gi.forceChannel = forceChannel;
|
||||
gi_setNPlayers( &gi, nli->nPlayersT, nli->nPlayersH );
|
||||
gi.gameID = nli->gameID;
|
||||
gi.dictLang = nli->lang;
|
||||
gi.forceChannel = nli->forceChannel;
|
||||
gi.serverRole = SERVER_ISCLIENT; /* recipient of invitation is client */
|
||||
replaceStringIfDifferent( params->mpool, &gi.dictName, dictName );
|
||||
replaceStringIfDifferent( params->mpool, &gi.dictName, nli->dict );
|
||||
|
||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||
params->needsNewGame = XP_FALSE;
|
||||
|
|
|
@ -68,12 +68,10 @@ typedef struct _LinSMSData {
|
|||
SMSProto* protoState;
|
||||
} LinSMSData;
|
||||
|
||||
static void doSend( LaunchParams* params, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_U32 gameID );
|
||||
static gboolean retrySend( gpointer data );
|
||||
static void sendOrRetry( LaunchParams* params, SMSMsgArray* arr, XP_U16 waitSecs,
|
||||
const XP_UCHAR* phone, XP_U16 port, XP_U32 gameID );
|
||||
static void sendOrRetry( LaunchParams* params, SMSMsgArray* arr, SMS_CMD cmd,
|
||||
XP_U16 waitSecs, const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_U32 gameID );
|
||||
static gint check_for_files( gpointer data );
|
||||
static gint check_for_files_once( gpointer data );
|
||||
|
||||
|
@ -85,13 +83,7 @@ formatQueuePath( const XP_UCHAR* phone, XP_U16 port, XP_UCHAR* path,
|
|||
snprintf( path, pathlen, "%s/%s_%d", SMS_DIR, phone, port );
|
||||
}
|
||||
|
||||
typedef enum { NONE, INVITE, DATA, DEATH, ACK, } SMS_CMD;
|
||||
#define SMS_PROTO_VERSION 0
|
||||
|
||||
|
||||
static LinSMSData* getStorage( LaunchParams* params );
|
||||
static void writeHeader( XWStreamCtxt* stream, SMS_CMD cmd );
|
||||
|
||||
|
||||
static void
|
||||
lock_queue( LinSMSData* storage )
|
||||
|
@ -114,7 +106,7 @@ unlock_queue( LinSMSData* storage )
|
|||
}
|
||||
|
||||
static XP_S16
|
||||
write_fake_sms( LaunchParams* params, XWStreamCtxt* stream,
|
||||
write_fake_sms( LaunchParams* params, const void* buf, XP_U16 buflen,
|
||||
const XP_UCHAR* phone, XP_U16 port )
|
||||
{
|
||||
XP_S16 nSent;
|
||||
|
@ -122,13 +114,11 @@ write_fake_sms( LaunchParams* params, XWStreamCtxt* stream,
|
|||
XP_Bool skipWrite = pct < params->smsSendFailPct;
|
||||
|
||||
if ( skipWrite ) {
|
||||
nSent = stream_getSize( stream );
|
||||
nSent = buflen;
|
||||
XP_LOGF( "%s(): dropping sms msg of len %d to phone %s", __func__,
|
||||
nSent, phone );
|
||||
} else {
|
||||
LinSMSData* storage = getStorage( params );
|
||||
const XP_U8* buf = stream_getPtr( stream );
|
||||
XP_U16 buflen = stream_getSize( stream );
|
||||
XP_LOGF( "%s(phone=%s, port=%d, len=%d)", __func__, phone,
|
||||
port, buflen );
|
||||
|
||||
|
@ -236,81 +226,38 @@ decodeAndDelete( LinSMSData* storage, const gchar* name,
|
|||
return nRead;
|
||||
} /* decodeAndDelete */
|
||||
|
||||
static void
|
||||
dispatch_invite( LinSMSData* storage, XP_U16 XP_UNUSED(proto),
|
||||
XWStreamCtxt* stream, CommsAddrRec* addr )
|
||||
{
|
||||
XP_UCHAR gameName[256];
|
||||
XP_UCHAR dictName[256];
|
||||
|
||||
XP_U32 gameID = stream_getU32( stream );
|
||||
XP_LOGF( "%s: got gameID %d", __func__, gameID );
|
||||
stringFromStreamHere( stream, gameName, VSIZE(gameName) );
|
||||
XP_U32 dictLang = stream_getU32( stream );
|
||||
stringFromStreamHere( stream, dictName, VSIZE(dictName) );
|
||||
XP_U8 nMissing = stream_getU8( stream );
|
||||
XP_U8 nPlayers = stream_getU8( stream );
|
||||
XP_U16 forceChannel = stream_getU8( stream );
|
||||
|
||||
addrFromStream( addr, stream );
|
||||
|
||||
(*storage->procs->inviteReceived)( storage->procClosure, gameName,
|
||||
gameID, dictLang, dictName, nPlayers,
|
||||
nMissing, forceChannel, addr );
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_data( LinSMSData* storage, XP_U16 XP_UNUSED(proto),
|
||||
XWStreamCtxt* stream, const CommsAddrRec* addr )
|
||||
{
|
||||
LOG_FUNC();
|
||||
|
||||
XP_U32 gameID = stream_getU32( stream );
|
||||
XP_U16 len = stream_getSize( stream );
|
||||
XP_U8 data[len];
|
||||
stream_getBytes( stream, data, len );
|
||||
|
||||
const XP_UCHAR* fromPhone = addr->u.sms.phone;
|
||||
SMSMsgArray* arr = smsproto_prepInbound( storage->protoState, fromPhone,
|
||||
data, len );
|
||||
if ( NULL != arr ) {
|
||||
for ( XP_U16 ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
SMSMsg* msg = &arr->msgs[ii];
|
||||
(*storage->procs->msgReceived)( storage->procClosure, addr, gameID,
|
||||
msg->data, msg->len );
|
||||
}
|
||||
smsproto_freeMsgArray( storage->protoState, arr );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parseAndDispatch( LaunchParams* params, uint8_t* buf, int len,
|
||||
CommsAddrRec* addr )
|
||||
{
|
||||
LinSMSData* storage = getStorage( params );
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(params->mpool)
|
||||
params->vtMgr );
|
||||
stream_setVersion( stream, CUR_STREAM_VERS );
|
||||
stream_putBytes( stream, buf, len );
|
||||
|
||||
XP_U8 proto = stream_getU8( stream );
|
||||
XP_ASSERT( SMS_PROTO_VERSION == proto );
|
||||
XP_U8 cmd = stream_getU8( stream );
|
||||
switch( cmd ) {
|
||||
case INVITE:
|
||||
dispatch_invite( storage, proto, stream, addr );
|
||||
break;
|
||||
case DATA:
|
||||
dispatch_data( storage, proto, stream, addr );
|
||||
break;
|
||||
case DEATH:
|
||||
case ACK:
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT( 0 );
|
||||
const XP_UCHAR* fromPhone = addr->u.sms.phone;
|
||||
SMSMsgArray* arr = smsproto_prepInbound( storage->protoState, fromPhone,
|
||||
buf, len );
|
||||
if ( NULL != arr ) {
|
||||
XP_ASSERT( arr->format == FORMAT_LOC );
|
||||
for ( XP_U16 ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
SMSMsgLoc* msg = &arr->u.msgsLoc[ii];
|
||||
switch ( msg->cmd ) {
|
||||
case DATA:
|
||||
(*storage->procs->msgReceived)( storage->procClosure, addr,
|
||||
msg->gameID,
|
||||
msg->data, msg->len );
|
||||
break;
|
||||
case INVITE:
|
||||
(*storage->procs->inviteReceived)( storage->procClosure,
|
||||
(NetLaunchInfo*)msg->data, addr );
|
||||
/* gameName, */
|
||||
/* gameID, dictLang, dictName, nPlayers, */
|
||||
/* nMissing, forceChannel, addr ); */
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT(0); /* implement me!! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
smsproto_freeMsgArray( storage->protoState, arr );
|
||||
}
|
||||
|
||||
stream_destroy( stream );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -341,28 +288,18 @@ linux_sms_init( LaunchParams* params, const gchar* myPhone, XP_U16 myPort,
|
|||
} /* linux_sms_init */
|
||||
|
||||
void
|
||||
linux_sms_invite( LaunchParams* params, const CurGameInfo* gi,
|
||||
const CommsAddrRec* addr, const gchar* gameName,
|
||||
XP_U16 nMissing, int forceChannel,
|
||||
linux_sms_invite( LaunchParams* params, const NetLaunchInfo* nli,
|
||||
const gchar* toPhone, int toPort )
|
||||
{
|
||||
LOG_FUNC();
|
||||
XWStreamCtxt* stream;
|
||||
stream = mem_stream_make_raw( MPPARM(params->mpool) params->vtMgr );
|
||||
writeHeader( stream, INVITE );
|
||||
stream_putU32( stream, gi->gameID );
|
||||
stringToStream( stream, gameName );
|
||||
stream_putU32( stream, gi->dictLang );
|
||||
stringToStream( stream, gi->dictName );
|
||||
stream_putU8( stream, nMissing );
|
||||
stream_putU8( stream, gi->nPlayers );
|
||||
stream_putU8( stream, forceChannel );
|
||||
LinSMSData* storage = getStorage( params );
|
||||
|
||||
addrToStream( stream, addr );
|
||||
|
||||
write_fake_sms( params, stream, toPhone, toPort );
|
||||
|
||||
stream_destroy( stream );
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* arr
|
||||
= smsproto_prepOutbound( storage->protoState, INVITE, nli->gameID, nli,
|
||||
sizeof(*nli), toPhone, toPort, XP_FALSE,
|
||||
&waitSecs );
|
||||
sendOrRetry( params, arr, INVITE, waitSecs, toPhone, toPort, nli->gameID );
|
||||
}
|
||||
|
||||
XP_S16
|
||||
|
@ -372,43 +309,32 @@ linux_sms_send( LaunchParams* params, const XP_U8* buf,
|
|||
{
|
||||
LinSMSData* storage = getStorage( params );
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( storage->protoState, buf, buflen,
|
||||
phone, XP_TRUE, &waitSecs );
|
||||
sendOrRetry( params, arr, waitSecs, phone, port, gameID );
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( storage->protoState, DATA, gameID,
|
||||
buf, buflen, phone, port,
|
||||
XP_TRUE, &waitSecs );
|
||||
sendOrRetry( params, arr, DATA, waitSecs, phone, port, gameID );
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static void
|
||||
doSend( LaunchParams* params, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_U32 gameID )
|
||||
{
|
||||
XP_LOGF( "%s(len=%d)", __func__, buflen );
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(params->mpool)
|
||||
params->vtMgr );
|
||||
writeHeader( stream, DATA );
|
||||
stream_putU32( stream, gameID );
|
||||
stream_putBytes( stream, buf, buflen );
|
||||
|
||||
(void)write_fake_sms( params, stream, phone, port );
|
||||
stream_destroy( stream );
|
||||
}
|
||||
|
||||
typedef struct _RetryClosure {
|
||||
LaunchParams* params;
|
||||
SMS_CMD cmd;
|
||||
XP_U16 port;
|
||||
XP_U32 gameID;
|
||||
XP_UCHAR phone[32];
|
||||
} RetryClosure;
|
||||
|
||||
static void
|
||||
sendOrRetry( LaunchParams* params, SMSMsgArray* arr, XP_U16 waitSecs,
|
||||
const XP_UCHAR* phone, XP_U16 port, XP_U32 gameID )
|
||||
sendOrRetry( LaunchParams* params, SMSMsgArray* arr, SMS_CMD cmd,
|
||||
XP_U16 waitSecs, const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_U32 gameID )
|
||||
{
|
||||
if ( !!arr ) {
|
||||
for ( XP_U16 ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||
SMSMsg* msg = &arr->msgs[ii];
|
||||
doSend( params, msg->data, msg->len, phone, port, gameID );
|
||||
const SMSMsgNet* msg = &arr->u.msgsNet[ii];
|
||||
// doSend( params, msg->data, msg->len, phone, port, gameID );
|
||||
(void)write_fake_sms( params, msg->data, msg->len,
|
||||
phone, port );
|
||||
}
|
||||
|
||||
LinSMSData* storage = getStorage( params );
|
||||
|
@ -420,6 +346,7 @@ sendOrRetry( LaunchParams* params, SMSMsgArray* arr, XP_U16 waitSecs,
|
|||
XP_STRCAT( closure->phone, phone );
|
||||
closure->port = port;
|
||||
closure->gameID = gameID;
|
||||
closure->cmd = cmd;
|
||||
g_timeout_add_seconds( 5, retrySend, closure );
|
||||
}
|
||||
}
|
||||
|
@ -430,9 +357,11 @@ retrySend( gpointer data )
|
|||
RetryClosure* closure = (RetryClosure*)data;
|
||||
LinSMSData* storage = getStorage( closure->params );
|
||||
XP_U16 waitSecs;
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( storage->protoState, NULL, 0,
|
||||
closure->phone, XP_TRUE, &waitSecs );
|
||||
sendOrRetry( closure->params, arr, waitSecs, closure->phone,
|
||||
SMSMsgArray* arr = smsproto_prepOutbound( storage->protoState, closure->cmd,
|
||||
closure->gameID, NULL, 0,
|
||||
closure->phone, closure->port,
|
||||
XP_TRUE, &waitSecs );
|
||||
sendOrRetry( closure->params, arr, closure->cmd, waitSecs, closure->phone,
|
||||
closure->port, closure->gameID );
|
||||
XP_FREEP( closure->params->mpool, &closure );
|
||||
return FALSE;
|
||||
|
@ -538,11 +467,4 @@ getStorage( LaunchParams* params )
|
|||
return storage;
|
||||
}
|
||||
|
||||
static void
|
||||
writeHeader( XWStreamCtxt* stream, SMS_CMD cmd )
|
||||
{
|
||||
stream_putU8( stream, SMS_PROTO_VERSION );
|
||||
stream_putU8( stream, cmd );
|
||||
}
|
||||
|
||||
#endif /* XWFEATURE_SMS */
|
||||
|
|
|
@ -23,12 +23,10 @@
|
|||
#ifdef XWFEATURE_SMS
|
||||
|
||||
#include "main.h"
|
||||
#include "nli.h"
|
||||
|
||||
typedef struct _SMSProcs {
|
||||
void (*inviteReceived)( void* closure, const XP_UCHAR* gameName,
|
||||
XP_U32 gameID, XP_U16 dictLang,
|
||||
const XP_UCHAR* dictName, XP_U16 nPlayers,
|
||||
XP_U16 nHere, XP_U16 forceChannel,
|
||||
void (*inviteReceived)( void* closure, const NetLaunchInfo* nli,
|
||||
const CommsAddrRec* returnAddr );
|
||||
void (*msgReceived)( void* closure, const CommsAddrRec* from, XP_U32 gameID,
|
||||
const XP_U8* buf, XP_U16 len );
|
||||
|
@ -45,9 +43,7 @@ void linux_sms_init( LaunchParams* params, const gchar* phone,
|
|||
XP_S16 linux_sms_send( LaunchParams* params, const XP_U8* buf,
|
||||
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port,
|
||||
XP_U32 gameID );
|
||||
void linux_sms_invite( LaunchParams* params, const CurGameInfo* info,
|
||||
const CommsAddrRec* addr, const gchar* gameName,
|
||||
XP_U16 nMissing, int forceChannel,
|
||||
void linux_sms_invite( LaunchParams* params, const NetLaunchInfo* nli,
|
||||
const gchar* phone, int port );
|
||||
void linux_sms_cleanup( LaunchParams* params );
|
||||
|
||||
|
|
Loading…
Reference in a new issue