Add support for "slim", which is "stem" + removal of some exports and checking of import details
For this to work, the static_dependencies.txt file needs to contain the augmented dependency information.
To help with this, it can now consume a mixture of both rom_content.csv lines and static_dependencies.txt lines: the
best way to update the information would be something like
(edit rom_content.csv to add "slim" to XXX.dll)
findstr /i "xxx.dll" rom_content.csv > slim.txt
findstr /i "xxx.dll" static_dependencies.txt >> slim.txt
perl ..\tools\static_dependencies.pl -u static_dependencies.txt slim.txt > new_dependencies.txt
This will notice the "slim" marking for xxx.dll, and record the detailed import and export lists for
xxx.dll and everything which links to it. The new information will look something like
sys\bin\xxx.dll /epoc32/release/armv5/urel/stem_xxx.dll exports=1-98.100-102:euser[100039e5].dll
sys\bin\yyy.dll /epoc32/release/armv5/urel/yyy.dll euser[100039e5].dll:xxx[102750c7].dll@2.4-5.77.104-106:scppnwdl.dll
sys\bin\zzz.dll /epoc32/release/armv5/urel/zzz.dll euser[100039e5].dll:xxx[102750c7].dll@23.25.74-77:scppnwdl.dll
Only executables for which there is a "slim" marking will have this level of detail.
The filtering script now does the detailed cross-checking of imports to exports for "slim" executables.
In this case, it will observe the stem_xxx.dll does not export ordinal 104, and so the filtering will include
deleting sys\bin\yyy.dll (xxx.dll Missing ordinal 104)
sys\bin\zzz.dll will be acceptable, because it only uses ordinals which are still present in stem_xxx.dll
/*
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <sys/types.h>
#include <string.h> // for memcpy
#include <fcntl.h> // for struct stat
#include <sys/errno.h> // for ENOTSOCK
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <netinet/in.h> // for htons
#include <sys/sockio.h>
#include <bt_sock.h> // Symbian BT constantss needed for cooperation with Symbian sockets
#include <arpa/inet.h>
#include <es_sock.h>
#include <in_sock.h>
#include <net/if.h>
#include <commdb.h>
#include <cdbcols.h>
#include <commdbconnpref.h>
#include <e32base.h>
#include <e32err.h>
#include <utf.h>
#include <e32std.h>
#include <net/route.h>
#include <in_iface.h>
#include "fdesc.h"
#include "lposix.h"
#include "sysif.h"
// Support for struct sockaddr conversion
TUSockAddr::TUSockAddr (TAny* aBuf)
: TSockAddr(), iError(0)
{
Prepare(aBuf);
}
void TUSockAddr::Prepare (TAny* aBuf)
//
// Prepare a TUSockAddr to receive an address (used in RecvFrom)
// Setting the length to 0 indicates that we don't really want this address anyway.
//
{
if (aBuf==0)
{
SetLength(0);
iError = EFAULT;
return;
}
}
EXPORT_C TUSockAddr::TUSockAddr (const TAny* aBuf, TUint aLen)
: TSockAddr(), iError(0)
{
Set(aBuf,aLen);
}
void TUSockAddr::Set (const TAny* aBuf, TUint aLen)
//
// Construct an ESOCK TSockAddr from a struct sockaddr.
// We have to deal with the network byte ordering of AF_INET addresses
//
{
if (!aBuf)
{
iError = EFAULT;
SetLength(0);
return;
}
const TUint dataOffset = (TUint)&((struct sockaddr *)0)->sa_data[0];
// aLen should be atleast have minimum size.
if (aLen < dataOffset)
{
iError = EINVAL;
SetLength(0);
return;
}
const struct sockaddr* sp= (const struct sockaddr *)(aBuf);
TUint8 *from=(TUint8*)aBuf;
if (sp->sa_family==AF_INET)
{
// byte-swap sockaddr_in back into host ordering
TUint port=(from[2]<<8)+from[3];
from+=4;
TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
from+=4;
SetFamily(AF_INET);
SetPort(port);
*(TUint32*)UserPtr()=addr;
SetUserLen(4);
return;
}
else if (sp->sa_family == AF_INET6)
{
SetFamily(sp->sa_family);
SetPort(ByteOrder::Swap16(sp->sa_port));
from+=4;
// copy the rest of the data as given
TUint8 *to=UserPtr();
if (aLen<4)
aLen=4;
aLen-=4; // skip fmaily and port
if (aLen>24)
aLen=24;
memcpy(to,from,aLen);
SetUserLen(aLen);
return;
}
#if 0 // break dependency on bluetooth.dll
else if (sp->sa_family == KBTAddrFamily)
{
// Make a TBTSockAddr from a sockaddr_bt...
TBTSockAddr tmpAddr;
// Family is always Bluetooth:
tmpAddr.SetFamily(KBTAddrFamily);
// The port number has the correct byte order already, as the
// POSIX Bluetooth APIs assume litle-endian format:
tmpAddr.SetPort(sp->sa_port);
// For the address we need to reverse the byte ordering, as
// Symbian appears to index Bluetooth addresses in a
// big-endian manner:
const TInt KBTAddrLength = 6; // Bytes in a Bluetooth address
const TInt KBTAddrOffset = 4; // Offset of address in sockaddr_bt
TBTDevAddr devAddr;
const TInt KMinLength = KBTAddrLength + KBTAddrOffset;
if (aLen >= KMinLength)
{
for (TInt i=0; i<KBTAddrLength; ++i)
{
devAddr[i] = from[KMinLength - 1 - i];
}
}
tmpAddr.SetBTAddr(devAddr);
// Security settings:
TBTServiceSecurity sec;
sec.SetUid(TUid::Uid(0));
sec.SetAuthentication(EFalse);
sec.SetEncryption(EFalse);
sec.SetAuthorisation(EFalse);
sec.SetDenied(EFalse);
tmpAddr.SetSecurity(sec);
// Now we must copy the contents of the "tmpAddr" TBTSockAddr,
// but unfortunately there isn't an assignment operator for us
// to use. Still, we know it is a self-contained T class for
// which a direct shallow copy using memcopy() will be ok:
//
memcpy(this, &tmpAddr, sizeof(TBTSockAddr));
return;
}
#endif
else
{
// Not AF_INET or KBTAddrFamily:
// expand the family and port
SetFamily(sp->sa_family);
SetPort(sp->sa_port);
from+=4;
// copy the rest of the data as given
TUint8 *to=UserPtr();
if (aLen<4)
aLen=4;
aLen-=4; // skip fmaily and port
if (aLen>24)
aLen=24;
memcpy(to,from,aLen);
SetUserLen(aLen);
}
}
/*
* Extract a struct sockaddr from a TSockAddr
*/
EXPORT_C void TUSockAddr::Get(TAny* addr, unsigned long* len)
{
if (addr==0)
{
iError = EFAULT;
SetLength(0);
return;
}
const TUint dataOffset = (TUint)&((struct sockaddr *)0)->sa_data[0];
// aLen should be atleast have minimum size.
if (*len < dataOffset)
{
iError = EINVAL;
SetLength(0);
return;
};
struct sockaddr* sp=(struct sockaddr*)addr;
TUint16 port=(TUint16)Port();
//The ipv4 address could be obtained either as
//plain 32 bit address or as ipv4 mapped ipv6 address
TInetAddr inetAddr(*this);
TBool isV4Mapped = (Family()==AF_INET6) && (inetAddr.IsV4Mapped() || inetAddr.IsV4Compat());
if (Family()==AF_INET || isV4Mapped)
{
sp->sa_family=AF_INET;
sp->sa_port= ByteOrder::Swap16(port);
TUint8* from=UserPtr();
TUint32 fromaddr;
//If the address is v4 mapped, we take the last 4 bytes from the 16 bytes long v6 structure.
if(isV4Mapped)
fromaddr = (from[15]<<24)+(from[14]<<16)+(from[13]<<8)+from[12];
else
fromaddr = (from[0]<<24)+(from[1]<<16)+(from[2]<<8)+ from[3];
*(TUint32*)sp->sa_data=fromaddr;
*len=8;
return;
}
else if (Family()==AF_INET6)
{
sp->sa_family=(TUint16)Family();
sp->sa_port=ByteOrder::Swap16(port);
TUint ulen=GetUserLen();
if (ulen+4>(*len))
ulen=(*len)-4;
*len=ulen+4;
memcpy(sp->sa_data,UserPtr(),ulen);
sp->sa_len = ulen;
return;
}
else if (Family()==KBTAddrFamily)
{
sp->sa_family=KBTAddrFamily;
sp->sa_port=port;
const TInt KBTAddrLength = 6;
if (GetUserLen() == KBTAddrLength)
{
for (TInt i=0; i<KBTAddrLength; ++i)
{
sp->sa_data[KBTAddrLength - 1 - i] = UserPtr()[i];
}
}
return;
}
else
{
// Not AF_INET or KBTAddrFamily:
sp->sa_family=(TUint16)Family();
sp->sa_port=port;
TUint ulen=GetUserLen();
if (ulen+4>(*len))
ulen=(*len)-4;
*len=ulen+4;
memcpy(sp->sa_data,UserPtr(),ulen);
}
}
// The Socket descriptor class
CSocketDesc::CSocketDesc()
:iIoctlBuf(0,0),
iSocketPtr(NULL),
iConnPref(),
iConnectionPtr(NULL),
iSubConnectionPtr(NULL),
iRConnectionIndex(-1),
iSockServPtr(NULL)
{
};
TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
{
if (protocol == 0)
{
if (family == AF_INET)
{
switch (style)
{
case SOCK_STREAM:
protocol = IPPROTO_TCP;
break;
case SOCK_DGRAM:
protocol = IPPROTO_UDP;
break;
}
}
else
{
protocol = KUndefinedProtocol;
}
}
iFcntlFlag = 0;
TInt err = CreateLock();
if (err)
{
return err;
}
if (family == AF_INET6)
{
err = iSocket.Open(aSs, KAfInet, style, protocol);
}
else
{
err = iSocket.Open(aSs, family, style, protocol);
}
if (err == KErrNone)
{
iStyle = style;
iSocket.Close(); // We will close now, to open later using connection preferences
iAddrFamily = family;
iProtocol = protocol;
iSockServPtr = &aSs; // Saving the const session pointer for later use
}
return err;
}
TInt CSocketDesc::FinalClose()
{
CLocalSystemInterface* backend = Backend();
backend->DefConnLock().Wait();
RHeap* oheap = User::SwitchHeap(backend->Heap());
if (iSocketPtr != NULL)
{
iSocketPtr = NULL;
StopInterface(NULL); // Checks for RConnection as well as RSubConnection
backend->RemoveSocket(this);
}
CSockDescBase::FinalClose();
User::SwitchHeap(oheap);
backend->DefConnLock().Signal();
return KErrNone;
}
void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
{
//Acquire the Lock before read and release it later
iReadLock.Wait();
if (iSocketPtr == NULL)
{
TInt ret = OpenUsingPreference();
if (ret != KErrNone) // Error in open
{
Complete(aStatus,ret);
iReadLock.Signal();
return;
}
}
CSockDescBase::Read (aBuf,aStatus);
iReadLock.Signal();
}
TInt CSocketDesc::ReadCompletion(TDes8& aBuf, TInt aStatus)
{
return CSockDescBase::ReadCompletion(aBuf, aStatus);
}
void CSocketDesc::ReadCancel()
{
if (iSocketPtr != NULL)
{
CSockDescBase::ReadCancel();
}
}
void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
{
TInt err = maybe_reopen_socket();
if (err != KErrNone)
{
Complete(aStatus, err);
return;
}
iWriteLock.Wait();
CSockDescBase::Write(aBuf, aStatus);
iWriteLock.Signal();
}
void CSocketDesc::WriteCancel()
{
if (iSocketPtr != NULL)
{
CSockDescBase::WriteCancel();
}
}
TInt CSocketDesc::Bind(const struct sockaddr* aAddr, unsigned long aSize)
{
TInt ret;
TUSockAddr addr(aAddr,aSize);
if (addr.iError != 0)
{
return addr.iError;
}
ret = maybe_reopen_socket();
if (ret != KErrNone)
return ret;
ATOMICSOCKETOP(ret = iSocket.Bind(addr),return KErrBadHandle)
return ret;
}
TInt CSocketDesc::Listen(TUint qSize)
{
TInt ret;
if (iStyle == SOCK_DGRAM) // Listen on UDP socket, crashing at RSocket::Listen().
{
return EOPNOTSUPP;
}
ret = maybe_reopen_socket();
if (ret != KErrNone)
return ret;
return CSockDescBase::Listen(qSize);
}
TInt CSocketDesc::SockName(int anEnd, struct sockaddr* anAddr,unsigned long* aSize)
{
if (!anAddr)
{
return EFAULT;
}
TInt ret = maybe_reopen_socket();
if (ret != KErrNone)
return ret;
struct sockaddr temp;
unsigned long len = sizeof( temp );
TUSockAddr nSockAddr(&temp, len );
ret = CSockDescBase::SockName(anEnd,nSockAddr);
if(ret == KErrNone )
{
nSockAddr.Get(&temp,&len );
if( *aSize > len )
*aSize = len;
memcpy( anAddr,&temp,*aSize);
}
return ret;
}
TInt CSocketDesc::GetSockOpt(TInt anOptionName, TInt anOptionLevel, TDes8& anOption)
{
TInt ret;
if (anOption.Ptr() == NULL)
{
return EFAULT;
}
if (anOption.Length() == 0)
{
return EINVAL;
}
ret = maybe_reopen_socket();
if (ret != KErrNone)
return ret;
if (SO_TYPE == anOptionName && SOL_SOCKET == anOptionLevel)
{
TProtocolDesc protocolInfo;
ATOMICSOCKETOP(ret = iSocket.Info(protocolInfo), ret = KErrBadHandle)
if (KErrNone == ret )
{
// Copy the Socket Type to the buffer
TInt size = (anOption.Length() < sizeof(protocolInfo.iSockType))? anOption.Length(): sizeof(protocolInfo.iSockType);
Mem::Copy((unsigned char*)anOption.Ptr(), &protocolInfo.iSockType, size);
anOption.SetLength(size);
}
return ret;
}
if(IPPROTO_IP == anOptionLevel && IP_MULTICAST_IF == anOptionName)
{
TUSockAddr addr;
struct sockaddr_in sockAddress;
sockAddress.sin_family = AF_INET;
ATOMICSOCKETOP(sockAddress.sin_port = iSocket.LocalPort(),return KErrBadHandle)
ATOMICSOCKETOP(iSocket.LocalName(addr);,return KErrBadHandle)
TInt a = sizeof(sockAddress);
addr.Get(&sockAddress,(unsigned long*)&a);
TInt size = (anOption.Length() < sizeof(sockAddress.sin_addr))? anOption.Length(): sizeof(sockAddress.sin_addr);
Mem::Copy((unsigned char*)anOption.Ptr(), &(sockAddress.sin_addr), size);
anOption.SetLength(size);
return KErrNone;
}
switch(anOptionLevel)
{
case IPPROTO_TCP:
anOptionLevel=SOL_TCP;
break;
case IPPROTO_IP:
anOptionLevel=SOL_IP;
break;
case SOL_SOCKET:
{
switch(anOptionName)
{
case SO_REUSEADDR:
anOptionLevel=SOL_IP;
break;
case SO_OOBINLINE:
case SO_KEEPALIVE:
anOptionLevel=SOL_TCP;
break;
case SO_BROADCAST:
*((TInt*)anOption.Ptr()) = 1;
return KErrNone;
}
}
}
switch(anOptionName)
{
case IP_MULTICAST_TTL:
anOptionLevel=KSolInetIp;
anOptionName=KSoIp6MulticastHops;
break;
case IP_MULTICAST_LOOP:
anOptionLevel=KSolInetIp;
anOptionName=KSoIp6MulticastLoop;
break;
}
ATOMICSOCKETOP(ret = iSocket.GetOpt(anOptionName,anOptionLevel,anOption), return KErrBadHandle)
return ret;
}
TInt CSocketDesc::GetInterfaceIndex(TUint32 anAddr)
{
TPckgBuf<TSoInetIfQuery> ifq;
TInt aIndex = -1;
if (KInetAddrAny == anAddr)
{
aIndex = 0;
return aIndex;
}
else
{
TInt ret = KErrNone;
ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle)
if (ret != KErrNone)
return KErrGeneral;
TPckgBuf<TSoInetInterfaceInfo>iface;
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
while(ret == KErrNone)
{
TSoInetInterfaceInfo &info = iface();
TInt result;
if(info.iState == EIfUp)
{
if (anAddr == info.iAddress.Address())
{
ifq().iName = info.iName;
ATOMICSOCKETOP( result = iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifq), result = KErrBadHandle )
if (result == KErrNone)
aIndex = ifq().iIndex;
}
}
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
}
}
return aIndex;
}
TInt CSocketDesc::SetSockOpt(TInt anOptionName, TInt anOptionLevel, TDesC8& anOption)
{
TInt ret;
if (anOption.Ptr() == NULL)
{
return EFAULT;
}
if (anOption.Length() == 0)
{
return EINVAL;
}
ret = maybe_reopen_socket();
if (ret != KErrNone)
return ret;
switch(anOptionLevel)
{
case IPPROTO_TCP:
anOptionLevel=SOL_TCP;
break;
case IPPROTO_IP:
anOptionLevel=SOL_IP;
break;
case SOL_SOCKET:
{
switch(anOptionName)
{
case SO_REUSEADDR:
anOptionLevel=SOL_IP;
break;
case SO_OOBINLINE:
case SO_KEEPALIVE:
anOptionLevel=SOL_TCP;
break;
}
}
}
TPckgBuf<TIp6Mreq> req;
struct ip_mreq *mreq;
TInt aIndex = -1;
TUint8 *from;
TUint32 srcAddr;
TUint32 maddr;
TInetAddr multiAddr;
TInt *Option = NULL;
TInt ttlValue = 0;
switch(anOptionName)
{
case IP_ADD_MEMBERSHIP: //KSoIp6JoinGroup
case IP_DROP_MEMBERSHIP: //KSoIp6LeaveGroup
mreq = (struct ip_mreq *)anOption.Ptr();
from = (TUint8 *)anOption.Ptr();
from+=4;
// swaping the byte order
srcAddr = ByteOrder::Swap32( mreq->imr_interface.s_addr);
//fetch the interface index
aIndex = GetInterfaceIndex(srcAddr);
// Set the multicast addr
from = (TUint8 *)anOption.Ptr();
maddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
multiAddr.SetAddress( maddr);
multiAddr.ConvertToV4Mapped();
if (multiAddr.IsMulticast())
{
req().iAddr = multiAddr.Ip6Address();
req().iInterface = aIndex;
}
ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName, anOptionLevel, req), return KErrBadHandle )
return ret;
case IP_MULTICAST_TTL:
anOptionLevel=KSolInetIp;
anOptionName=KSoIp6MulticastHops;
Option = (TInt*)anOption.Ptr();
ttlValue = *Option;
ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName,anOptionLevel,ttlValue), return KErrBadHandle )
return ret;
case SO_BROADCAST:
//check if user is trying to disable broadcast
Option = (TInt*)anOption.Ptr();
return (*Option == 0 ? KErrNotSupported : KErrNone);
case IP_MULTICAST_IF:
{
//No support for equivalent flag KsoIp6MulticastIf presently
//call bind instead
struct in_addr *inAddress = (struct in_addr*)anOption.Ptr();
struct sockaddr_in sockAddress;
sockAddress.sin_family = AF_INET;
ATOMICSOCKETOP(sockAddress.sin_port = iSocket.LocalPort();,return KErrBadHandle)
sockAddress.sin_addr.s_addr = inAddress->s_addr;
TUSockAddr ifAddress(&sockAddress, sizeof(sockAddress));
ATOMICSOCKETOP( ret = iSocket.Bind(ifAddress), return KErrBadHandle )
return ret;
}
case IP_MULTICAST_LOOP:
anOptionLevel=KSolInetIp;
anOptionName=KSoIp6MulticastLoop;
break;
}
ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName,anOptionLevel,anOption), return KErrBadHandle )
return ret;
}
void CSocketDesc::Sync (TRequestStatus& aStatus)
{
// Judging from the Solaris man pages, this does nothing.
Complete(aStatus,KErrNone);
}
void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
{
TInt err = maybe_reopen_socket();
if (err != KErrNone)
{
Complete(aStatus, err);
return;
}
iReadLock.Wait();
CSockDescBase::RecvFrom(aDesc, from, flags, aStatus);
iReadLock.Signal();
}
void CSocketDesc::RecvFromCancel()
{
if (iSocketPtr != NULL)
{
CSockDescBase::RecvFromCancel();
}
}
void CSocketDesc::SendTo(TDes8& aDesc, const struct sockaddr* anAddr, unsigned long aAddrLen, int flags, TRequestStatus& aStatus)
{
TInt err = maybe_reopen_socket();
if (err != KErrNone)
{
Complete(aStatus, err);
return;
}
TUSockAddr toAddr(anAddr, aAddrLen);
iWriteLock.Wait();
CSockDescBase::SendTo(aDesc, toAddr, flags, aStatus);
iWriteLock.Signal();
}
void CSocketDesc::SendToCancel()
{
// Should we use atomic loads here?
if (iSocketPtr != NULL)
{
CSockDescBase::SendToCancel();
}
}
void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
{
if (__e32_atomic_load_acq32(&iSocketPtr) == NULL) // Not opened at all. Nothing to do.
{
Complete(aStatus,KErrNone);
return;
}
CSockDescBase::Shutdown(aHow,aStatus);
return;
}
void CSocketDesc::Accept(CFileDescBase*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs, TSockAddr * /*aAddr*/)
{
aNewSocket = NULL;
TInt err = maybe_reopen_socket();
if (err != KErrNone)
{
Complete(aStatus, err);
return;
}
iReadLock.Wait();
// what are the below coverity thingummichs?
//coverity[alloc_fn]
//coverity[assign]
CSocketDesc *newSocket = new CSocketDesc;
if (!newSocket)
{
Complete(aStatus, KErrNoMemory);
iReadLock.Signal();
return;
}
err = newSocket->CreateLock();
if (err)
{
Complete(aStatus, KErrNoMemory);
delete newSocket;
iReadLock.Signal();
//coverity[memory_leak]
return;
}
err = newSocket->iSocket.Open(aSs);
if (err)
{
Complete(aStatus, err);
newSocket->FinalClose(); // this will Close locks
delete newSocket;
iReadLock.Signal();
//coverity[memory_leak]
return;
}
newSocket->iSocketPtr = &newSocket->iSocket;
newSocket->iStyle = iStyle;
err = KErrNone;
ATOMICSOCKETOP( iSocket.Accept(newSocket->iSocket,aStatus), err = KErrBadHandle )
if( err )
{
Complete(aStatus, err);
newSocket->FinalClose(); // this will Close locks
delete newSocket;
}
else
{
aNewSocket = newSocket;
}
iReadLock.Signal();
}
void CSocketDesc::AcceptCancel()
{
if (iSocketPtr != NULL)
{
ATOMICSOCKETOP( iSocket.CancelAccept(), NOP )
}
}
void CSocketDesc::Connect(const struct sockaddr* aAddr,unsigned long size,TRequestStatus& aStatus)
{
TUSockAddr addr(aAddr,size);
if (addr.iError != 0)
{
aStatus = addr.iError;
return;
}
TInt err = maybe_reopen_socket();
if (err != KErrNone)
{
aStatus = err;
return;
}
iWriteLock.Wait();
if( GetConnectionProgress() == EFalse )
{
ATOMICSOCKETOP(iSocket.Connect(addr, aStatus), Complete(aStatus,KErrBadHandle))
User::WaitForRequest(aStatus);
if( aStatus.Int() == KErrWouldBlock )
SetConnectionProgress(ETrue);
}
else
{
aStatus = EALREADY;
}
iWriteLock.Signal();
}
void CSocketDesc::ConnectCancel()
{
if (iSocketPtr != NULL)
{
ATOMICSOCKETOP(iSocket.CancelConnect(),NOP)
}
}
void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
{
TInt ret = KErrNone;
int* param = reinterpret_cast<int*>(aParam);
ret = maybe_reopen_socket();
if (ret != KErrNone)
{
Complete(aStatus, ret);
return;
}
switch ((unsigned)aCmd)
{
case FIONREAD:
case E32IONREAD:
{
ATOMICSOCKETOP( ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param), ret = KErrBadHandle )
}
break;
case E32IOSELECT:
{
iIoctlBuf.Set((TText8*)aParam,4,4);
iIoctlLock.Wait();
iIoctlFlag = ETrue;
ATOMICSOCKETOP(iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket), Complete(aStatus,KErrBadHandle))
}
return;
case SIOCGIFCONF:
ret = GetInterfaceList(aParam);
break;
case SIOCGIFINDEX:
ret = GetInterfaceIndexByName(aParam);
break;
case SIOCGIFACTIVECONF:
ret = GetActiveInterfaceList(aParam);
break;
case SIOCSIFNAME:
ret = SetInterfaceByName(aParam);
break;
case SIOCIFSTART:
ret = StartInterface(aParam);
if(KErrNone == ret)
{
iSocket.Close();
iSocketPtr = NULL;
}
break;
case SIOCIFACTIVESTART:
ret = StartActiveInterface(aParam);
if(KErrNone == ret)
{
iSocket.Close();
iSocketPtr = NULL;
}
break;
case SIOCIFSTOP:
ret = StopInterface(aParam);
break;
case SIOCATMARK:
ATOMICSOCKETOP(ret=iSocket.GetOpt(KSoTcpRcvAtMark,KSolInetTcp,*param), ret = KErrBadHandle)
break;
case SIOCGIFADDR:
ret = GetIpAddress(aParam);
break;
case SIOCGIFNUM:
ret = GetInterafceNumber(aParam);
break;
case SIOCADDRT:
ret = RouteRequest(KSoInetAddRoute, aParam);
break;
case SIOCDELRT:
ret = RouteRequest(KSoInetDeleteRoute, aParam);
break;
case SIOCGIFHWADDR:
ret = GetInterfaceHWAddress(aParam);
break;
case SIOCGIFACTIVEIAP:
ret = GetActiveInterface( aParam);
break;
default:
ret=KErrNotSupported;
break;
}
Complete(aStatus,ret);
}
TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
{
if(iIoctlFlag)
{
iIoctlLock.Signal();
iIoctlFlag = EFalse;
}
return aStatus;
}
void CSocketDesc::IoctlCancel()
{
if (iSocketPtr && iIoctlFlag)
{
ATOMICSOCKETOP(iSocket.CancelIoctl(), NOP)
iIoctlLock.Signal();
iIoctlFlag = EFalse;
}
}
// -----------------------------------------------------------------------------
// CSocketDesc::Fcntl
// Symbian Socket Specific Implementation for fcntl
// Implementation of fcntl for Socket will make use of
// RSocket::SetOpt(KSONonBlockingIO/KSOBlockingIO, KSOLSocket)
// As of now fcntl supports F_SETFL and F_GETFL
// -----------------------------------------------------------------------------
//
TInt CSocketDesc::Fcntl(TUint anArg, TUint aCmd)
{
TInt err = maybe_reopen_socket();
if (err != KErrNone)
return err;
return CSockDescBase::Fcntl(anArg, aCmd);
}
TInt CSocketDesc :: GetIpAddress( void *aParam )
{
TInetAddr myAddr;
ATOMICSOCKETOP( iSocket.LocalName(myAddr), return KErrBadHandle )
TUint32 myIP = myAddr.Address();
if (myIP == 0)
{
return KErrGeneral;
}
ifreq *ifr = (ifreq *)aParam;
((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr = myIP;
return KErrNone;
}
TInt CSocketDesc :: GetRemoteIpAddress( void *aParam )
{
TInetAddr remoteAddr;
ATOMICSOCKETOP( iSocket.RemoteName(remoteAddr), return KErrBadHandle )
TUint32 remoteIP = remoteAddr.Address();
if (remoteIP == 0)
{
return KErrGeneral;
}
ifreq *ifr = (ifreq *)aParam;
((struct sockaddr_in *)&ifr->ifr_dstaddr)->sin_addr.s_addr = remoteIP;
return KErrNone;
}
TInt CSocketDesc :: GetInterafceNumber( void *aParam )
{
TInt count = 0;
TInt ret = KErrNone;
TRAP(ret, AccessPointCountL(count));
*(TInt *)aParam = count;
return ret;
}
#ifdef __SYMBIAN_COMPILE_UNUSED__
TInt CSocketDesc :: GetInterafceParamInfo( void *aParam,TInt aType)
{
TInt ret = KErrNone;
TAccessPointRecord tempRecord;
ifreq *ifr = (ifreq *)aParam;
TRAP(ret,FindConnectionInfoL(tempRecord,ifr->ifr_name));
if(ret != KErrNone)
return ret;
wchar_t *str = (wchar_t *)( tempRecord.iServiceType.PtrZ());
TInt servFlag = 0;
if(WcsCmp(str,L"LANService") == 0)
{
servFlag = 0;
}
else if(WcsCmp(str,L"OutgoingGPRS") == 0)
{
servFlag = 1;
}
if(aType == EACCESS_GETMETRIC)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETMETRIC);
}
else if(aType == EACCESS_GETMTU)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETMTU);
}
else if(aType == EACCESS_GETNETMASK)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETNETMASK);
}
else if(aType == EACCESS_GETBROADCAST)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETBROADCAST);
}
else if(aType == EACCESS_GETPHYSADDR)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETPHYSADDR);
}
else if(aType == EACCESS_GETFLAGS)
{
ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETFLAGS);
}
return ret;
}
TInt CSocketDesc :: SetInterafceParamInfo( void *aParam,TInt aType)
{
TInt ret = KErrNone;
TAccessPointRecord tempRecord;
ifreq *ifr = (ifreq *)aParam;
TRAP(ret,FindConnectionInfoL(tempRecord,ifr->ifr_name));
if(ret != KErrNone)
return ret;
wchar_t *str = (wchar_t *)(tempRecord.iServiceType.PtrZ());
TInt servFlag = 0;
if(WcsCmp(str,L"LANService") == 0)
{
servFlag = 0;
}
else if(WcsCmp(str,L"OutgoingGPRS") == 0)
{
servFlag = 1;
}
if(aType == EACCESS_SETMETRIC)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETMETRIC);
}
else if(aType == EACCESS_SETMTU)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETMTU);
}
else if(aType == EACCESS_SETFLAGS)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETFLAGS);
}
else if(aType == EACCESS_SETPHYSADDR)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETPHYSADDR);
}
else if(aType == EACCESS_SETNETMASK)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETNETMASK);
}
else if(aType == EACCESS_SETBROADCAST)
{
ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETBROADCAST);
}
return ret;
}
void CSocketDesc::FindConnectionInfoL(TAccessPointRecord &aRecord,char *ptr)
{
//TAccessPointRecord tempRecord;
CCommsDatabase* iapDatabase;
CCommsDbTableView* view;
TInt res;
TPtrC8 tptr((TText8*)ptr);
TBuf<KCommsDbSvrMaxColumnNameLength> temp;
res = CnvUtfConverter::ConvertToUnicodeFromUtf8(temp, tptr);
if(res < KErrNone)
{
User::Leave(res);
}
else if(res > KErrNone)
{
User::Leave(KErrOverflow);
}
// This function can leave on insufficient memory
OpenIapTableLC(&iapDatabase, &view);
res = view->GotoFirstRecord();
while (res == KErrNone)
{
// On error continue with the next record
TRAP( res,ReadRecordFromIapTableL(view, aRecord));
if (res == KErrNone)
{
if(WcsCmp ((wchar_t*)aRecord.iName.PtrZ(),(wchar_t*)temp.PtrZ()) == 0)
break;
}
res = view->GotoNextRecord();
}
CleanupStack::PopAndDestroy();// view
CleanupStack::PopAndDestroy(iapDatabase);
return;
}
TInt CSocketDesc :: SetInterfaceDetails( void *aParam ,TInt aFlag, TInt aType )
{
ifreq *ifr = (ifreq *)aParam;
TPckgBuf<TSoInetIfQuery> ifq;
TBuf8 <25> ipBuf8;
TName aBuf;
TInt ret = KErrNone;
ATOMICSOCKETOP( ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle )
if (ret != KErrNone)
{
return KErrGeneral;
}
TPckgBuf<TSoInet6InterfaceInfo> info;
TSoInet6InterfaceInfo &in = info();
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
while(ret == KErrNone)
{
if(info().iName != _L("") && info().iName != _L("loop6") && info().iName != _L("loop4"))
{
TDes16& aName = info().iName;
if( ((aFlag == 0 ) && ( aName.FindC(_L("WLAN")) != KErrNotFound )) ||
((aFlag == 1) && (aName.FindC(_L("Generic")) != KErrNotFound )) )
{
switch(aType)
{
case EACCESS_SETMETRIC:
if(info().iState == EIfUp)
{
info().iSpeedMetric = ifr->ifr_metric;
}
goto setout;
case EACCESS_SETMTU:
if(info().iState == EIfUp)
{
info().iMtu = ifr->ifr_mtu ;
}
goto setout;
case EACCESS_SETNETMASK :
// Presently netmask address is NULL
if((info().iState == EIfUp) && (ifr->ifr_addr.sa_data !=NULL))
{
/*
CharToTBuf8(ifr->ifr_addr.sa_data,ipBuf8);
if (CnvUtfConverter::ConvertToUnicodeFromUtf8( aBuf,ipBuf8 ) == KErrNone)
{
ret = info().iNetMask.Input(aBuf);
}
info().iNetMask.SetAddress(INET_ADDR(255,255,255,0));
*/
return KErrNotSupported;
}
break;
case EACCESS_SETBROADCAST :
if((info().iState == EIfUp) && (ifr->ifr_broadaddr.sa_data !=NULL))
{
/*CharToTBuf8(ifr->ifr_broadaddr.sa_data,ipBuf8);
if (CnvUtfConverter::ConvertToUnicodeFromUtf8( aBuf,ipBuf8 ) == KErrNone)
{
ret = info().iBrdAddr.Input(aBuf);
}
*/
return KErrNotSupported;
}
break;
case EACCESS_SETPHYSADDR :
// Currently no imeplentation is given as KIfHasHardwareAddr is always
// set to 0 for wlan and GPRS
if(info().iFeatures&KIfHasHardwareAddr)
{
return KErrNotSupported;
}
break;
case EACCESS_SETFLAGS :
info().iFeatures = 0;
// Interface UP
if((ifr->ifr_flags & IFF_UP) && (ifr->ifr_flags & IFF_DRV_RUNNING))
{
info().iState = EIfUp;
}
else
{
info().iState = EIfDown;
}
// Loopback
if(ifr->ifr_flags & IFF_LOOPBACK)
{
info().iFeatures |= KIfIsLoopback;
}
// point to point support
if(ifr->ifr_flags & IFF_POINTOPOINT)
{
info().iFeatures |= KIfIsPointToPoint;
}
// Broadcast
if(ifr->ifr_flags & IFF_BROADCAST)
{
info().iFeatures |=KIfCanBroadcast;
}
// Multicast
if(ifr->ifr_flagshigh & IFF_MULTICAST)
{
info().iFeatures = KIfCanMulticast;
}
//these flags details are available in symbian but not used by lib layer.
/* if(info().iFeatures&KIfCanSetMTU)
if(info().iFeatures&KIfHasHardwareAddr)
if(info().iFeatures&KIfCanSetHardwareAddr) */
goto setout;
default:
break;
}
}
}
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
}
setout:
TPckgBuf<TSoInet6InterfaceInfo> changeToNew(info());
ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl,changeToNew), return KErrBadHandle )
return ret;
}
#endif // __SYMBIAN_COMPILE_UNUSED__
TInt CSocketDesc::GetInterfaceDetails( void *aParam ,TInt aFlag, TInt aType )
{
TPckgBuf<TSoInetIfQuery> ifq;
TInt ret = KErrNone;
ATOMICSOCKETOP( ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle )
if (ret != KErrNone)
{
return KErrGeneral;
}
ifreq *ifr = (ifreq *)aParam;
*(ifr->ifr_addr.sa_data) = '\0';
TPckgBuf<TSoInetInterfaceInfo> info;
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
while( ret == KErrNone)
{
if(info().iName != _L("") && info().iName != _L("loop6") && info().iName != _L("loop4"))
{
TDes16& aName = info().iName;
TName aBuf;
TBuf8<KMaxName> ipAddr;
if( ((aFlag == 0 ) && ( aName.FindC(_L("WLAN")) != KErrNotFound )) ||
((aFlag == 1) && (aName.FindC(_L("Generic")) != KErrNotFound )) )
{
switch(aType)
{
case EACTIVE_GETIP :
if((info().iState == EIfUp) && (info().iAddress.Address() != NULL))
{
if(!((info().iAddress.IsLinkLocal()) || (info().iAddress.IsSiteLocal())))
{
info().iAddress.Output(aBuf);
if (CnvUtfConverter::ConvertFromUnicodeToUtf8( ipAddr, aBuf ) == KErrNone)
{
StrlCopy(ifr->ifr_addr.sa_data,(const char *) ipAddr.PtrZ(),ipAddr.Length()+1);
}
}
}
break;
case EACCESS_GETMETRIC:
ifr->ifr_metric = 0;
if (info().iState == EIfUp)
{
ifr->ifr_metric = info().iSpeedMetric;
}
break;
case EACCESS_GETMTU:
ifr->ifr_mtu = 0;
if (info().iState == EIfUp)
{
ifr->ifr_mtu = info().iMtu;
}
break;
case EACCESS_GETNETMASK :
*(ifr->ifr_addr.sa_data) = '\0';
// Presently netmask address is NULL
if((info().iState == EIfUp) && (info().iNetMask.Address() != NULL))
{
//anAddr = info().iNetMask.Address();
info().iNetMask.Output(aBuf);
if (CnvUtfConverter::ConvertFromUnicodeToUtf8( ipAddr, aBuf ) == KErrNone)
{
StrlCopy(ifr->ifr_addr.sa_data,(const char *) ipAddr.PtrZ(),ipAddr.Length()+1);
}
}
break;
case EACCESS_GETBROADCAST :
*(ifr->ifr_broadaddr.sa_data) = '\0';
// Presently Breaodcast address is NULL
if((info().iState == EIfUp) && (info().iBrdAddr.Address() != NULL))
{
//anAddr = info().iBrdAddr.Address();
info().iBrdAddr.Output(aBuf);
if (CnvUtfConverter::ConvertFromUnicodeToUtf8( ipAddr, aBuf ) == KErrNone)
{
StrlCopy(ifr->ifr_broadaddr.sa_data,(const char *) ipAddr.PtrZ(),ipAddr.Length()+1);
}
}
break;
case EACCESS_GETPHYSADDR :
ifr->ifr_phys = 0;
// Currently no imeplentation is given as KIfHasHardwareAddr is always
// set to 0 for wlan and GPRS
if(info().iFeatures&KIfHasHardwareAddr)
{
//nada.
}
break;
case EACCESS_GETFLAGS :
ifr->ifr_flags = 0;
ifr->ifr_flagshigh=0;
// Interface UP
if(info().iState == EIfUp)
{
ifr->ifr_flags |= IFF_UP;
ifr->ifr_flags |= IFF_DRV_RUNNING;
}
// Loopback
if(info().iFeatures&KIfIsLoopback)
{
ifr->ifr_flags |= IFF_LOOPBACK;
}
// point to point support
if(info().iFeatures&KIfIsPointToPoint)
{
ifr->ifr_flags |= IFF_POINTOPOINT;
}
// Broadcast
if(info().iFeatures&KIfCanBroadcast)
{
ifr->ifr_flags |= IFF_BROADCAST;
}
// Multicast
if(info().iFeatures&KIfCanMulticast)
{
ifr->ifr_flagshigh |= ((IFF_MULTICAST & 0xff00) >> 8);
}
//these flags details are available in symbian but not used by lib layer.
/* if(info().iFeatures&KIfCanSetMTU)
if(info().iFeatures&KIfHasHardwareAddr)
if(info().iFeatures&KIfCanSetHardwareAddr) */
break;
}
}
}
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
}
return KErrNone;
}
TInt CSocketDesc::Poll(TPollMode aMode,TBool& aReadyStatus,TInt& aErrno)
{
TInt ret = maybe_reopen_socket();
if (ret != KErrNone)
{
return ret;
}
TInt status;
ATOMICSOCKETOP(ret = iSocket.GetOpt(KSOSelectPoll, KSOLSocket, status), ret = KErrBadHandle)
if (ret == KErrNone)
{
aReadyStatus = status & aMode;
}
return MapError(ret, aErrno);
}
/* The synchronous - non-blocking Poll */
TInt CSocketDesc::Poll(TUint aEvents)
{
TInt err = maybe_reopen_socket();
if (err != KErrNone)
return err;
return CSockDescBase::Poll(aEvents);
}
/* Cancel an outstanding notification request */
void CSocketDesc::CancelNotify()
{
CSockDescBase::CancelNotify();
}
TAccessPointRecord::TAccessPointRecord()
:iId(0),
iName(0),
iDialogPref(ECommDbDialogPrefDoNotPrompt),
iDirection(ECommDbConnectionDirectionUnknown),
iService(0),
iServiceType(0), // Text value
iBearer(0),
iBearerType(0), // Text value
iNetwork(0),
iNetworkWeighting(0),
iLocation(0)
{
}
inline TInt CSocketDesc::GetInterfaceList(void *aParam)
{
return GetInterface(aParam, EACCESS_POINT);
}
TInt CSocketDesc::GetInterfaceIndexByName(void *aParam)
{
ifreq *ifrQuery = (ifreq*)aParam;
ifconf ifc;
// Know how many interfaces
ifc.ifc_len = 0;
ifc.ifc_buf = NULL;
TInt ret = GetInterface(&ifc, EACCESS_POINT);
if (ret != KErrNone)
{
return ret;
}
// Allocate the memory to get the detail interface information
ifc.ifc_buf = (caddr_t)Backend()->Alloc( ifc.ifc_len);
if (ifc.ifc_buf == NULL)
{
return KErrNoMemory;
}
ret = GetInterface(&ifc, EACCESS_POINT);
if (ret != KErrNone)
{
Backend()->Free(ifc.ifc_buf);
return ret;
}
ifreq *ifr = ifc.ifc_req;
TInt ifCount = ifc.ifc_len / sizeof(ifreq);
TInt i = 0;
// We wouldn't need this if we were using a StrNcmp below
ifrQuery->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
// Search for the interface name
for (; i < ifCount; i++, ifr++)
{
if ( StrCmp(ifrQuery->ifr_name, ifr->ifr_name) == 0)
{
ifrQuery->ifr_index = ifr->ifr_index;
break;
}
}
if (i == ifCount)
{
ret = KErrNotFound;
}
Backend()->Free(ifc.ifc_buf);
return ret;
}
inline TInt CSocketDesc::GetActiveInterfaceList(void *aParam)
{
return GetInterface(aParam, EACTIVE_CONNECTION);
}
TInt CSocketDesc::GetInterface(void *aParam, TInt aType)
{
TInt ret = KErrNone;
ifconf *ifc = (ifconf*)aParam;
TInt length = (ifc->ifc_len) / sizeof(ifreq);
TInt count = 0;
// If the length is zero, fill the number of interface information
if ( length <= 0 || ifc->ifc_buf == NULL )
{
if (aType == EACCESS_POINT)
{
TRAP(ret, AccessPointCountL(count));
}
else if (aType == EACTIVE_CONNECTION)
{
ret = ActiveConnectionCount(count);
}
else
{
ret = KErrArgument;
}
if (ret == KErrNone)
{
ifc->ifc_len = sizeof(ifreq) * count;
}
return ret;
}
// length is not 0, read 'length' number of records
CArrayFixFlat<TAccessPointRecord> *apArray;
wchar_t *str;
TInt apIndex;
TInt result = KErrNone;
ifreq *ifr = ifc->ifc_req;
TInt ActiveSet = 0;
// Fixed array of 'length'
apArray = new CArrayFixFlat<TAccessPointRecord>(length);
if (apArray == NULL)
{
return KErrNoMemory;
}
if (aType == EACCESS_POINT)
{
// On return length would contain the number of access points.
TRAP(result, AccessPointListL(apArray, length));
}
else if (aType == EACTIVE_CONNECTION)
{
TRAP(ret, ret=ActiveConnectionListL(apArray, length));
if( ret == KErrNone )
{
TRAP(ret,FindConnectionDetailsL(apArray, length));
ActiveSet = 1;
}
}
if (ret != KErrNone)
{
delete apArray;
return ret;
}
for (apIndex = 0; apIndex < length; apIndex++,ifr++)
{
TAccessPointRecord& ref = (*apArray)[apIndex];
ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
TPtr8 ptr((TText8*)ifr->ifr_name, IFNAMSIZ);
ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, ref.iName);
if(ret == KErrNone)
{
if(ptr.Length() < ptr.MaxLength())
{
ptr.ZeroTerminate();
}
else
{
return KErrOverflow;
}
}
else if (ret > KErrNone)
{
return KErrOverflow;
}
else
{
return ret;
}
// Copy theinterface index
ifr->ifr_index = ref.iId;
if(ActiveSet == 1)
{
str = (wchar_t *)(ref.iServiceType.PtrZ() );
TInt servFlag = 0;
if(WcsCmp(str,L"LANService") == 0)
{
servFlag = 0;
}
else if(WcsCmp(str,L"OutgoingGPRS") == 0)
{
servFlag = 1;
}
GetInterfaceDetails(ifr,servFlag,EACTIVE_GETIP);
}
}
ifc->ifc_len = sizeof(ifreq) * apIndex;
delete apArray;
return KErrNone;
}
TInt CSocketDesc::SetInterfaceByName(void *aParam)
{
ifreq *ifr = (ifreq *)aParam;
if (!ifr)
{
return KErrArgument;
}
ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
TPtrC8 ptr((TText8*)ifr->ifr_name);
TInt ret = CnvUtfConverter::ConvertToUnicodeFromUtf8(iConnPref.iName,ptr);
if(ret > KErrNone )
{
return KErrOverflow;
}
return ret;
}
inline TInt CSocketDesc::StartInterface(void *aParam)
{
return StartConnection(aParam);
}
inline TInt CSocketDesc::StartActiveInterface(void *aParam)
{
return StartSubConnection(aParam);
}
TInt CSocketDesc::StopInterface(void *)
{
if (iConnectionPtr != NULL)
{
StopConnection();
return KErrNone;
}
else if (iSubConnectionPtr != NULL)
{
StopSubConnection();
return KErrNone;
}
return KErrNotFound;
}
TInt CSocketDesc::OpenUsingPreference()
{
TInt ret = 0;
// Update when supporting INET6
TInt addrfamily = (iAddrFamily == AF_INET6 ? KAfInet : iAddrFamily);
if (iConnectionPtr != NULL) // iConnection initialized
{
ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,iConnection);
}
else if (iSubConnectionPtr != NULL) // iSubConnection initialized
{
ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,iSubConnection);
}
else
{
RConnection& defConnection = Backend()->GetDefaultConnection();
//Now check if the default connection is intialized. This is given lesser
//priority than the socket specific preferences checked above.
if(defConnection.SubSessionHandle() != 0)
{
ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,defConnection);
if (!ret)
{
Backend()->AddSocket(this);
}
}
else // No connection preference is set
{
ret = ECONNABORTED;
}
}
if (ret == KErrNone)
{
__e32_atomic_store_rel32(&iSocketPtr, (unsigned long)&iSocket);
}
iConnectInProgress = EFalse;
return ret;
}
void CSocketDesc::TempClose()
{
TUint32 ret = __e32_atomic_ior_ord32((void *)&iCount,0x8000);
if( ret >= 0x8000 )
{
// This indicates a TempClose has already been done from one of the threads
return;
}
// loop and yeild till no more references are held to the iSocket
while( iCount != 0x8000 )
{
// Yeild for 1 ms
User::After(1000);
}
if (iSocket.SubSessionHandle() != 0)
{
iSocketPtr = NULL;
iSocket.CancelAll();
TRequestStatus status;
iSocket.Shutdown(RSocket::EImmediate, status);
User::WaitForRequest(status);
iSocket.Close();
}
}
void CSocketDesc::AccessPointListL(CArrayFixFlat<TAccessPointRecord> *&aRecordPtr,
TInt &aCount)
{
TAccessPointRecord tempRecord;
CCommsDatabase* iapDatabase;
CCommsDbTableView* view;
// This function can leave on insufficient memory
OpenIapTableLC(&iapDatabase, &view);
TInt count = 0;
TInt ret = view->GotoFirstRecord();
while (ret == KErrNone && count < aCount)
{
TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
if (ret == KErrNone)
{
aRecordPtr->AppendL(tempRecord);
count++;
}
ret = view->GotoNextRecord();
}
CleanupStack::PopAndDestroy();// view
CleanupStack::PopAndDestroy(iapDatabase);
aCount = aRecordPtr->Count();
}
void CSocketDesc::FindConnectionDetailsL(CArrayFixFlat<TAccessPointRecord> *&aRecordPtr,
TInt &aCount)
{
TAccessPointRecord tempRecord;
CCommsDatabase* iapDatabase;
CCommsDbTableView* view;
// This function can leave on insufficient memory
OpenIapTableLC(&iapDatabase, &view);
TInt count = 0;
TInt ret = view->GotoFirstRecord();
while (ret == KErrNone && count < aCount)
{
TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
if (ret == KErrNone)
{
if((*aRecordPtr)[count].iId == tempRecord.iId )
{
(*aRecordPtr)[count].iServiceType = tempRecord.iServiceType;
ret = view->GotoFirstRecord();
count++;
continue;
}
ret = view->GotoNextRecord();
}
}
CleanupStack::PopAndDestroy();// view
CleanupStack::PopAndDestroy(iapDatabase);
aCount = aRecordPtr->Count();
}
void CSocketDesc::AccessPointCountL(TInt &aCount)
{
CCommsDatabase* iapDatabase;
CCommsDbTableView* view;
OpenIapTableLC(&iapDatabase, &view);
aCount = 0;
TInt ret = view->GotoFirstRecord();
while(ret == KErrNone)
{
aCount++;
ret = view->GotoNextRecord();
}
CleanupStack::PopAndDestroy();// view
CleanupStack::PopAndDestroy(iapDatabase);
}
void CSocketDesc::ReadRecordFromIapTableL(CCommsDbTableView* aView, TAccessPointRecord &aRecord)
{
aView->ReadUintL(TPtrC(COMMDB_ID), aRecord.iId);
aView->ReadTextL(TPtrC(COMMDB_NAME), aRecord.iName);
aRecord.iDialogPref = ECommDbDialogPrefDoNotPrompt;
aView->ReadUintL(TPtrC(IAP_SERVICE), aRecord.iService);
aView->ReadTextL(TPtrC(IAP_SERVICE_TYPE), aRecord.iServiceType);
aView->ReadUintL(TPtrC(IAP_BEARER), aRecord.iBearer);
/*
* IAP_BEARER_TYPE is not a column of IAP table even though its
* listed in header. So not trying to read it.
*/
aView->ReadUintL(TPtrC(IAP_NETWORK), aRecord.iNetwork);
aView->ReadUintL(TPtrC(IAP_NETWORK_WEIGHTING), aRecord.iNetworkWeighting);
aView->ReadUintL(TPtrC(IAP_LOCATION), aRecord.iLocation);
}
void CSocketDesc::OpenIapTableLC(CCommsDatabase **aIapDatabase, CCommsDbTableView **aView)
{
// Get IAP names and ids from the database
*aIapDatabase = CCommsDatabase::NewL(EDatabaseTypeIAP);
CleanupStack::PushL(*aIapDatabase);
(*aIapDatabase)->ShowHiddenRecords();
// This is LC code, that means code has pushed, but not popped
(*aView) = (*aIapDatabase)->OpenTableLC(TPtrC(IAP));
}
inline TInt CSocketDesc::ActiveConnectionCount(TInt &aCount)
{
aCount = ((CFileTable*)iFids)->RConnectionCount();
return KErrNone;
}
TInt CSocketDesc::ActiveConnectionListL(CArrayFixFlat<TAccessPointRecord> *aRecordPtr, TInt &aLength)
{
TInt rcIndex;
RConnection *rc;
TAccessPointRecord tempRecord;
for (rcIndex = 0;rcIndex < aLength; rcIndex++)
{
if ( ((CFileTable*)iFids)->RConnectionAt(rcIndex, rc) != KErrNone )
{
break;
}
// Read index and name of the connection
if ( GetRConnectionDetails(rc, tempRecord) != KErrNone )
{
break;
}
aRecordPtr->AppendL(tempRecord);
}
aLength = aRecordPtr->Count();
return KErrNone;
}
TInt CSocketDesc::GetRConnectionDetails(RConnection *aRc, TAccessPointRecord &aApr)
{
_LIT(KName, "IAP\\Name");
_LIT(KId, "IAP\\Id");
TInt ret = aRc->GetDesSetting(KName, aApr.iName);
if (ret == KErrNone)
{
ret = aRc->GetIntSetting(KId, aApr.iId);
}
return ret;
}
TInt CSocketDesc::StartConnection(void * /* ptr */)
{
if (iConnectionPtr != NULL)
{
return KErrAlreadyExists;
}
TCommDbConnPref connPref;
TInt ret = GetConnectionPreference(connPref);
if (ret != KErrNone)
{
return ret;
}
ret = iConnection.Open(*iSockServPtr);
if (ret != KErrNone)
{
return ret;
}
ret = iConnection.Start(connPref);
if (ret != KErrNone)
{
iConnection.Close();
return ret;
}
iConnectionPtr = &iConnection;
ret = ((CFileTable*)iFids)->AddRConnectionPtr(iConnectionPtr, iRConnectionIndex);
if (ret != KErrNone)
{
iConnection.Close();
iConnectionPtr = NULL;
}
return ret;
}
TInt CSocketDesc::GetConnectionPreference(TCommDbConnPref &aCommPref)
{
if (iConnPref.iName.Length() == 0)
{
return KErrArgument;
}
TAccessPointRecord apr;
TInt ret;
// Connection preference is set
TRAP(ret, GetIapDetailsByNameL(iConnPref.iName, apr));
if (ret == KErrNone)
{
aCommPref.SetIapId(apr.iId);
aCommPref.SetNetId(apr.iNetwork);
aCommPref.SetBearerSet(apr.iBearer);
aCommPref.SetDialogPreference((TCommDbDialogPref)apr.iDialogPref);
aCommPref.SetDirection((TCommDbConnectionDirection)apr.iDirection);
}
return ret;
}
void CSocketDesc::GetIapDetailsByNameL(
TBuf<KCommsDbSvrMaxColumnNameLength> aIapName,
TAccessPointRecord &aRecord)
{
TAccessPointRecord tempRecord;
CCommsDatabase* iapDatabase;
CCommsDbTableView* view;
TInt ret = KErrNotFound;
OpenIapTableLC(&iapDatabase, &view);
ret = view->GotoFirstRecord();
while (ret == KErrNone)
{
TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
if (ret == KErrNone)
{
if (aIapName == tempRecord.iName)
{
aRecord = tempRecord;
ret = KErrNone;
break;
}
}
ret = view->GotoNextRecord();
}
CleanupStack::PopAndDestroy();// view
CleanupStack::PopAndDestroy(iapDatabase);
if (ret != KErrNone)
{
User::Leave(KErrNotFound);
}
}
void CSocketDesc::StopConnection()
{
iConnection.Close();
iConnectionPtr = NULL;
((CFileTable*)iFids)->RemoveRConnectionPtrAt(iRConnectionIndex);
iRConnectionIndex = -1;
}
void CSocketDesc::StopSubConnection()
{
iSubConnection.Close();
iSubConnectionPtr = NULL;
}
TInt CSocketDesc::StartSubConnection(void *)
{
if (iSubConnectionPtr != NULL)
{
return KErrAlreadyExists;
}
TInt ret = KErrArgument;
TInt rcIndex = 0;
RConnection *rc;
TAccessPointRecord record;
do
{
if (((CFileTable*)iFids)->RConnectionAt(rcIndex, rc) != KErrNone)
{
break;
}
// Read index and name of the connection
GetRConnectionDetails(rc, record);
if (record.iName == iConnPref.iName)
{
ret = KErrNone; // RConnection found
break;
}
rcIndex++;
}
while (ETrue); //Loop over all active connections
if (ret == KErrNone)
{
ret = iSubConnection.Open(*iSockServPtr, RSubConnection::EAttachToDefault, *rc);
if (ret == KErrNone)
{
iSubConnectionPtr = &iSubConnection;
}
}
return ret;
}
inline void CSocketDesc::SetFids(void *aFids)
{
iFids = aFids;
}
//Add an entry in the interface routing table
TInt CSocketDesc::RouteRequest(TInt aReq, void *aParam)
{
struct rtentry* rt=reinterpret_cast<struct rtentry*>(aParam);
if (!rt)
{
return KErrArgument;
}
TInt ret;
TPckgBuf<TSoInetRouteInfo>iroute;
iroute().iType=ERtNormal;
iroute().iState=ERtReady;
iroute().iMetric=rt->rt_metric;
if (rt->rt_dev)
{
TPckgBuf<TSoInetInterfaceInfo> iface;
TFileName name;
name.Copy(TPtrC8((TText8*)rt->rt_dev));
if((ret=GetInterfaceByName(name, iface)) != KErrNone)
return ret;
Copy(iroute().iIfAddr, iface().iAddress);
ConvertRtEntry(iroute(), rt);
//add the entry
ATOMICSOCKETOP( ret = iSocket.SetOpt(aReq, KSolInetRtCtrl, iroute),return KErrBadHandle )
return ret;
}
return KErrUnknown;
}
TInt CSocketDesc::Copy(TInetAddr& aDest, TInetAddr& aSrc)
{
if (aSrc.IsV4Mapped() || aSrc.IsV4Compat())
{
aSrc.ConvertToV4();
}
aDest.SetAddress(aSrc.Address());
aDest.SetFamily(aSrc.Family());
aDest.SetPort(aSrc.Port());
return KErrNone;
}
TInt CSocketDesc::ConvertSockAddr(TInetAddr& aInetAddr, struct sockaddr_in *aSockAddr)
{
if (aSockAddr == NULL)
{
return KErrArgument;
}
//convert the address and port from network to host byte order...
aInetAddr.SetAddress(ByteOrder::Swap32(aSockAddr->sin_addr.s_addr));
aInetAddr.SetFamily(aSockAddr->sin_family);
aInetAddr.SetPort(ByteOrder::Swap16(aSockAddr->sin_port));
return KErrNone;
}
TInt CSocketDesc::ConvertRtEntry(TSoInetRouteInfo& aRouteInfo, struct rtentry *aRouteEntry)
{
if(aRouteEntry == NULL)
{
return KErrArgument;
}
ConvertSockAddr(aRouteInfo.iDstAddr, (struct sockaddr_in *)&aRouteEntry->rt_dst);
ConvertSockAddr(aRouteInfo.iNetMask, (struct sockaddr_in *)&aRouteEntry->rt_genmask);
ConvertSockAddr(aRouteInfo.iGateway, (struct sockaddr_in *)&aRouteEntry->rt_gateway);
return KErrNone;
}
TInt CSocketDesc::GetInterfaceByName(const TDesC& aIfName, TPckgBuf<TSoInetInterfaceInfo>& aIface)
{
TInt ret = KErrNone;
ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle)
if (ret != KErrNone)
{
return ret;
}
TPckgBuf<TSoInetInterfaceInfo> iface;
ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle)
while(ret == KErrNone)
{
if (!iface().iAddress.IsUnspecified() && iface().iName.CompareF(aIfName) == 0)
{
aIface = iface;
return ret;
}
ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
}
return KErrUnknown;
}
TInt CSocketDesc::GetInterfaceHWAddress(void *aParam)
{
ifreq *ifr = reinterpret_cast<ifreq *>(aParam);
if (!ifr)
{
return KErrArgument;
}
if (ifr->ifr_name[0] != '\0')
{
TPckgBuf<TSoInetInterfaceInfo> iface;
TFileName name;
ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
name.Copy(TPtrC8((TText8*)ifr->ifr_name));
TInt ret = GetInterfaceByName(name, iface);
if (ret != KErrNone)
return ret;
if (iface().iHwAddr.Length() > sizeof(SSockAddr))
{
Mem::Copy(&(ifr->ifr_hwaddr.sa_data[0]),&(iface().iHwAddr[sizeof(SSockAddr)]), 6);
ifr->ifr_hwaddr.sa_family = (TUint16)iface().iHwAddr.Family();
ifr->ifr_hwaddr.sa_port = ByteOrder::Swap16(iface().iHwAddr.Port());
return ret;
}
}
return KErrUnknown;
}
//This function retrieves the Currently active IAP ID using the RSocket Query.
//First get the interface index of the active connection using KSoInterfaceIndex
//Then with the help of the interface index, fetch the TSoInetIfQuery, under which iZone
//will contain the snap id. User is supposed to call if_indextoname() api to get the IAP name
//from the ID retured with this Ioctl implementation.
TInt CSocketDesc::GetActiveInterface( void *aParam)
{
TInt ifindex = -1;
TInt ret = KErrNone;
ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInterfaceIndex, KSolInetIp , ifindex), ret = KErrBadHandle)
if(ret!=KErrNone)
{
return ret;
}
TPckgBuf<TSoInetIfQuery> opt;
opt().iIndex = ifindex;
ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetIfQueryByIndex, KSolInetIfQuery, opt), ret = KErrBadHandle)
if(ret!=KErrNone)
{
return ret;
}
ifreq *ifr = (ifreq * )aParam;
ifr->ifr_index = opt().iZone[1]; //IAP_ID
return KErrNone;
}