2005-02-26 02:57:19 +00:00
|
|
|
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
|
|
|
/*
|
2006-01-08 01:25:02 +00:00
|
|
|
* Copyright 2005 by Eric House (xwords@eehouse.org). (based on sample
|
2005-02-26 02:57:19 +00:00
|
|
|
* app helloworldbasic "Copyright (c) 2002, Nokia. All rights
|
|
|
|
* reserved.")
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
|
|
|
|
|
|
#include "symssock.h"
|
2005-03-01 01:13:05 +00:00
|
|
|
#include "symutil.h"
|
2005-02-26 02:57:19 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
CSendSocket::RunL()
|
|
|
|
{
|
2005-03-01 01:13:05 +00:00
|
|
|
XP_LOGF( "CSendSocket::RunL called; iStatus=%d", iStatus.Int() );
|
|
|
|
/* iSendTimer.Cancel(); */
|
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
TBool statusGood = iStatus.Int() == KErrNone;
|
2005-03-01 01:13:05 +00:00
|
|
|
switch ( iSSockState ) {
|
|
|
|
case ELookingUp:
|
|
|
|
iResolver.Close(); /* we probably won't need this again */
|
2005-03-09 14:51:11 +00:00
|
|
|
if ( statusGood ) {
|
2005-03-01 01:13:05 +00:00
|
|
|
iNameRecord = iNameEntry();
|
2005-03-19 22:28:55 +00:00
|
|
|
XP_LOGF( "name resolved" );
|
2005-03-01 01:13:05 +00:00
|
|
|
ConnectL( TInetAddr::Cast(iNameRecord.iAddr).Address() );
|
2005-03-20 19:52:21 +00:00
|
|
|
} else {
|
|
|
|
ResetState();
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EConnecting:
|
2005-03-09 14:51:11 +00:00
|
|
|
if ( statusGood ) {
|
2005-03-01 01:13:05 +00:00
|
|
|
iSSockState = EConnected;
|
|
|
|
XP_LOGF( "connect successful" );
|
|
|
|
if ( iSendBuf.Length() > 0 ) {
|
|
|
|
DoActualSend();
|
2005-03-09 14:51:11 +00:00
|
|
|
} else if ( iListenPending ) {
|
|
|
|
Listen();
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
2005-03-20 19:52:21 +00:00
|
|
|
} else {
|
|
|
|
ResetState();
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ESending:
|
2005-03-09 14:51:11 +00:00
|
|
|
if ( statusGood ) {
|
2005-03-01 01:13:05 +00:00
|
|
|
XP_LOGF( "send successful" );
|
2005-03-20 19:52:21 +00:00
|
|
|
} else {
|
|
|
|
/* Depending on error, might need to close socket, reconnect, etc.
|
|
|
|
For now we'll just trust the upper layers to figure out they
|
|
|
|
didn't get through, or user to resend. */
|
|
|
|
XP_LOGF( "send failed with error %d", iStatus.Int() );
|
|
|
|
}
|
2005-03-01 01:13:05 +00:00
|
|
|
|
2005-03-20 19:52:21 +00:00
|
|
|
iSSockState = EConnected;
|
|
|
|
iSendBuf.SetLength(0);
|
2005-03-09 14:51:11 +00:00
|
|
|
|
2005-03-20 19:52:21 +00:00
|
|
|
if ( iListenPending ) {
|
|
|
|
Listen();
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
break;
|
2005-03-09 14:51:11 +00:00
|
|
|
|
|
|
|
case EListening:
|
|
|
|
if ( statusGood ) {
|
|
|
|
if ( iDataLen == 0 ) {
|
|
|
|
/* Do nothing; we need to read again via Listen call */
|
|
|
|
iDataLen = XP_NTOHS( *(XP_U16*)iInBufDesc->Ptr() );
|
2005-03-20 19:52:21 +00:00
|
|
|
XP_LOGF( "Recv succeeded with length; now looking for %d byte"
|
|
|
|
"packet", iDataLen );
|
2005-03-09 14:51:11 +00:00
|
|
|
} else {
|
|
|
|
iDataLen = 0;
|
|
|
|
XP_LOGF( "Got packet! Calling callback" );
|
|
|
|
(*iCallback)( iInBufDesc, iClosure );
|
|
|
|
}
|
|
|
|
iSSockState = EConnected;
|
|
|
|
Listen(); /* go back to listening */
|
2005-03-20 19:52:21 +00:00
|
|
|
} else {
|
|
|
|
XP_LOGF( "listen failed with error %d", iStatus.Int() );
|
|
|
|
ResetState();
|
2005-03-09 14:51:11 +00:00
|
|
|
}
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
} /* RunL */
|
2005-02-26 02:57:19 +00:00
|
|
|
|
2005-03-20 19:52:21 +00:00
|
|
|
void
|
|
|
|
CSendSocket::ResetState()
|
|
|
|
{
|
|
|
|
iSendBuf.SetLength(0);
|
|
|
|
iSSockState = ENotConnected;
|
|
|
|
}
|
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
TBool
|
|
|
|
CSendSocket::Listen()
|
|
|
|
{
|
|
|
|
XP_LOGF( "CSendSocket::Listen" );
|
|
|
|
iListenPending = ETrue;
|
|
|
|
|
|
|
|
if ( IsActive() ) {
|
2005-03-20 19:52:21 +00:00
|
|
|
/* since iListenPending is set, we'll eventually get to listening once
|
|
|
|
all the RunL()s get called. Do nothing. */
|
2005-03-09 14:51:11 +00:00
|
|
|
} else {
|
|
|
|
if ( iSSockState == ENotConnected ) {
|
|
|
|
ConnectL();
|
2005-03-20 19:52:21 +00:00
|
|
|
} else if ( iSSockState == EConnected ) {
|
2005-03-09 14:51:11 +00:00
|
|
|
delete iInBufDesc;
|
|
|
|
|
|
|
|
TInt seekLen = iDataLen == 0? 2: iDataLen;
|
|
|
|
iInBufDesc = new TPtr8( iInBuf, seekLen );
|
|
|
|
XP_LOGF( "calling iSendSocket.Recv; looking for %d bytes",
|
|
|
|
iInBufDesc->MaxSize() );
|
|
|
|
iSendSocket.Recv( *iInBufDesc, 0, iStatus );
|
|
|
|
|
|
|
|
SetActive();
|
|
|
|
iSSockState = EListening;
|
|
|
|
iListenPending = EFalse;
|
2005-03-20 19:52:21 +00:00
|
|
|
} else {
|
|
|
|
XP_LOGF( "iSSockState=%d", iSSockState );
|
|
|
|
XP_ASSERT( 0 );
|
2005-03-09 14:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-20 19:52:21 +00:00
|
|
|
return ETrue;
|
2005-03-09 14:51:11 +00:00
|
|
|
} /* Listen */
|
|
|
|
|
|
|
|
TBool
|
|
|
|
CSendSocket::CancelListen()
|
|
|
|
{
|
|
|
|
TBool result = iSSockState == EListening;
|
|
|
|
if ( result ) {
|
|
|
|
XP_ASSERT( IsActive() );
|
|
|
|
Cancel();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
} /* CancelListen */
|
|
|
|
|
2005-02-26 02:57:19 +00:00
|
|
|
void
|
|
|
|
CSendSocket::DoCancel()
|
|
|
|
{
|
2005-03-01 01:13:05 +00:00
|
|
|
if ( iSSockState == ESending ) {
|
|
|
|
iSendSocket.CancelWrite();
|
|
|
|
iSSockState = EConnected;
|
|
|
|
} else if ( iSSockState == EConnecting ) {
|
|
|
|
iSendSocket.CancelConnect();
|
|
|
|
iSSockState = ENotConnected;
|
|
|
|
} else if ( iSSockState == ELookingUp ) {
|
|
|
|
iResolver.Cancel();
|
|
|
|
iResolver.Close();
|
2005-03-09 14:51:11 +00:00
|
|
|
} else if ( iSSockState == EListening ) {
|
|
|
|
iSendSocket.CancelRecv();
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
} /* DoCancel */
|
2005-02-26 02:57:19 +00:00
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
CSendSocket::CSendSocket( ReadNotifyCallback aCallback,
|
|
|
|
void* aClosure )
|
2005-02-26 02:57:19 +00:00
|
|
|
: CActive(EPriorityStandard)
|
2005-03-01 01:13:05 +00:00
|
|
|
,iSSockState(ENotConnected)
|
|
|
|
,iAddrSet( EFalse )
|
2005-03-09 14:51:11 +00:00
|
|
|
,iCallback(aCallback)
|
|
|
|
,iClosure(aClosure)
|
|
|
|
,iListenPending(EFalse)
|
|
|
|
,iInBufDesc( NULL )
|
|
|
|
,iDataLen( 0 )
|
2005-02-26 02:57:19 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CSendSocket::~CSendSocket()
|
|
|
|
{
|
2005-03-03 15:26:19 +00:00
|
|
|
Cancel();
|
|
|
|
iSocketServer.Close();
|
2005-02-26 02:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CSendSocket::ConstructL()
|
|
|
|
{
|
2005-03-01 01:13:05 +00:00
|
|
|
CActiveScheduler::Add( this );
|
|
|
|
XP_LOGF( "calling iSocketServer.Connect()" );
|
2005-03-23 05:48:11 +00:00
|
|
|
TInt err = iSocketServer.Connect( 2 );
|
2005-03-01 01:13:05 +00:00
|
|
|
XP_LOGF( "Connect=>%d", err );
|
|
|
|
User::LeaveIfError( err );
|
2005-02-26 02:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*static*/ CSendSocket*
|
2005-03-09 14:51:11 +00:00
|
|
|
CSendSocket::NewL( ReadNotifyCallback aCallback, void* aClosure )
|
2005-02-26 02:57:19 +00:00
|
|
|
{
|
2005-03-09 14:51:11 +00:00
|
|
|
CSendSocket* me = new CSendSocket( aCallback, aClosure );
|
2005-02-26 02:57:19 +00:00
|
|
|
CleanupStack::PushL( me );
|
|
|
|
me->ConstructL();
|
|
|
|
CleanupStack::Pop( me );
|
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|
2005-03-01 01:13:05 +00:00
|
|
|
void
|
|
|
|
CSendSocket::ConnectL( TUint32 aIpAddr )
|
|
|
|
{
|
|
|
|
XP_LOGF( "ConnectL( 0x%x )", aIpAddr );
|
|
|
|
|
|
|
|
TInt err = iSendSocket.Open( iSocketServer, KAfInet,
|
2005-03-09 14:51:11 +00:00
|
|
|
KSockStream, KProtocolInetTcp );
|
2005-03-01 01:13:05 +00:00
|
|
|
XP_LOGF( "iSocket.Open => %d", err );
|
|
|
|
User::LeaveIfError( err );
|
|
|
|
|
|
|
|
// Set up address information
|
2005-03-19 22:28:55 +00:00
|
|
|
iAddress.SetPort( iCurAddr.u.ip_relay.port );
|
2005-03-01 01:13:05 +00:00
|
|
|
iAddress.SetAddress( aIpAddr );
|
|
|
|
|
|
|
|
// Initiate socket connection
|
2005-03-09 14:51:11 +00:00
|
|
|
XP_LOGF( "calling iSendSocket.Connect" );
|
2005-03-01 01:13:05 +00:00
|
|
|
iSendSocket.Connect( iAddress, iStatus );
|
2005-03-01 13:53:41 +00:00
|
|
|
|
|
|
|
SetActive();
|
2005-03-01 01:13:05 +00:00
|
|
|
iSSockState = EConnecting;
|
|
|
|
|
|
|
|
// Start a timeout
|
|
|
|
/* iSendTimer.After( iConnectTimeout ); */
|
|
|
|
|
|
|
|
} /* ConnectL */
|
|
|
|
|
|
|
|
void
|
|
|
|
CSendSocket::ConnectL()
|
|
|
|
{
|
|
|
|
XP_LOGF( "CSendSocket::ConnectL" );
|
|
|
|
if ( iSSockState == ENotConnected ) {
|
|
|
|
TInetAddr ipAddr;
|
|
|
|
|
2005-03-19 22:28:55 +00:00
|
|
|
if ( iCurAddr.u.ip_relay.hostName && iCurAddr.u.ip_relay.hostName[0] ) {
|
2005-03-01 01:13:05 +00:00
|
|
|
|
2005-03-19 22:28:55 +00:00
|
|
|
XP_LOGF( "connecting to %s", iCurAddr.u.ip_relay.hostName );
|
2005-03-01 01:13:05 +00:00
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
TBuf16<MAX_HOSTNAME_LEN> tbuf;
|
2005-03-19 22:28:55 +00:00
|
|
|
tbuf.Copy( TBuf8<MAX_HOSTNAME_LEN>(iCurAddr.u.ip_relay.hostName) );
|
2005-03-09 14:51:11 +00:00
|
|
|
TInt err = ipAddr.Input( tbuf );
|
|
|
|
XP_LOGF( "ipAddr.Input => %d", err );
|
2005-03-01 01:13:05 +00:00
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
if ( err != KErrNone ) {
|
|
|
|
/* need to look it up */
|
|
|
|
err = iResolver.Open( iSocketServer, KAfInet, KProtocolInetUdp );
|
|
|
|
XP_LOGF( "iResolver.Open => %d", err );
|
|
|
|
User::LeaveIfError( err );
|
2005-03-01 01:13:05 +00:00
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
iResolver.GetByName( tbuf, iNameEntry, iStatus );
|
|
|
|
iSSockState = ELookingUp;
|
|
|
|
|
|
|
|
SetActive();
|
|
|
|
} else {
|
|
|
|
ConnectL( ipAddr.Address() );
|
|
|
|
}
|
2005-03-01 01:13:05 +00:00
|
|
|
} else {
|
2005-03-09 14:51:11 +00:00
|
|
|
/* PENDING FIX THIS!!!! */
|
|
|
|
XP_LOGF( "Can't connect: no relay name" );
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* ConnectL */
|
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
void
|
|
|
|
CSendSocket::ConnectL( const CommsAddrRec* aAddr )
|
|
|
|
{
|
|
|
|
/* If we're connected and the address is the same, do nothing. Otherwise
|
|
|
|
disconnect, change the address, and reconnect. */
|
|
|
|
|
|
|
|
TBool sameAddr = iAddrSet &&
|
|
|
|
(0 == XP_MEMCMP( (void*)&iCurAddr, (void*)aAddr, sizeof(aAddr) ) );
|
|
|
|
|
|
|
|
if ( sameAddr && iSSockState >= EConnected ) {
|
|
|
|
/* do nothing */
|
|
|
|
} else {
|
|
|
|
Disconnect();
|
|
|
|
|
|
|
|
iCurAddr = *aAddr;
|
|
|
|
iAddrSet = ETrue;
|
|
|
|
|
|
|
|
ConnectL();
|
|
|
|
}
|
|
|
|
} /* ConnectL */
|
|
|
|
|
2005-03-01 01:13:05 +00:00
|
|
|
void
|
|
|
|
CSendSocket::Disconnect()
|
|
|
|
{
|
|
|
|
XP_LOGF( "CSendSocket::Disconnect" );
|
|
|
|
Cancel();
|
|
|
|
if ( iSSockState >= EConnected ) {
|
|
|
|
iSendSocket.Close();
|
|
|
|
}
|
|
|
|
iSSockState = ENotConnected;
|
|
|
|
} /* Disconnect */
|
|
|
|
|
2005-02-26 02:57:19 +00:00
|
|
|
TBool
|
2005-03-01 01:13:05 +00:00
|
|
|
CSendSocket::SendL( const XP_U8* aBuf, XP_U16 aLen, const CommsAddrRec* aAddr )
|
2005-02-26 02:57:19 +00:00
|
|
|
{
|
|
|
|
XP_LOGF( "CSendSocket::SendL called" );
|
2005-03-01 01:13:05 +00:00
|
|
|
TBool success;
|
|
|
|
|
2005-03-09 14:51:11 +00:00
|
|
|
XP_ASSERT( iSSockState == EListening || !IsActive() );
|
2005-03-01 01:13:05 +00:00
|
|
|
if ( iSSockState == ESending ) {
|
|
|
|
success = EFalse;
|
|
|
|
} else if ( aLen > KMaxMsgLen ) {
|
|
|
|
success = EFalse;
|
2005-03-20 19:52:21 +00:00
|
|
|
} else if ( iSendBuf.Length() != 0 ) {
|
|
|
|
XP_LOGF( "old buffer not sent yet" );
|
|
|
|
success = EFalse;
|
2005-03-01 01:13:05 +00:00
|
|
|
} else {
|
2005-03-09 14:51:11 +00:00
|
|
|
/* TCP-based protocol requires 16-bits of length, in network
|
|
|
|
byte-order, followed by data. */
|
|
|
|
XP_U16 netLen = XP_HTONS( aLen );
|
|
|
|
iSendBuf.Append( (TUint8*)&netLen, sizeof(netLen) );
|
|
|
|
iSendBuf.Append( aBuf, aLen );
|
2005-03-01 01:13:05 +00:00
|
|
|
|
|
|
|
if ( iSSockState == ENotConnected ) {
|
2005-03-19 22:28:55 +00:00
|
|
|
ConnectL( aAddr );
|
2005-03-09 14:51:11 +00:00
|
|
|
} else if ( iSSockState == EConnected || iSSockState == EListening ) {
|
2005-03-01 01:13:05 +00:00
|
|
|
DoActualSend();
|
2005-03-09 14:51:11 +00:00
|
|
|
} else {
|
|
|
|
XP_ASSERT( 0 ); /* not sure why we'd be here */
|
2005-03-01 01:13:05 +00:00
|
|
|
}
|
|
|
|
success = ETrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
2005-02-26 02:57:19 +00:00
|
|
|
} /* SendL */
|
2005-03-01 01:13:05 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
CSendSocket::DoActualSend()
|
|
|
|
{
|
|
|
|
XP_LOGF( "CSendSocket::DoActualSend called" );
|
2005-03-09 14:51:11 +00:00
|
|
|
|
|
|
|
if ( CancelListen() ) {
|
|
|
|
iListenPending = ETrue;
|
|
|
|
}
|
|
|
|
|
2005-03-01 01:13:05 +00:00
|
|
|
iSendSocket.Write( iSendBuf, iStatus ); // Initiate actual write
|
|
|
|
SetActive();
|
|
|
|
|
|
|
|
// Request timeout
|
|
|
|
/* iSendTimer.After( iWriteTimeout ); */
|
|
|
|
iSSockState = ESending;
|
|
|
|
}
|
|
|
|
|
2005-02-26 02:57:19 +00:00
|
|
|
#endif
|