Merge tag 'android_beta_100' into android_branch

ready for release
This commit is contained in:
Eric House 2016-01-03 11:36:37 -08:00
commit 22dde029c8
26 changed files with 319 additions and 197 deletions

View file

@ -22,7 +22,7 @@
to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eehouse.android.xw4dbg"
android:versionCode="93"
android:versionCode="94"
android:versionName="@string/app_version"
>

View file

@ -55,7 +55,7 @@
<!-- extension targets. Uncomment the ones where you want to do custom work
in between standard targets -->
<property name="INITIAL_CLIENT_VERS" value="4"/>
<property name="INITIAL_CLIENT_VERS" value="7"/>
<property name="VARIANT_NAME" value="xw4dbg"/>
<property name="APP_NAME" value="CrossDbg"/>

View file

@ -22,7 +22,7 @@
to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eehouse.android.xw4"
android:versionCode="93"
android:versionCode="94"
android:versionName="@string/app_version"
>

View file

@ -13,10 +13,10 @@
</style>
</head>
<body>
<h2>Crosswords 4.4 beta 99 release</h2>
<h2>Crosswords 4.4 beta 100 release</h2>
<p>This is a quick-fix release for Bluetooth on Android
Marshmallow.</p>
<p>This is the first of two releases that together fix stalling
issues in network games.</p>
<div id="survey">
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
@ -26,10 +26,9 @@
<h3>New with this release</h3>
<ul>
<li>Work around "security" change that broke Bluetooth
invitations and gameplay on the latest Android release
("Marshmallow").</li>
<li>Fix crash choosing menu at the wrong time</li>
<li>Fix to recognize (but not yet send) correct identifier for
game state. (Once this upgrade is out I'll do a new release that
also sends the correct identifier.)</li>
</ul>
<p>(The full changelog

View file

@ -55,7 +55,7 @@
<!-- extension targets. Uncomment the ones where you want to do custom work
in between standard targets -->
<property name="INITIAL_CLIENT_VERS" value="6"/>
<property name="INITIAL_CLIENT_VERS" value="7"/>
<property name="VARIANT_NAME" value="xw4"/>
<property name="APP_NAME" value="Crosswords"/>

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ..; ../scripts/ndkbuild.sh -j3"; -*- */
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright © 2009 - 2011 by Eric House (xwords@eehouse.org). All rights
* Copyright © 2009 - 2016 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -648,7 +648,7 @@ makeDict( MPFORMAL JNIEnv *env, DictMgrCtxt* dictMgr, JNIUtilCtxt* jniutil, jstr
anddict->super.langName = getStringCopy( MPPARM(mpool)
env, jlangname );
XP_U32 numEdges;
XP_U32 numEdges = 0;
XP_Bool parses = parseDict( anddict, (XP_U8*)anddict->bytes,
bytesSize, &numEdges );
if ( !parses || (check && !checkSanity( &anddict->super,

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_version">4.4 beta 99</string>
<string name="app_version">4.4 beta 100</string>
</resources>

View file

@ -1738,7 +1738,7 @@
<string name="about_vers_fmt">Crosswords for Android, Version %1$s,
rev %2$s, built on %3$s.</string>
<!-- copyright info -->
<string name="about_copyright">Copyright (C) 1998-2015 by Eric
<string name="about_copyright">Copyright (C) 1998-2016 by Eric
House. This free/open source software is released under the GNU Public
License.</string>

View file

@ -1495,7 +1495,7 @@
<string name="about_vers_fmt">Sdrowssorc rof ,diordna Noisrev %1$s,
ver %2$s, tliub no %3$s.</string>
<!-- copyright info -->
<string name="about_copyright">Thgirypoc )C( 5102-8991 yb Cire
<string name="about_copyright">Thgirypoc )C( 6102-8991 yb Cire
Esuoh. Siht nepo/eerf ecruos erawtfos si desaeler rednu eht UNG Cilbup
Esnecil.</string>
<!-- Another paragraph in the about dialog -->

View file

@ -1495,7 +1495,7 @@
<string name="about_vers_fmt">CROSSWORDS FOR ANDROID, VERSION %1$s,
REV %2$s, BUILT ON %3$s.</string>
<!-- copyright info -->
<string name="about_copyright">COPYRIGHT (C) 1998-2015 BY ERIC
<string name="about_copyright">COPYRIGHT (C) 1998-2016 BY ERIC
HOUSE. THIS FREE/OPEN SOURCE SOFTWARE IS RELEASED UNDER THE GNU PUBLIC
LICENSE.</string>
<!-- Another paragraph in the about dialog -->

View file

@ -48,7 +48,7 @@ public class NetStateCache {
private static boolean s_netAvail = false;
private static boolean s_isWifi;
private static PvtBroadcastReceiver s_receiver;
private static final boolean s_onSim = XWApp.onEmulator();
private static final boolean s_onSDKSim = Build.PRODUCT.contains("sdk"); // not genymotion
public static void register( Context context, StateChangedIf proc )
{
@ -69,11 +69,23 @@ public class NetStateCache {
public static boolean netAvail( Context context )
{
initIfNot( context );
boolean result = s_netAvail || s_onSim;
if ( BuildConfig.DEBUG ) {
checkSame( context, result );
// Cache is returning false negatives. Don't trust it.
if ( !s_netAvail ) {
boolean netAvail = getIsConnected( context );
if ( netAvail ) {
String msg = "netAvail(): second-guessing successful!!!";
DbgUtils.logf( msg );
Utils.showToast( context, msg );
s_netAvail = true;
if ( null != s_receiver ) {
s_receiver.notifyStateChanged( context );
}
}
}
DbgUtils.logf( "NetStateCache.netAvail() => %b", result );
boolean result = s_netAvail || s_onSDKSim;
DbgUtils.logf( "netAvail() => %b", result );
return result;
}
@ -94,6 +106,19 @@ public class NetStateCache {
}
}
private static boolean getIsConnected( Context context )
{
boolean result = false;
NetworkInfo ni = ((ConnectivityManager)
context.getSystemService( Context.CONNECTIVITY_SERVICE ))
.getActiveNetworkInfo();
if ( null != ni && ni.isConnectedOrConnecting() ) {
result = true;
}
DbgUtils.logf( "NetStateCache.getConnected() => %b", result );
return result;
}
private static void initIfNot( Context context )
{
synchronized( s_haveReceiver ) {
@ -150,7 +175,7 @@ public class NetStateCache {
}
@Override
public void onReceive( final Context context, Intent intent )
public void onReceive( Context context, Intent intent )
{
DbgUtils.assertOnUIThread();
@ -180,41 +205,7 @@ public class NetStateCache {
if ( s_netAvail != netAvail ) {
s_netAvail = netAvail; // keep current in case we're asked
// We want to wait for WAIT_STABLE_MILLIS of inactivity
// before informing listeners. So each time there's a
// change, kill any existing timer then set another, which
// will only fire if we go that long without coming
// through here again.
if ( null != mNotifyLater ) {
mHandler.removeCallbacks( mNotifyLater );
mNotifyLater = null;
}
if ( mLastStateSent != s_netAvail ) {
mNotifyLater = new Runnable() {
@Override
public void run() {
Assert.assertTrue( mLastStateSent != s_netAvail );
mLastStateSent = s_netAvail;
synchronized( s_ifs ) {
Iterator<StateChangedIf> iter = s_ifs.iterator();
while ( iter.hasNext() ) {
iter.next().netAvail( s_netAvail );
}
}
if ( s_netAvail ) {
CommsConnType typ = CommsConnType
.COMMS_CONN_RELAY;
GameUtils.resendAllIf( context, typ,
false );
}
}
};
mHandler.postDelayed( mNotifyLater, WAIT_STABLE_MILLIS );
}
notifyStateChanged( context );
} else {
DbgUtils.logdf( "NetStateCache.PvtBroadcastReceiver.onReceive:"
+ " no change; doing nothing; s_netAvail=%b",
@ -222,6 +213,46 @@ public class NetStateCache {
}
}
}
public void notifyStateChanged( final Context context )
{
// We want to wait for WAIT_STABLE_MILLIS of inactivity
// before informing listeners. So each time there's a
// change, kill any existing timer then set another, which
// will only fire if we go that long without coming
// through here again.
if ( null != mNotifyLater ) {
mHandler.removeCallbacks( mNotifyLater );
mNotifyLater = null;
}
if ( mLastStateSent != s_netAvail ) {
mNotifyLater = new Runnable() {
@Override
public void run() {
Assert.assertTrue( mLastStateSent != s_netAvail );
mLastStateSent = s_netAvail;
DbgUtils.logf( "NetStateCache.notifyStateChanged(%b)",
s_netAvail );
synchronized( s_ifs ) {
Iterator<StateChangedIf> iter = s_ifs.iterator();
while ( iter.hasNext() ) {
iter.next().netAvail( s_netAvail );
}
}
if ( s_netAvail ) {
CommsConnType typ = CommsConnType
.COMMS_CONN_RELAY;
GameUtils.resendAllIf( context, typ, false );
}
}
};
mHandler.postDelayed( mNotifyLater, WAIT_STABLE_MILLIS );
}
}
} // class PvtBroadcastReceiver
}

View file

@ -6,6 +6,9 @@ $(DEST_PATH)/%.java : $(SRC_PATH)/%.java
-e "s,\(import org.eehouse.android.\)xw4\(.*\);,\1$(VARIANT)\2;," \
< $< > $@
$(DEST_PATH)/icon48x48.png : $(SRC_PATH)/icon48x48.png
convert $< -fill red -gravity Center -annotate +0+5 ' Dbg ' $@
$(DEST_PATH)/%.png : $(SRC_PATH)/%.png
@cp $< $@

View file

@ -94,9 +94,9 @@ dbg_logstream( const XWStreamCtxt* stream, const char* func, int line )
if ( !!stream ) {
XP_U16 len = 0;
XWStreamPos end = stream_getPos( stream, POS_WRITE );
stream_copyBits( stream, 0, end, NULL, &len );
stream_copyBits( stream, end, NULL, &len );
XP_U8 buf[len];
stream_copyBits( stream, 0, end, buf, &len );
stream_copyBits( stream, end, buf, &len );
char comment[128];
XP_SNPRINTF( comment, VSIZE(comment), "%s line %d", func, line );
LOG_HEX( buf, len, comment );

View file

@ -25,6 +25,7 @@
#include "comtypes.h"
#include "memstream.h"
#include "vtabmgr.h"
#include "strutils.h"
#ifdef CPLUS
extern "C" {
@ -184,10 +185,10 @@ mem_stream_getBits( XWStreamCtxt* p_sctx, XP_U16 nBits )
return result;
} /* stream_getBits */
#if defined HASH_STREAM || defined DEBUG
#if defined DEBUG
static void
mem_stream_copyBits( const XWStreamCtxt* p_sctx, XWStreamPos XP_UNUSED(startPos),
XWStreamPos endPos, XP_U8* buf, XP_U16* lenp )
mem_stream_copyBits( const XWStreamCtxt* p_sctx, XWStreamPos endPos,
XP_U8* buf, XP_U16* lenp )
{
MemStreamCtxt* stream = (MemStreamCtxt*)p_sctx;
XP_U16 len = BYTE_PART(endPos);
@ -195,7 +196,7 @@ mem_stream_copyBits( const XWStreamCtxt* p_sctx, XWStreamPos XP_UNUSED(startPos)
XP_ASSERT( len <= stream->nBytesAllocated );
XP_MEMCPY( buf, stream->buf, len );
if ( 0 != BIT_PART(endPos) ) {
buf[len-1] &= 1 << BIT_PART(endPos);
buf[len-1] &= ~(0xFF << BIT_PART(endPos));
}
}
*lenp = len;
@ -371,6 +372,36 @@ mem_stream_getSize( const XWStreamCtxt* p_sctx )
return size;
} /* mem_stream_getSize */
static XP_U32
mem_stream_getHash( const XWStreamCtxt* p_sctx, XWStreamPos pos,
XP_Bool correct )
{
XP_U32 hash = 0;
const MemStreamCtxt* stream = (const MemStreamCtxt*)p_sctx;
const XP_U8* ptr = stream->buf;
XP_U16 len = BYTE_PART(pos);
XP_U16 bits = BIT_PART(pos);
if ( 0 != bits ) {
XP_ASSERT( 0 < len );
--len;
}
hash = augmentHash( 0, ptr, len );
if ( 0 != bits ) {
XP_U8 byt = ptr[len];
if ( correct ) {
byt &= ~(0xFF << bits);
} else {
byt &= 1 << bits;
}
hash = augmentHash( hash, &byt, 1 );
}
hash = finishHash( hash );
LOG_RETURNF( "%X(%d:%d)", hash, len, bits );
return hash;
} /* mem_stream_getHash */
static const XP_U8*
mem_stream_getPtr( const XWStreamCtxt* p_sctx )
{
@ -476,7 +507,7 @@ make_vtable( MemStreamCtxt* stream )
SET_VTABLE_ENTRY( vtable, stream_getU16, mem );
SET_VTABLE_ENTRY( vtable, stream_getU32, mem );
SET_VTABLE_ENTRY( vtable, stream_getBits, mem );
#if defined HASH_STREAM || defined DEBUG
#if defined DEBUG
SET_VTABLE_ENTRY( vtable, stream_copyBits, mem );
#endif
@ -497,6 +528,7 @@ make_vtable( MemStreamCtxt* stream )
SET_VTABLE_ENTRY( vtable, stream_close, mem );
SET_VTABLE_ENTRY( vtable, stream_getSize, mem );
SET_VTABLE_ENTRY( vtable, stream_getHash, mem );
SET_VTABLE_ENTRY( vtable, stream_getPtr, mem );
SET_VTABLE_ENTRY( vtable, stream_getAddress, mem );
SET_VTABLE_ENTRY( vtable, stream_setAddress, mem );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2000-2011 by Eric House (xwords@eehouse.org). All rights
* Copyright 2000-2015 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -312,36 +312,67 @@ model_destroy( ModelCtxt* model )
} /* model_destroy */
XP_U32
model_getHash( const ModelCtxt* model, XP_U16 version )
model_getHash( const ModelCtxt* model )
{
#ifndef STREAM_VERS_HASHSTREAM
XP_USE(version);
#endif
StackCtxt* stack = model->vol.stack;
XP_ASSERT( !!stack );
XP_U32 hash =
#ifdef STREAM_VERS_HASHSTREAM
STREAM_VERS_HASHSTREAM <= version ?
stack_getHash( stack ) :
#endif
stack_getHashOld( stack );
/* XP_LOGF( "%s(version=%x)=>%.8X", __func__, version, */
/* (unsigned int)hash ); */
return hash;
return stack_getHash( stack, XP_FALSE );
}
XP_Bool
model_hashMatches( const ModelCtxt* model, const XP_U32 hash )
{
StackCtxt* stack = model->vol.stack;
XP_Bool matches =
#ifdef STREAM_VERS_HASHSTREAM
(hash == stack_getHash( stack )) ||
#endif
(hash == stack_getHashOld( stack ));
XP_Bool matches = hash == stack_getHash( stack, XP_TRUE )
|| hash == stack_getHash( stack, XP_FALSE );
return matches;
}
XP_Bool
model_popToHash( ModelCtxt* model, const XP_U32 hash, PoolContext* pool )
{
XP_U16 nPopped = 0;
StackCtxt* stack = model->vol.stack;
const XP_U16 nEntries = stack_getNEntries( stack );
StackEntry entries[nEntries];
XP_S16 foundAt = -1;
for ( XP_U16 ii = 0; ii < nEntries; ++ii ) {
if ( hash == stack_getHash( stack, XP_TRUE )
|| hash == stack_getHash( stack, XP_FALSE ) ) {
foundAt = ii;
break;
}
if ( ! stack_popEntry( stack, &entries[ii] ) ) {
break;
}
++nPopped;
}
for ( XP_S16 ii = nPopped - 1; ii >= 0; --ii ) {
stack_redo( stack, &entries[ii] );
}
XP_Bool found = -1 != foundAt;
if ( found ) {
XP_LOGF( "%s: undoing %d turns to match hash %X", __func__,
foundAt, hash );
#ifdef DEBUG
XP_Bool success =
#endif
model_undoLatestMoves( model, pool, foundAt, NULL, NULL );
XP_ASSERT( success );
/* Assert not needed for long */
XP_ASSERT( hash == stack_getHash( model->vol.stack, XP_TRUE )
|| hash == stack_getHash( model->vol.stack, XP_FALSE ) );
}
return found;
}
#ifdef STREAM_VERS_BIGBOARD
void
model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses, XP_U16 nBonuses )

View file

@ -122,8 +122,11 @@ void model_writeToTextStream( const ModelCtxt* model, XWStreamCtxt* stream );
void model_setSize( ModelCtxt* model, XP_U16 boardSize );
void model_destroy( ModelCtxt* model );
XP_U32 model_getHash( const ModelCtxt* model, XP_U16 version );
XP_U32 model_getHash( const ModelCtxt* model );
XP_Bool model_hashMatches( const ModelCtxt* model, XP_U32 hash );
XP_Bool model_popToHash( ModelCtxt* model, const XP_U32 hash,
PoolContext* pool );
void model_setNPlayers( ModelCtxt* model, XP_U16 numPlayers );
XP_U16 model_getNPlayers( const ModelCtxt* model );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/* -*- compile-command: "cd ../linux && make -j5 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2001, 2006-2012 by Eric House (xwords@eehouse.org). All rights
* Copyright 2001-2015 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -67,88 +67,14 @@ stack_init( StackCtxt* stack )
shrunk to fit as soon as we serialize/deserialize anyway. */
} /* stack_init */
static XP_U32
augmentHash( XP_U32 hash, const XP_U8* ptr, XP_U16 len )
{
XP_ASSERT( 0 < len );
// see http://en.wikipedia.org/wiki/Jenkins_hash_function
XP_U16 ii;
for ( ii = 0; ii < len; ++ii ) {
hash += *ptr++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
// XP_LOGF( "%s: hashed %d bytes -> %X", __func__, len, (unsigned int)hash );
return hash;
}
static XP_U32
finishHash( XP_U32 hash )
{
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static XP_U32
augmentFor( XP_U32 hash, const StackEntry* entry )
{
switch( entry->moveType ) {
case ASSIGN_TYPE: {
TrayTileSet tiles;
sortTiles( &tiles, &entry->u.assign.tiles, 0 );
hash = augmentHash( hash, (XP_U8*)&tiles, sizeof(tiles) );
}
break;
case MOVE_TYPE:
hash = augmentHash( hash, (XP_U8*)&entry->u.move,
sizeof(entry->u.move) );
break;
case TRADE_TYPE:
hash = augmentHash( hash, (XP_U8*)&entry->u.trade,
sizeof(entry->u.trade) );
break;
case PHONY_TYPE:
hash = augmentHash( hash, (XP_U8*)&entry->u.phony,
sizeof(entry->u.phony) );
break;
}
return hash;
}
XP_U32
stack_getHashOld( StackCtxt* stack )
{
XP_U16 nn, nEntries = stack->nEntries;
XP_U32 hash = 0L;
for ( nn = 0; nn < nEntries; ++nn ) {
StackEntry entry;
XP_MEMSET( &entry, 0, sizeof(entry) );
if ( !stack_getNthEntry( stack, nn, &entry ) ) {
XP_ASSERT( 0 );
}
hash = augmentFor( hash, &entry );
// XP_LOGF( "hash after %d: %.8X", nn, (unsigned int)hash );
}
XP_ASSERT( 0 != hash );
hash = finishHash( hash );
LOG_RETURNF( "%.8X", (unsigned int)hash );
return hash;
} /* stack_getHashOld */
#ifdef STREAM_VERS_HASHSTREAM
XP_U32
stack_getHash( const StackCtxt* stack )
stack_getHash( const StackCtxt* stack, XP_Bool correct )
{
XP_U32 hash;
XP_U16 len = 0;
stream_copyBits( stack->data, 0, stack->top, NULL, &len );
XP_U8 buf[len];
stream_copyBits( stack->data, 0, stack->top, buf, &len );
// LOG_HEX( buf, len, __func__ );
hash = finishHash( augmentHash( 0L, buf, len ) );
// LOG_RETURNF( "%.8X", (unsigned int)hash );
XP_U32 hash = 0;
if ( !!stack->data ) {
hash = stream_getHash( stack->data, stack->top, correct );
}
return hash;
} /* stack_getHash */
#endif
@ -250,7 +176,7 @@ stack_copy( const StackCtxt* stack )
}
static void
pushEntry( StackCtxt* stack, const StackEntry* entry )
pushEntryImpl( StackCtxt* stack, const StackEntry* entry )
{
XP_U16 ii, bitsPerTile;
XWStreamPos oldLoc;
@ -308,9 +234,33 @@ pushEntry( StackCtxt* stack, const StackEntry* entry )
++stack->nEntries;
stack->highWaterMark = stack->nEntries;
stack->top = stream_setPos( stream, POS_WRITE, oldLoc );
// XP_LOGSTREAM( stack->data );
#ifdef DEBUG_HASHING
XP_LOGSTREAM( stack->data );
#endif
SET_DIRTY( stack );
} /* pushEntry */
} /* pushEntryImpl */
static void
pushEntry( StackCtxt* stack, const StackEntry* entry )
{
#ifdef DEBUG_HASHING
XP_Bool correct = XP_TRUE;
XP_U32 origHash = stack_getHash( stack, correct );
#endif
pushEntryImpl( stack, entry );
#ifdef DEBUG_HASHING
XP_U32 newHash = stack_getHash( stack, XP_TRUE );
StackEntry lastEntry;
if ( stack_popEntry( stack, &lastEntry ) ) {
XP_ASSERT( origHash == stack_getHash( stack, correct ) );
pushEntryImpl( stack, &lastEntry );
XP_ASSERT( newHash == stack_getHash( stack, correct ) );
XP_LOGF( "%s: all ok", __func__ );
}
#endif
}
static void
readEntry( const StackCtxt* stack, StackEntry* entry )
@ -482,7 +432,9 @@ stack_popEntry( StackCtxt* stack, StackEntry* entry )
setCacheReadyFor( stack, nn ); /* set cachedPos by side-effect */
stack->top = stack->cachedPos;
}
// XP_LOGSTREAM( stack->data );
#ifdef DEBUG_HASHING
XP_LOGSTREAM( stack->data );
#endif
return found;
} /* stack_popEntry */

View file

@ -69,8 +69,7 @@ StackCtxt* stack_make( MPFORMAL VTableMgr* vtmgr );
void stack_destroy( StackCtxt* stack );
void stack_init( StackCtxt* stack );
XP_U32 stack_getHashOld( StackCtxt* stack );
XP_U32 stack_getHash( const StackCtxt* stack );
XP_U32 stack_getHash( const StackCtxt* stack, XP_Bool correct );
void stack_setBitsPerTile( StackCtxt* stack, XP_U16 bitsPerTile );
void stack_loadFromStream( StackCtxt* stack, XWStreamCtxt* stream );

View file

@ -2032,8 +2032,10 @@ sendMoveTo( ServerCtxt* server, XP_U16 devIndex, XP_U16 turn,
XP_U16 version = stream_getVersion( stream );
if ( STREAM_VERS_BIGBOARD <= version ) {
XP_ASSERT( version == server->nv.streamVersion );
XP_U32 hash = model_getHash( server->vol.model, version );
// XP_LOGF( "%s: adding hash %x", __func__, (unsigned int)hash );
XP_U32 hash = model_getHash( server->vol.model );
#ifdef DEBUG_HASHING
XP_LOGF( "%s: adding hash %x", __func__, (unsigned int)hash );
#endif
stream_putU32( stream, hash );
}
#endif
@ -2084,10 +2086,16 @@ readMoveInfo( ServerCtxt* server, XWStreamCtxt* stream,
#ifdef STREAM_VERS_BIGBOARD
if ( STREAM_VERS_BIGBOARD <= stream_getVersion( stream ) ) {
XP_U32 hashReceived = stream_getU32( stream );
success = model_hashMatches( server->vol.model, hashReceived );
if ( !success ) {
XP_LOGF( "%s: hash mismatch",__func__);
success = model_hashMatches( server->vol.model, hashReceived )
|| model_popToHash( server->vol.model, hashReceived, server->pool );
// XP_ASSERT( success ); /* I need to understand when this can fail */
#ifdef DEBUG_HASHING
if ( success ) {
XP_LOGF( "%s: hash match: %X",__func__, hashReceived );
} else {
XP_LOGF( "%s: hash mismatch: %X not found",__func__, hashReceived );
}
#endif
}
#endif
if ( success ) {

View file

@ -228,6 +228,30 @@ p_replaceStringIfDifferent( MPFORMAL XP_UCHAR** curLoc, const XP_UCHAR* newStr
*curLoc = curStr;
} /* replaceStringIfDifferent */
XP_U32
augmentHash( XP_U32 hash, const XP_U8* ptr, XP_U16 len )
{
// see http://en.wikipedia.org/wiki/Jenkins_hash_function
for ( XP_U16 ii = 0; ii < len; ++ii ) {
hash += *ptr++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
#ifdef DEBUG_HASHING
XP_LOGF( "%s: hashed %d bytes -> %X", __func__, len, (unsigned int)hash );
#endif
return hash;
}
XP_U32
finishHash( XP_U32 hash )
{
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
/*
* A wrapper for printing etc. potentially null strings.
*/

View file

@ -68,6 +68,8 @@ XP_UCHAR* p_copyString( MPFORMAL const XP_UCHAR* instr
# define copyString( p, in ) p_copyString( in )
#endif
XP_U32 augmentHash( XP_U32 hash, const XP_U8* ptr, XP_U16 len );
XP_U32 finishHash( XP_U32 hash );
void p_replaceStringIfDifferent( MPFORMAL XP_UCHAR** curLoc,
const XP_UCHAR* newStr

View file

@ -1,6 +1,7 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 1997 - 2000 by Eric House (xwords@eehouse.org). All rights reserved.
* Copyright 1997 - 2015 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
@ -48,9 +49,9 @@ typedef struct StreamCtxVTable {
XP_U16 (*m_stream_getU16)( XWStreamCtxt* dctx );
XP_U32 (*m_stream_getU32)( XWStreamCtxt* dctx );
XP_U32 (*m_stream_getBits)( XWStreamCtxt* dctx, XP_U16 nBits );
#if defined HASH_STREAM || defined DEBUG
void (*m_stream_copyBits)( const XWStreamCtxt* dctx, XWStreamPos startPos,
XWStreamPos endPos, XP_U8* buf, XP_U16* len );
#if defined DEBUG
void (*m_stream_copyBits)( const XWStreamCtxt* dctx, XWStreamPos endPos,
XP_U8* buf, XP_U16* len );
#endif
void (*m_stream_putU8)( XWStreamCtxt* dctx, XP_U8 byt );
@ -73,6 +74,8 @@ typedef struct StreamCtxVTable {
void (*m_stream_close)( XWStreamCtxt* dctx );
XP_U16 (*m_stream_getSize)( const XWStreamCtxt* dctx );
XP_U32 (*m_stream_getHash)( const XWStreamCtxt* dctx, XWStreamPos pos,
XP_Bool correct );
const XP_U8* (*m_stream_getPtr)( const XWStreamCtxt* dctx );
@ -113,9 +116,9 @@ struct XWStreamCtxt {
#define stream_getBits(sc, n) \
(sc)->vtable->m_stream_getBits((sc), (n))
#if defined HASH_STREAM || defined DEBUG
#define stream_copyBits(sc, s, e, b, l) \
(sc)->vtable->m_stream_copyBits((sc), (s), (e), (b), (l))
#if defined DEBUG
#define stream_copyBits(sc, e, b, l) \
(sc)->vtable->m_stream_copyBits((sc), (e), (b), (l))
#endif
#define stream_putU8(sc, b) \
@ -154,6 +157,9 @@ struct XWStreamCtxt {
#define stream_getSize(sc) \
(sc)->vtable->m_stream_getSize((sc))
#define stream_getHash(sc, p, c) \
(sc)->vtable->m_stream_getHash((sc), (p), (c))
#define stream_getPtr(sc) \
(sc)->vtable->m_stream_getPtr((sc))

View file

@ -0,0 +1,32 @@
# -*-mode: Makefile -*-
# Copyright 2002 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.
XWLANG=ODS7
LANGCODE=fr_FR
TARGET_TYPE ?= WINCE
include ../Makefile.langcommon
$(XWLANG)Main.dict.gz: $(XWDICTPATH)/French/ods7.txt
cat $< | tr -d '\r' | tr a-z A-Z | grep '^[A-Z]*$$' | gzip >$@
# Everything but creating of the Main.dict file is inherited from the
# "parent" Makefile.langcommon in the parent directory.
clean: clean_common
rm -f $(XWLANG)Main.dict.gz *.bin $(XWLANG)*.pdb $(XWLANG)*.seb

View file

@ -22,6 +22,7 @@ ifeq ($(MEMDEBUG),TRUE)
DEFINES = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING -DNUMBER_KEY_AS_INDEX
DEFINES += -DCOMMS_CHECKSUM
CFLAGS += -g $(GPROFFLAG) -Wall -Wunused-parameter -Wcast-align -Werror -O0
# DEFINES += -DDEBUG_HASHING
CFLAGS += -DDEBUG_TS -rdynamic
PLATFORM = obj_linux_memdbg
else
@ -119,7 +120,7 @@ DEFINES += -DXWFEATURE_DEVID
DEFINES += -DXWFEATURE_COMMSACK
#DEFINES += -DXWFEATURE_ACTIVERECT
DEFINES += -DCOMMS_XPORT_FLAGSPROC
DEFINES += -DINITIAL_CLIENT_VERS=2
DEFINES += -DINITIAL_CLIENT_VERS=3
DEFINES += -DCOMMON_LAYOUT
DEFINES += -DNATIVE_NLI

View file

@ -554,7 +554,7 @@ secondTimerFired( gpointer data )
if ( !!game->server && !!game->board ) {
XP_U16 undoRatio = cGlobals->params->undoRatio;
if ( 0 != undoRatio ) {
if ( (XP_RANDOM() % 100) < undoRatio ) {
if ( (XP_RANDOM() % 1000) < undoRatio ) {
XP_LOGF( "%s: calling server_handleUndo", __func__ );
if ( server_handleUndo( game->server, 1 ) ) {
board_draw( game->board );
@ -2443,8 +2443,8 @@ main( int argc, char** argv )
#ifdef USE_GLIBLOOP
case CMD_UNDOPCT:
mainParams.undoRatio = atoi( optarg );
if ( mainParams.undoRatio < 0 || mainParams.undoRatio > 100 ) {
usage(argv[0], "must be 0 <= n <= 100" );
if ( mainParams.undoRatio < 0 || mainParams.undoRatio > 1000 ) {
usage(argv[0], "must be 0 <= n <= 1000" );
}
break;
#endif

View file

@ -6,7 +6,7 @@ APP_NEW=""
DO_CLEAN=""
APP_NEW_PARAMS=""
NGAMES=""
UDP_PCT_START=5
UDP_PCT_START=100
UDP_PCT_INCR=10
UPGRADE_ODDS=""
NROOMS=""
@ -68,7 +68,7 @@ function cleanup() {
function connName() {
LOG=$1
grep 'got_connect_cmd: connName' $LOG | \
grep -a 'got_connect_cmd: connName' $LOG | \
tail -n 1 | \
sed 's,^.*connName: \"\(.*\)\" (reconnect=.)$,\1,'
}
@ -356,7 +356,7 @@ maybe_resign() {
if [ "$RESIGN_RATIO" -gt 0 ]; then
KEY=$1
LOG=${LOGS[$KEY]}
if grep -q XWRELAY_ALLHERE $LOG; then
if grep -aq XWRELAY_ALLHERE $LOG; then
if [ 0 -eq $(($RANDOM % $RESIGN_RATIO)) ]; then
echo "making $LOG $(connName $LOG) resign..."
kill_from_log $LOG && close_device $KEY $DEADDIR "resignation forced" || /bin/true
@ -397,14 +397,13 @@ check_game() {
CONNNAME="$(connName $LOG)"
OTHERS=""
if [ -n "$CONNNAME" ]; then
if grep -q '\[unused tiles\]' $LOG; then
ALL_DONE=TRUE
if grep -aq '\[unused tiles\]' $LOG ; then
for INDX in ${!LOGS[*]}; do
[ $INDX -eq $KEY ] && continue
ALOG=${LOGS[$INDX]}
CONNNAME2="$(connName $ALOG)"
if [ "$CONNNAME2" = "$CONNNAME" ]; then
if ! grep -q '\[unused tiles\]' $ALOG; then
if ! grep -aq '\[unused tiles\]' $ALOG; then
OTHERS=""
break
fi
@ -424,11 +423,11 @@ check_game() {
done
echo ""
# XWRELAY_ERROR_DELETED may be old
elif grep -q 'relay_error_curses(XWRELAY_ERROR_DELETED)' $LOG; then
elif grep -aq 'relay_error_curses(XWRELAY_ERROR_DELETED)' $LOG; then
echo "deleting $LOG $(connName $LOG) b/c another resigned"
kill_from_log $LOG || /bin/true
close_device $KEY $DEADDIR "other resigned"
elif grep -q 'relay_error_curses(XWRELAY_ERROR_DEADGAME)' $LOG; then
elif grep -aq 'relay_error_curses(XWRELAY_ERROR_DEADGAME)' $LOG; then
echo "deleting $LOG $(connName $LOG) b/c another resigned"
kill_from_log $LOG || /bin/true
close_device $KEY $DEADDIR "other resigned"
@ -474,7 +473,7 @@ summarizeTileCounts() {
for KEY in ${KEYS[@]}; do
local LOG=${LOGS[$KEY]}
local LINE=$(grep pool_removeTiles $LOG | tail -n 1)
local LINE=$(grep -a pool_removeTiles $LOG | tail -n 1)
if [ -n "$LINE" ]; then
local NUM=$(echo $LINE | sed 's,^.*removeTiles: \(.*\) tiles.*$,\1,')
STR="${STR} ${KEY}:${NUM}"
@ -482,7 +481,7 @@ summarizeTileCounts() {
done
if [ -n "${STR}" ]; then
echo "$(date +%r) tiles left: $STR"
echo "** $(date +%r) tiles left: $STR"
fi
}
@ -613,7 +612,7 @@ function usage() {
echo " [--seed <int>] \\" >&2
echo " [--send-chat <interval-in-seconds> \\" >&2
echo " [--udp-incr <pct>] \\" >&2
echo " [--udp-start <pct>] \\" >&2
echo " [--udp-start <pct>] # default: $UDP_PCT_START \\" >&2
echo " [--undo-pct <int>] \\" >&2
exit 1