From 95a93191be08f8a0edc56e2662234df15b37e83c Mon Sep 17 00:00:00 2001 From: ehouse Date: Sat, 31 Jan 2009 18:06:09 +0000 Subject: [PATCH] Beginning of rewrite of socket code for communication with relay, replacing dedicated threads for read and write with non-blocking sockets driven from the main window proc. So far it can do a round-trip against the relay on win32, and compiles but isn't tested on wince. --- wince/cedebug.c | 3 +- wince/cemain.c | 69 ++++----- wince/cemain.h | 9 +- wince/cesockwr.c | 394 +++++++++++++++++++++++++++++++++++++---------- wince/cesockwr.h | 9 +- 5 files changed, 359 insertions(+), 125 deletions(-) diff --git a/wince/cedebug.c b/wince/cedebug.c index e455fda4c..b142f6600 100644 --- a/wince/cedebug.c +++ b/wince/cedebug.c @@ -52,7 +52,8 @@ messageToStr( UINT message ) CASE_STR( WM_TIMER ); CASE_STR( WM_DESTROY ); CASE_STR( XWWM_TIME_RQST ); - CASE_STR( XWWM_PACKET_ARRIVED ); + CASE_STR( XWWM_HOSTNAME_ARRIVED ); + CASE_STR( XWWM_SOCKET_EVT ); CASE_STR( WM_DRAWITEM ); CASE_STR( WM_NEXTDLGCTL ); CASE_STR( WM_CTLCOLORSTATIC ); diff --git a/wince/cemain.c b/wince/cemain.c index 0344b8f0c..e2dba6bc1 100755 --- a/wince/cemain.c +++ b/wince/cemain.c @@ -54,6 +54,7 @@ #include "cesvdgms.h" #include "cedraw.h" #include "cesms.h" +#include "cesockwr.h" #include "dbgutil.h" @@ -862,15 +863,19 @@ ceInitAndStartBoard( CEAppGlobals* globals, XP_Bool newGame, board_invalAll( globals->game.board ); InvalidateRect( globals->hWnd, NULL, TRUE /* erase */ ); -#ifdef XWFEATURE_RELAY - if ( newGame && globals->gameInfo.serverRole == SERVER_ISCLIENT ) { - XWStreamCtxt* stream; - XP_ASSERT( !!globals->game.comms ); - stream = make_generic_stream( globals ); - stream_setOnCloseProc( stream, ce_send_on_close ); - server_initClientConnection( globals->game.server, stream ); +/* #ifdef XWFEATURE_RELAY */ +/* if ( newGame && globals->gameInfo.serverRole == SERVER_ISCLIENT ) { */ +/* XWStreamCtxt* stream; */ +/* XP_ASSERT( !!globals->game.comms ); */ +/* stream = make_generic_stream( globals ); */ +/* stream_setOnCloseProc( stream, ce_send_on_close ); */ +/* server_initClientConnection( globals->game.server, stream ); */ +/* } */ +/* #endif */ + + if ( !!globals->game.comms ) { + comms_start( globals->game.comms ); } -#endif ceSetLeftSoftkey( globals, ID_MOVE_TURNDONE ); @@ -1861,6 +1866,9 @@ ceSaveAndExit( CEAppGlobals* globals ) { (void)ceSaveCurGame( globals, XP_TRUE ); ceSavePrefs( globals ); + if ( !!globals->socketWrap ) { + ce_sockwrap_delete( globals->socketWrap ); + } DestroyWindow(globals->hWnd); } /* ceSaveAndExit */ @@ -2025,25 +2033,6 @@ checkFireLateKeyTimer( CEAppGlobals* globals ) return drop; } /* checkFireLateKeyTimer */ -#ifndef XWFEATURE_STANDALONE_ONLY -static XP_Bool -processPacket( CEAppGlobals* globals, XWStreamCtxt* instream ) -{ - XP_Bool draw = XP_FALSE; - - XP_ASSERT( globals->game.comms != NULL ); - - if ( comms_checkIncomingStream( globals->game.comms, - instream, NULL ) ) { - draw = server_receiveMessage( globals->game.server, instream ); - } - stream_destroy( instream ); - ce_util_requestTime( &globals->util ); - - return draw; -} /* processPacket */ -#endif - static XP_Bool checkPenDown( CEAppGlobals* globals ) { @@ -2551,8 +2540,12 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; #ifndef XWFEATURE_STANDALONE_ONLY - case XWWM_PACKET_ARRIVED: - draw = processPacket( globals, (XWStreamCtxt*)lParam ); + case XWWM_HOSTNAME_ARRIVED: + ce_sockwrap_hostname( globals->socketWrap, wParam, lParam ); + break; + + case XWWM_SOCKET_EVT: + draw = ce_sockwrap_event( globals->socketWrap, wParam, lParam ); break; #endif @@ -2824,22 +2817,24 @@ wince_snprintf( XP_UCHAR* buf, XP_U16 len, const XP_UCHAR* format, ... ) } /* wince_snprintf */ #if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH -static void +static XP_Bool got_data_proc( XP_U8* data, XP_U16 len, void* closure ) { - /* Remember that this gets called by the reader thread, not by the one - running the window loop. */ CEAppGlobals* globals = (CEAppGlobals*)closure; - BOOL posted; XWStreamCtxt* stream; + XP_Bool draw; stream = make_generic_stream( globals ); stream_putBytes( stream, data, len ); - assertOnTop( globals->hWnd ); - posted = PostMessage( globals->hWnd, XWWM_PACKET_ARRIVED, - 0, (DWORD)stream ); - XP_ASSERT( posted ); + XP_ASSERT( !!globals->game.comms ); + if ( comms_checkIncomingStream( globals->game.comms, stream, NULL ) ) { + draw = server_receiveMessage( globals->game.server, stream ); + } + stream_destroy( stream ); + ce_util_requestTime( &globals->util ); + + return draw; } /* got_data_proc */ #endif diff --git a/wince/cemain.h b/wince/cemain.h index e523369de..39eac22bc 100755 --- a/wince/cemain.h +++ b/wince/cemain.h @@ -27,7 +27,6 @@ #include "game.h" #include "util.h" #include "mempool.h" -#include "cesockwr.h" #define LCROSSWORDS_DIR_NODBG L"Crosswords" #define CE_GAMEFILE_VERSION1 0x01 /* means draw gets to save/restore */ @@ -110,7 +109,7 @@ enum { N_CACHED_PATHS }; -typedef struct CEAppGlobals { +typedef struct _CEAppGlobals { HINSTANCE hInst; HDC hdc; /* to pass drawing ctxt to draw code */ HWND hWnd; @@ -158,7 +157,7 @@ typedef struct CEAppGlobals { #ifdef KEYBOARD_NAV XP_Bool keyDown; #endif - CeSocketWrapper* socketWrap; + struct CeSocketWrapper* socketWrap; CEAppPrefs appPrefs; @@ -188,8 +187,8 @@ typedef struct CEAppGlobals { enum { XWWM_TIME_RQST = WM_APP ,XWWM_REM_SEL - ,XWWM_PACKET_ARRIVED - + ,XWWM_HOSTNAME_ARRIVED + ,XWWM_SOCKET_EVT }; #define CE_NUM_EDITABLE_COLORS CE_BLACK_COLOR diff --git a/wince/cesockwr.c b/wince/cesockwr.c index 605b906dd..1bd46cc47 100755 --- a/wince/cesockwr.c +++ b/wince/cesockwr.c @@ -1,4 +1,4 @@ -/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */ +/* -*- compile-command: "make -j TARGET_OS=win32 DEBUG=TRUE" -*- */ /* * Copyright 2005-2009 by Eric House (xwords@eehouse.org). All rights * reserved. @@ -19,12 +19,14 @@ */ #ifndef XWFEATURE_STANDALONE_ONLY +#include +#include + #include "cesockwr.h" #include "cemain.h" #include "cedebug.h" #include "debhacks.h" -#include /* This object owns all network activity: sending and receiving packets. It maintains two threads, one to send and the other to listen. Incoming @@ -39,31 +41,41 @@ enum { WRITER_THREAD, N_THREADS }; typedef enum { - CE_IP_NONE, /* shouldn't be used */ - CE_IP_UNCONNECTED, - CE_IP_CONNECTED -} CE_CONNSTATE; + CE_IPST_START + ,CE_IPST_RESOLVINGHOST + ,CE_IPST_HOSTRESOLVED + ,CE_IPST_CONNECTING + ,CE_IPST_CONNECTED +} CeConnState; #define MAX_QUEUE_SIZE 3 - struct CeSocketWrapper { +struct CeSocketWrapper { + WSADATA wsaData; DataRecvProc dataProc; - void* dataClosure; + CEAppGlobals* globals; + union { + HOSTENT hent; + XP_U8 hostNameBuf[MAXGETHOSTSTRUCT]; + } hostNameUnion; + HANDLE getHostTask; + + /* Outgoing queue */ XP_U8* packets[MAX_QUEUE_SIZE]; XP_U16 lens[MAX_QUEUE_SIZE]; XP_U16 nPackets; + /* Incoming */ + char in_buf[512]; /* char is what WSARecv wants */ + XP_U16 in_offset; + CommsAddrRec addrRec; SOCKET socket; - CE_CONNSTATE connState; - - HANDLE queueAddEvent; - HANDLE socketConnEvent; + CeConnState connState; HANDLE queueMutex; - HANDLE threads[N_THREADS]; #ifdef DEBUG XP_U16 nSent; @@ -72,6 +84,28 @@ typedef enum { MPSLOT }; +#ifdef DEBUG +static const char* +ConnState2Str( CeConnState connState ) +{ +#define CASESTR(s) case (s): return #s + switch( connState ) { + CASESTR( CE_IPST_START ); + CASESTR( CE_IPST_RESOLVINGHOST ); + CASESTR( CE_IPST_HOSTRESOLVED ); + CASESTR( CE_IPST_CONNECTING ); + CASESTR( CE_IPST_CONNECTED ); + } +#undef CASESTR + return ""; +} +#else +# define ConnState2Str(s) +#endif + +static XP_Bool connectIfNot( CeSocketWrapper* self ); + + /* queue_packet: Place packet on queue using semaphore. Return false * if no room or fail for some other reason. */ @@ -96,8 +130,9 @@ queue_packet( CeSocketWrapper* self, XP_U8* packet, XP_U16 len ) __func__, self->nPackets ); /* signal the writer thread */ - SetEvent( self->queueAddEvent ); - success = XP_TRUE; +/* XP_LOGF( "%s: calling SetEvent(%p)", __func__, self->queueAddEvent ); */ +/* SetEvent( self->queueAddEvent ); */ +/* success = XP_TRUE; */ } if ( !ReleaseMutex( self->queueMutex ) ) { @@ -184,62 +219,99 @@ sendLenAndData( CeSocketWrapper* self, XP_U8* packet, XP_U16 len ) return success; } /* sendLenAndData */ +static void +send_packet_if( CeSocketWrapper* self ) +{ + XP_U8* packet; + XP_U16 len; + if ( get_packet( self, &packet, &len ) ) { + if ( sendLenAndData( self, packet, len ) ) { + /* successful send. Remove our copy */ + remove_packet( self ); + XP_FREE( self->mpool, packet ); + } + } +} + +static void +stateChanged( CeSocketWrapper* self, CeConnState newState ) +{ + CeConnState curState = self->connState; + self->connState = newState; + + XP_LOGF( "%s: %s -> %s", __func__, ConnState2Str( curState ), + ConnState2Str( newState ) ); + + switch( newState ) { + case CE_IPST_START: + break; + case CE_IPST_RESOLVINGHOST: + break; + case CE_IPST_HOSTRESOLVED: + connectIfNot( self ); + break; + case CE_IPST_CONNECTING: + break; + case CE_IPST_CONNECTED: + send_packet_if( self ); + break; + } + +} + static XP_Bool connectSocket( CeSocketWrapper* self ) { SOCKET sock; - /* first look up the ip address */ - if ( self->addrRec.u.ip_relay.ipAddr == 0 ) { - struct hostent* ent; - ent = MS(gethostbyname)( self->addrRec.u.ip_relay.hostName ); - if ( ent != NULL ) { - XP_U32 tmp; - XP_MEMCPY( &tmp, &ent->h_addr_list[0][0], - sizeof(self->addrRec.u.ip_relay.ipAddr) ); - self->addrRec.u.ip_relay.ipAddr = XP_NTOHL( tmp ); - } else { - logLastError( "gethostbyname" ); - } - } - if ( self->addrRec.u.ip_relay.ipAddr != 0 ) { - sock = MS(socket)( AF_INET, SOCK_STREAM, IPPROTO_IP ); + sock = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_IP, + NULL, 0, WSA_FLAG_OVERLAPPED ); XP_LOGF( "got socket %d", sock ); if ( sock != INVALID_SOCKET ) { - struct sockaddr_in name; + struct sockaddr_in name = {0}; + + /* Put socket in non-blocking mode */ + if ( 0 != WSAAsyncSelect( sock, self->globals->hWnd, + XWWM_SOCKET_EVT, + FD_READ | FD_WRITE | FD_CONNECT ) ) { + XP_WARNF( "WSAAsyncSelect failed" ); + } name.sin_family = AF_INET; name.sin_port = XP_HTONS( self->addrRec.u.ip_relay.port ); name.sin_addr.S_un.S_addr = XP_HTONL(self->addrRec.u.ip_relay.ipAddr); - if ( SOCKET_ERROR != MS(connect)( sock, (struct sockaddr *)&name, - sizeof(name) ) ) { - self->connState = CE_IP_CONNECTED; + XP_LOGF( "%s: calling WSAConnect", __func__ ); + if ( SOCKET_ERROR != WSAConnect( sock, (struct sockaddr *)&name, + sizeof(name), NULL, NULL, + NULL, NULL ) ) { self->socket = sock; - - /* Let the reader thread know there's now a socket to listen - on */ - SetEvent( self->socketConnEvent ); - + stateChanged( self, CE_IPST_CONNECTED ); + } else if ( WSAEWOULDBLOCK == WSAGetLastError() ) { + stateChanged( self, CE_IPST_CONNECTING ); } else { - logLastError( "connect" ); + int err = WSAGetLastError(); + XP_LOGF( "%s:%d: WSAGetLastError=>%d", __func__, __LINE__, err ); } } else { - logLastError( "socket" ); + int err = WSAGetLastError(); + XP_LOGF( "%s:%d: WSAGetLastError=>%d", __func__, __LINE__, err ); } } - return self->connState == CE_IP_CONNECTED; + XP_LOGF( "%d", self->connState == CE_IPST_CONNECTED ); + return self->connState == CE_IPST_CONNECTED; } /* connectSocket */ static XP_Bool connectIfNot( CeSocketWrapper* self ) { - XP_Bool success = self->connState == CE_IP_CONNECTED; + LOG_FUNC(); + XP_Bool success = self->connState == CE_IPST_CONNECTED; - if ( !success ) { + if ( !success && CE_IPST_HOSTRESOLVED == self->connState ) { success = connectSocket( self ); } return success; @@ -248,17 +320,18 @@ connectIfNot( CeSocketWrapper* self ) static void closeConnection( CeSocketWrapper* self ) { - if ( self->connState >= CE_IP_UNCONNECTED ) { + if ( self->connState >= CE_IPST_CONNECTED ) { if ( self->socket != -1 ) { MS(closesocket)( self->socket ); } self->socket = -1; - self->connState = CE_IP_UNCONNECTED; + stateChanged( self, CE_IPST_START ); } } /* closeConnection */ +#if 0 static DWORD WriterThreadProc( LPVOID lpParameter ) { @@ -290,7 +363,9 @@ WriterThreadProc( LPVOID lpParameter ) ExitThread(0); /* docs say to exit this way */ return 0; } /* WriterThreadProc */ +#endif +#if 0 /* Read until we get the number of bytes sought or until an error's received. */ static XP_Bool @@ -331,7 +406,9 @@ read_bytes_blocking( CeSocketWrapper* self, XP_U8* buf, XP_U16 len ) XP_ASSERT( len == 0 ); return len == 0; } /* read_bytes_blocking */ +#endif +#if 0 static DWORD ReaderThreadProc( LPVOID lpParameter ) { @@ -355,42 +432,62 @@ ReaderThreadProc( LPVOID lpParameter ) break; /* bad socket */ } - (*self->dataProc)( buf, len, self->dataClosure ); + (*self->dataProc)( buf, len, self->globals ); } } ExitThread(0); /* docs say to exit this way */ return 0; } /* ReaderThreadProc */ +#endif +static void +getHostAddr( CeSocketWrapper* self ) +{ + if ( self->addrRec.u.ip_relay.hostName[0] ) { + XP_LOGF( "%s: calling WSAAsyncGetHostByName(%s)", + __func__, self->addrRec.u.ip_relay.hostName ); + self->getHostTask + = WSAAsyncGetHostByName( self->globals->hWnd, + XWWM_HOSTNAME_ARRIVED, + self->addrRec.u.ip_relay.hostName, + (char*)&self->hostNameUnion, + sizeof(self->hostNameUnion) ); + if ( NULL == self->getHostTask ) { + int err = WSAGetLastError(); + XP_LOGF( "%s: WSAGetLastError=>%d", __func__, err ); + } + + stateChanged( self, CE_IPST_RESOLVINGHOST ); + } +} CeSocketWrapper* -ce_sockwrap_new( MPFORMAL DataRecvProc proc, void* closure ) +ce_sockwrap_new( MPFORMAL DataRecvProc proc, CEAppGlobals* globals ) { - CeSocketWrapper* self = XP_MALLOC( mpool, sizeof(*self) ); - XP_MEMSET( self, 0, sizeof(*self) ); + CeSocketWrapper* self = NULL; - self->dataProc = proc; - self->dataClosure = closure; - MPASSIGN(self->mpool, mpool ); - self->socket = -1; + WSADATA wsaData; + int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); + if (iResult != NO_ERROR) { + XP_WARNF("Error at WSAStartup()\n"); + } else { - self->queueMutex = CreateMutex( NULL, FALSE, NULL ); - XP_ASSERT( self->queueMutex != NULL ); + self = XP_MALLOC( mpool, sizeof(*self) ); + XP_MEMSET( self, 0, sizeof(*self) ); - self->queueAddEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - self->socketConnEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - - /* I have no idea why these casts are necessary to prevent warnings. All - sigs look right to me. */ - self->threads[WRITER_THREAD] = - CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE)WriterThreadProc, - self, 0, NULL ); - self->threads[READER_THREAD] = - CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE)ReaderThreadProc, - self, 0, NULL ); + self->wsaData = wsaData; + + self->dataProc = proc; + self->globals = globals; + MPASSIGN(self->mpool, mpool ); + self->socket = -1; + + self->queueMutex = CreateMutex( NULL, FALSE, NULL ); + XP_ASSERT( self->queueMutex != NULL ); + + getHostAddr( self ); + } return self; } /* ce_sockwrap_new */ @@ -399,23 +496,156 @@ ce_sockwrap_delete( CeSocketWrapper* self ) { /* This isn't a good thing to do. Better to signal them to exit some other way */ - TerminateThread( self->threads[WRITER_THREAD], 0 ); - TerminateThread( self->threads[READER_THREAD], 0 ); - - WaitForMultipleObjects( N_THREADS, self->threads, TRUE, INFINITE ); - closeConnection( self ); - CloseHandle( self->threads[WRITER_THREAD] ); - CloseHandle( self->threads[READER_THREAD] ); CloseHandle( self->queueMutex ); - CloseHandle( self->queueAddEvent ); - CloseHandle( self->socketConnEvent ); + WSACleanup(); XP_FREE( self->mpool, self ); } /* ce_sockwrap_delete */ +void +ce_sockwrap_hostname( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam ) +{ + LOG_FUNC(); + DWORD err = WSAGETASYNCERROR( lParam ); + + XP_ASSERT( CE_IPST_RESOLVINGHOST == self->connState ); + + if ( 0 == err ) { + HANDLE comp = (HANDLE)wParam; + XP_ASSERT( comp == self->getHostTask ); + + XP_U32 tmp; + XP_MEMCPY( &tmp, &self->hostNameUnion.hent.h_addr_list[0][0], + sizeof(tmp) ); + self->addrRec.u.ip_relay.ipAddr = XP_NTOHL( tmp ); + + XP_LOGF( "got address: %d.%d.%d.%d", + (int)((tmp>>0) & 0xFF), + (int)((tmp>>8) & 0xFF), + (int)((tmp>>16) & 0xFF), + (int)((tmp>>24) & 0xFF) ); + + stateChanged( self, CE_IPST_HOSTRESOLVED ); + } else { + XP_LOGF( "%s: async operation failed: %ld", __func__, err ); +/* WSAENETDOWN */ +/* WSAENOBUFS */ +/* WSAEFAULT */ +/* WSAHOST_NOT_FOUND */ +/* WSATRY_AGAIN */ +/* WSANO_RECOVERY */ +/* WSANO_DATA */ + } + + LOG_RETURN_VOID(); +} /* ce_sockwrap_hostname */ + +/* MSDN: When one of the nominated network events occurs on the specified + socket s, the application window hWnd receives message wMsg. The wParam + parameter identifies the socket on which a network event has occurred. The + low word of lParam specifies the network event that has occurred. The high + word of lParam contains any error code. The error code be any error as + defined in Winsock2.h. + */ + +static XP_Bool +dispatch_if_complete( CeSocketWrapper* self, XP_U16 nBytesRecvd ) +{ + XP_U16 lenInBuffer = nBytesRecvd + self->in_offset; + XP_U16 msgLen; + XP_Bool draw = XP_FALSE; + if ( lenInBuffer >= sizeof(msgLen) ) { + XP_MEMCPY( &msgLen, self->in_buf, sizeof(msgLen) ); + msgLen = XP_NTOHS( msgLen ); + + XP_LOGF( "%s: at least we have len: %d", __func__, msgLen ); + + /* We know the length of the full buffer. Do we have it? */ + if ( lenInBuffer >= (msgLen + sizeof(msgLen)) ) { + XP_U16 lenLeft, lenUsed; + + /* first send */ + XP_LOGF( "%s: sending %d bytes to dataProc", __func__, msgLen ); + draw = (*self->dataProc)( (XP_U8*)&self->in_buf[sizeof(msgLen)], + msgLen, self->globals ); + + /* then move down any additional bytes */ + lenUsed = msgLen + sizeof(msgLen); + XP_ASSERT( lenInBuffer >= lenUsed ); + lenLeft = lenInBuffer - lenUsed; + if ( lenLeft > 0 ) { + XP_MEMCPY( self->in_buf, &self->in_buf[lenUsed], lenLeft ); + } + + self->in_offset = 0; + nBytesRecvd = lenLeft; /* will set below */ + } + } + + self->in_offset += nBytesRecvd; + return draw; +} /* dispatch_if_complete */ + +static XP_U16 +read_from_socket( CeSocketWrapper* self ) +{ + WSABUF wsabuf; + DWORD flags = 0; + DWORD nBytesRecvd = 0; + + wsabuf.buf = &self->in_buf[self->in_offset]; + wsabuf.len = sizeof(self->in_buf) - self->in_offset; + + int err = WSARecv( self->socket, &wsabuf, 1, &nBytesRecvd, + &flags, NULL, NULL ); + if ( 0 == err ) { + XP_LOGF( "%s: got %ld bytes", __func__, nBytesRecvd ); + } else { + XP_ASSERT( err == SOCKET_ERROR ); + err = WSAGetLastError(); + XP_LOGF( "%s: WSARecv=>%d", __func__, err ); + } + + XP_ASSERT( nBytesRecvd < 0xFFFF ); + return (XP_U16)nBytesRecvd; +} /* read_from_socket */ + +XP_Bool +ce_sockwrap_event( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam ) +{ + SOCKET socket = (SOCKET)wParam; + long event = (long)LOWORD(lParam); + XP_Bool draw = XP_FALSE; + + if ( 0 != (FD_READ & event) ) { + XP_U16 nReceived; + XP_LOGF( "%s: got FD_READ", __func__ ); + nReceived = read_from_socket( self ); + if ( nReceived > 0 ) { + draw = dispatch_if_complete( self, nReceived ); + } + event &= ~FD_READ; + } + if ( 0 != (FD_WRITE & event) ) { + event &= ~FD_WRITE; + XP_LOGF( "%s: got FD_WRITE", __func__ ); + } + if ( 0 != (FD_CONNECT & event) ) { + XP_LOGF( "%s: got FD_CONNECT", __func__ ); + event &= ~FD_CONNECT; + self->socket = socket; + stateChanged( self, CE_IPST_CONNECTED ); + } + + if ( 0 != event ) { + XP_WARNF( "%s: unexpected bits left: 0x%lx", __func__, event ); + } + return draw; +} + XP_U16 ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr ) @@ -425,11 +655,15 @@ ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len, /* If the address has changed, we need to close the connection. Send thread will take care of opening it again. */ XP_ASSERT( addr->conType == COMMS_CONN_RELAY ); - if ( 0 != XP_STRCMP( addr->u.ip_relay.hostName, self->addrRec.u.ip_relay.hostName ) - || 0 != XP_STRCMP( addr->u.ip_relay.cookie, self->addrRec.u.ip_relay.cookie ) + if ( 0 != XP_STRCMP( addr->u.ip_relay.hostName, + self->addrRec.u.ip_relay.hostName ) + || 0 != XP_STRCMP( addr->u.ip_relay.cookie, + self->addrRec.u.ip_relay.cookie ) || addr->u.ip_relay.port != self->addrRec.u.ip_relay.port ) { closeConnection( self ); XP_MEMCPY( &self->addrRec, addr, sizeof(self->addrRec) ); + + getHostAddr( self ); } packet = XP_MALLOC( self->mpool, len ); diff --git a/wince/cesockwr.h b/wince/cesockwr.h index 75b41cad9..572c6accb 100755 --- a/wince/cesockwr.h +++ b/wince/cesockwr.h @@ -23,14 +23,19 @@ #include "comms.h" #include "mempool.h" +#include "cemain.h" typedef struct CeSocketWrapper CeSocketWrapper; /* forward */ -typedef void (*DataRecvProc)( XP_U8* data, XP_U16 len, void* closure ); +typedef XP_Bool (*DataRecvProc)( XP_U8* data, XP_U16 len, void* closure ); -CeSocketWrapper* ce_sockwrap_new( MPFORMAL DataRecvProc proc, void* closure ); +CeSocketWrapper* ce_sockwrap_new( MPFORMAL DataRecvProc proc, + CEAppGlobals* globals ); void ce_sockwrap_delete( CeSocketWrapper* self ); +void ce_sockwrap_hostname( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam ); +XP_Bool ce_sockwrap_event( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam ); + XP_U16 ce_sockwrap_send( CeSocketWrapper* self, const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr );