# HG changeset patch # User William Roberts # Date 1286807865 -3600 # Node ID 37dc158a4522ec2b2e56d0eb8fd8c8b0b992b460 # Parent b1cc137d8adb0e9b6b024f0e612865a642669523 Start breaking the dependency of backend.dll on bluetooth.dll - commit copies of the original ossrv files from PDK 3.0.2 diff -r b1cc137d8adb -r 37dc158a4522 breakdeps/backend.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/backend.mmp Mon Oct 11 15:37:45 2010 +0100 @@ -0,0 +1,163 @@ +// Copyright (c) 2005-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: +// Name : backend.mmp +// Part of : backend specific include MMP file +// This is a project specific include file for building the +// backend library. +// + + + +TARGET backend.dll +TARGETTYPE dll +UID 0x1000008d 0x102828D5 + +LANG SC +CAPABILITY ALL -TCB +VENDORID 0x70000001 +VERSION 1.1 +// Macro defs +#include "../../libc/group/libcflags.mmpi" +#ifdef GCCXML +MACRO __wchar_t_defined +#endif //GCCXML + +USERINCLUDE ../inc +USERINCLUDE ../../libc/inc +USERINCLUDE ../../ewsd/inc +USERINCLUDE ../ipcserver/ipccli/inc +USERINCLUDE ../ipcserver/ipcsrv/inc + +// Illegal dependancy on tz.h in MW layer. Needs fixing +MW_LAYER_SYSTEMINCLUDE_SYMBIAN +OS_LAYER_SYSTEMINCLUDE_SYMBIAN +OS_LAYER_LIBC_SYSTEMINCLUDE + +//backend without signals and librt support +#ifndef SYMBIAN_OE_POSIX_SIGNALS +#ifdef WINSCW +DEFFILE ../bwins/old_backend.def +#else +DEFFILE ../eabi/old_backend.def +#endif +#endif + +//backend without librt support +#if (defined SYMBIAN_OE_POSIX_SIGNALS && !defined SYMBIAN_OE_LIBRT) +#ifdef WINSCW +DEFFILE ../bwins/backendwolibrt.def +#else +DEFFILE ../eabi/backendwolibrt.def +#endif +#endif + +SOURCEPATH ../inc +DOCUMENT base.dosc +DOCUMENT consolestream.dosc +DOCUMENT fdesc.dosc +DOCUMENT fdtransfermsg.dosc +DOCUMENT fdtransfer_cli.dosc +DOCUMENT fdtransfer_srv.dosc +DOCUMENT filestream.dosc +DOCUMENT link.dosc +DOCUMENT lposix.dosc +DOCUMENT ltime.dosc +DOCUMENT netdb_r.dosc +DOCUMENT readrequesthandler.dosc +DOCUMENT serialstream.dosc +DOCUMENT shutdown.dosc +DOCUMENT spawn_r.dosc +DOCUMENT stdioclient.dosc +DOCUMENT stdioserver.dosc +DOCUMENT stdiosession.dosc +DOCUMENT streambase.dosc +DOCUMENT sysif.dosc +DOCUMENT sysreent.dosc +DOCUMENT systemspecialfilercg.dosc +DOCUMENT mmap.dosc +DOCUMENT mmapcontrollernode.dosc +DOCUMENT mmapmemorynode.dosc +DOCUMENT stdio_r.dosc +DOCUMENT stdlib_r.dosc +DOCUMENT sysusrinclude.dosc + + +SOURCEPATH ../ipcserver/ipccli/inc +DOCUMENT ipcclient.dosc + +#ifndef WINSCW +EPOCALLOWDLLDATA +#endif //WINSCW + +//Main Backend codes +SOURCEPATH ../src/corebackend + +SOURCE localif.cpp posixfs.cpp +SOURCE ftable.cpp fdesc.cpp uconsole.cpp usocket.cpp +SOURCE userial.cpp upipedesc.cpp uredirdesc.cpp udirectorydesc.cpp +SOURCE utilityfuns.cpp systemspecialfilercg.cpp conv.cpp +SOURCE fdtransfer_srv.cpp fdtransfer_cli.cpp +SOURCE ufilesocket.cpp +SOURCE usocketbase.cpp + +//Syscall code +SOURCEPATH ../src/syscall + +SOURCE handlefms.cpp handlenms.cpp handlepms.cpp +#ifdef SYMBIAN_OE_POSIX_SIGNALS +SOURCE handlesms.cpp +#endif +SOURCE handleipc.cpp handlemmap.cpp +SOURCE mmapcontroller.cpp mmapmemorynode.cpp +SOURCE handlestringfuncs.cpp + +//ipcserver-client code +SOURCEPATH ../ipcserver/ipccli/src +SOURCE ipcclient.cpp + +//StdioServer-Client Code +SOURCEPATH ../src/StdioRedir/Client +SOURCE StdioClient.cpp + +#ifdef SYMBIAN_OE_POSIX_SIGNALS +//signal server client code +SOURCEPATH ../src/signalserver/client +SOURCE signalclient.cpp +#endif + +//Backend dependent Libraries + +LIBRARY euser.lib +LIBRARY commdb.lib +LIBRARY efsrv.lib +LIBRARY esock.lib +LIBRARY c32.lib +LIBRARY bluetooth.lib +LIBRARY insock.lib +LIBRARY rpipe.lib +LIBRARY charconv.lib +LIBRARY estor.lib +LIBRARY tzclient.lib + +#ifdef WINSCW +//wsd solution +LIBRARY ewsd.lib +#endif + + +PAGED +// End of File + + +SMPSAFE diff -r b1cc137d8adb -r 37dc158a4522 breakdeps/usocket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/breakdeps/usocket.cpp Mon Oct 11 15:37:45 2010 +0100 @@ -0,0 +1,2248 @@ +/* +* 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 +#include // for memcpy +#include // for struct stat +#include // for ENOTSOCK +#include +#include +#include +#include // for htons +#include +#include // Symbian BT constantss needed for cooperation with Symbian sockets +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + } + 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; isa_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; isa_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 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; + + TPckgBufiface; + 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 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(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 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 ifq; + TBuf8 <25> ipBuf8; + TName aBuf; + TInt ret = KErrNone; + ATOMICSOCKETOP( ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle ) + if (ret != KErrNone) + { + return KErrGeneral; + } + TPckgBuf 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 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 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 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 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 *apArray; + wchar_t *str; + TInt apIndex; + TInt result = KErrNone; + ifreq *ifr = ifc->ifc_req; + TInt ActiveSet = 0; + + // Fixed array of 'length' + apArray = new CArrayFixFlat(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 *&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 *&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 *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 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(aParam); + + if (!rt) + { + return KErrArgument; + } + + TInt ret; + TPckgBufiroute; + iroute().iType=ERtNormal; + iroute().iState=ERtReady; + iroute().iMetric=rt->rt_metric; + if (rt->rt_dev) + { + TPckgBuf 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& aIface) + { + TInt ret = KErrNone; + ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle) + if (ret != KErrNone) + { + return ret; + } + TPckgBuf 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(aParam); + + if (!ifr) + { + return KErrArgument; + } + + if (ifr->ifr_name[0] != '\0') + { + TPckgBuf 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 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; + }