--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/backend/src/corebackend/ufilesocket.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,602 @@
+// Copyright (c) 2008-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:
+// conv.CPP
+// Descrpition: This file implements the functions for local socket(AF_LOCAL, PF_LOCAL, AF_UNIX)
+//
+//
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <utf.H>
+#include "fdesc.h"
+#include "systemspecialfilercg.h"
+#include "lposix.h"
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Socket
+// Creates socket using RSocket::Open
+// -----------------------------------------------------------------------------
+//
+
+TInt CFileSocketDesc::Socket(RSocketServ& aSs, int /*aFamily*/, int aStyle, int aProtocol)
+ {
+ if(aProtocol == 0)
+ {
+ switch (aStyle)
+ {
+ case SOCK_STREAM:
+ aProtocol = IPPROTO_TCP;
+ break;
+
+ case SOCK_DGRAM:
+ aProtocol = IPPROTO_UDP;
+ break;
+
+ default:
+ aProtocol = KUndefinedProtocol;
+ }
+ }
+
+ iFcntlFlag = 0;
+ iStyle = aStyle;
+ iProtocol = aProtocol;
+ TInt err = CreateLock();
+ if (err)
+ {
+ return err;
+ }
+
+ err = iSocket.Open(aSs, KAfInet, aStyle, aProtocol);
+ return err;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Bind
+// Binds the socket to path provided in the aAddr
+// Creates a filesystem entry for the path, binds iSocket to a loopback address and
+// registers the address with ipc server.
+//
+// -----------------------------------------------------------------------------
+
+TInt CFileSocketDesc::Bind(const struct sockaddr* aAddr, unsigned long aSize)
+ {
+ struct SSpecialFileMagicHeader enBuf;
+ int err;
+ const wchar_t* wspath = NULL;
+ if(aSize == NULL)
+ {
+ return EINVAL;
+ }
+
+ sockaddr_un* addr = (sockaddr_un*)aAddr;
+ if((err=ValidateAddress(addr,&aSize)) != KErrNone)
+ {
+ return err;
+ }
+ if (iPath.Length() != 0)
+ {
+ //Already bound condition
+ return EINVAL;
+ }
+
+ err = _EncodeSystemSplFileMagicHeader(&enBuf, EFileTypeSocket);
+ if (err != 0)
+ {
+ return err;
+ }
+
+ TPtrC8 sunpath((TUint8 *)addr->sun_path);
+ TFileName fname16;
+ err = CnvUtfConverter::ConvertToUnicodeFromUtf8(fname16, sunpath);
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ wspath = (const wchar_t*)(fname16.PtrZ());
+
+ TInt errorNum;
+ err = _CreateSysSplFile(wspath, (char*)&enBuf, sizeof(struct SSpecialFileMagicHeader), errorNum, Backend()->FileSession());
+ if (err != KErrNone)
+ {
+ if (errorNum == EEXIST)
+ {
+ err = EADDRINUSE;
+ }
+ return err;
+ }
+
+ TFileName fullpathName;
+ err=GetFullFile(fullpathName,(const TText16*)wspath,Backend()->FileSession());
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ err = CnvUtfConverter::ConvertFromUnicodeToUtf8(iPath, fullpathName);
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ TInetAddr inetAddr(KInetAddrLoop,0);
+ err = iSocket.Bind(inetAddr);
+ if(err != KErrNone)
+ {
+ iPath.Zero();
+ return err;
+ }
+ TUint portNum = iSocket.LocalPort();
+ if(KErrNone == err)
+ {
+ err = Backend()->iIpcS.RegisterSockAddrWithIPCSvr(iPath,portNum);
+ if(KErrNone != err)
+ {
+ iPath.Zero();
+ return err;
+ }
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Accept
+// Accepts connections from clients
+// -----------------------------------------------------------------------------
+//
+
+void CFileSocketDesc::Accept(CFileDescBase*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs, TSockAddr *)
+ {
+ TAutoFastLock lock(iReadLock);
+ if (iStyle == SOCK_DGRAM) // Listen on UDP socket, crashing at RSocket::Listen().
+ {
+ Complete(aStatus,KErrNotSupported);
+ return;
+ }
+
+ //coverity[alloc_fn]
+ //coverity[assign]
+ CFileSocketDesc *newSocket = new CFileSocketDesc;
+ TInt err=KErrNone;
+ if (newSocket!=0)
+ {
+ err = newSocket->CreateLock();
+ if (err)
+ {
+ Complete(aStatus, KErrNoMemory);
+ delete newSocket;
+ aNewSocket = NULL;
+ //coverity[memory_leak]
+ return;
+ }
+
+ err=newSocket->iSocket.Open(aSs);
+ }
+ if (newSocket ==0 || err!=KErrNone)
+ {
+ Complete(aStatus,KErrNoMemory);
+ delete newSocket;
+ aNewSocket = NULL;
+ //coverity[memory_leak]
+ return;
+ }
+
+ newSocket->iStyle = iStyle;
+ newSocket->iProtocol = iProtocol;
+ iSocket.Accept(newSocket->iSocket,aStatus);
+ aNewSocket = newSocket;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::AcceptCancel
+// Cancels the accept request
+// -----------------------------------------------------------------------------
+//
+void CFileSocketDesc::AcceptCancel()
+ {
+ iSocket.CancelAccept();
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Connect
+// Gets the local socket port number from the IPCs and connects to that port
+// -----------------------------------------------------------------------------
+//
+void CFileSocketDesc::Connect(const struct sockaddr* addr, unsigned long size,TRequestStatus& aStatus)
+ {
+ TUint portNo,ret;
+
+ if((ret = GetLocalSockPortByPath((sockaddr_un*)addr,size,portNo)) != KErrNone)
+ {
+ aStatus = ret;
+ return;
+ }
+ TInetAddr sAddr(KInetAddrLoop,portNo);
+ iSocket.Connect(sAddr,aStatus);
+ User::WaitForRequest(aStatus);
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::ConnectCancel
+// Cancels the connect request
+// -----------------------------------------------------------------------------
+//
+void CFileSocketDesc::ConnectCancel()
+ {
+ iSocket.CancelConnect();
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Listen
+// Sets up the listen buffer
+// -----------------------------------------------------------------------------
+//
+TInt CFileSocketDesc::Listen(TUint qSize)
+ {
+ if (iStyle == SOCK_DGRAM) // Listen on UDP socket, crashing at RSocket::Listen().
+ {
+ return EOPNOTSUPP;
+ }
+ return CSockDescBase::Listen(qSize);
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Write
+//
+// -----------------------------------------------------------------------------
+
+void CFileSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
+ {
+ //Acquire the Lock before write and release it later
+ TAutoFastLock lock(iWriteLock);
+ CSockDescBase::Write(aBuf,aStatus);
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Read
+//
+// -----------------------------------------------------------------------------
+
+void CFileSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
+ {
+ //Acquire the Lock before read and release it later
+ TAutoFastLock lock(iReadLock);
+ CSockDescBase::Read(aBuf,aStatus);
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::RecvFrom
+//
+// -----------------------------------------------------------------------------
+
+void CFileSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& AFrom, int aFlags, TRequestStatus& aStatus)
+ {
+ TAutoFastLock lock(iReadLock);
+ CSockDescBase::RecvFrom(aDesc, AFrom, aFlags, aStatus);
+ return;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::SendTo
+//
+// -----------------------------------------------------------------------------
+
+void CFileSocketDesc::SendTo(TDes8& aDesc, const struct sockaddr* aToAddr, unsigned long aAddrLen,int aFlags, TRequestStatus& aStatus)
+ {
+ TAutoFastLock lock(iWriteLock);
+
+ if(iStyle == SOCK_DGRAM)
+ {
+ TUint portNo;
+ TInt ret;
+ if((ret = GetLocalSockPortByPath((sockaddr_un*)aToAddr,aAddrLen,portNo)) != KErrNone)
+ {
+ Complete(aStatus,ret);
+ return;
+ }
+ TInetAddr sAddr(KInetAddrLoop,portNo);
+ CSockDescBase::SendTo(aDesc, sAddr, aFlags, aStatus);
+ return;
+ }
+
+ TUSockAddr addr(NULL,0);
+ CSockDescBase::SendTo(aDesc, addr, aFlags, aStatus);
+ return;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::Ioctl
+// Not supported as of now.
+// -----------------------------------------------------------------------------
+
+void CFileSocketDesc::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus)
+ {
+ Complete(aStatus, KErrNotSupported);
+ return;
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::FinalClose
+//
+// -----------------------------------------------------------------------------
+
+TInt CFileSocketDesc::FinalClose()
+ {
+ RemoveLocalSockAddr();
+ RHeap* oheap = User::SwitchHeap(Backend()->Heap());
+ CSockDescBase::FinalClose();
+ User::SwitchHeap(oheap);
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::GetSockOpt
+// Get the socket option
+// -----------------------------------------------------------------------------
+TInt CFileSocketDesc::GetSockOpt(TInt anOptionName,TInt anOptionLevel,TDes8& anOption)
+ {
+ if (anOption.Ptr() == NULL)
+ {
+ return EFAULT;
+ }
+ if (anOption.Length() == 0)
+ {
+ return EINVAL;
+ }
+ if(anOptionLevel != SOL_SOCKET)
+ {
+ return KErrNotSupported;
+ }
+ switch(anOptionName)
+ {
+ case SO_TYPE:
+ TInt size;
+ size = (anOption.MaxLength() < sizeof(iStyle))? anOption.MaxLength(): sizeof(iStyle);
+ Mem::Copy((unsigned char*)anOption.Ptr(), &iStyle, size);
+ anOption.SetLength(size);
+ return KErrNone;
+ case SO_KEEPALIVE:
+ anOptionLevel=SOL_TCP;
+ break;
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ break;
+ default:
+ return KErrNotSupported;
+ }
+
+ return iSocket.GetOpt(anOptionName,anOptionLevel,anOption);
+
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::SetSockOpt
+// Set the socket option
+// -----------------------------------------------------------------------------
+
+TInt CFileSocketDesc::SetSockOpt(TInt anOptionName,TInt anOptionLevel,TDesC8& anOption)
+ {
+ if (anOption.Ptr() == NULL)
+ {
+ return EFAULT;
+ }
+ if (anOption.Length() == 0)
+ {
+ return EINVAL;
+ }
+ if(anOptionLevel != SOL_SOCKET)
+ {
+ return KErrNotSupported;
+ }
+ switch(anOptionName)
+ {
+ case SO_KEEPALIVE:
+ if(iStyle == SOCK_STREAM)
+ {
+ anOptionLevel=SOL_TCP;
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+ break;
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ break;
+ default:
+ return KErrNotSupported;
+ }
+
+ return iSocket.SetOpt(anOptionName,anOptionLevel,anOption);
+
+ }
+
+// ---------------------------------------------------------------------------------
+// CFileSocketDesc::SockName
+// Fetches the local socket address.
+// ---------------------------------------------------------------------------------
+//
+TInt CFileSocketDesc::SockName(int anEnd, struct sockaddr* aAddr,unsigned long* aAddrLen)
+ {
+ TInt ret = KErrNone;
+ TUSockAddr lSockAddr;
+ if(anEnd == 0)
+ {
+ TInt ret;
+ if((ret = ValidateAddress((sockaddr_un*)aAddr,aAddrLen)) != KErrNone)
+ {
+ if ( ( ret == EINVAL ) && (aAddrLen != 0))
+ {
+ // since the length passed is less than the first field but greater than 0 i.e sun_family we dont need to fill any field into aAddr structure passed.
+ return KErrNone;
+ }
+ return ret;
+ }
+ struct sockaddr_un* addr = (struct sockaddr_un*)aAddr;
+ TInt buflen = *aAddrLen - (sizeof(addr->sun_family) + sizeof(addr->sun_len));
+ addr->sun_family = AF_UNIX;
+ *aAddrLen = sizeof(addr->sun_family);
+
+ if(iPath.Length() && buflen > 1)
+ {
+ TPtr8 sockPath((TText8*)(addr->sun_path),buflen);
+ sockPath.Copy(iPath.Left(buflen-1));
+ sockPath.ZeroTerminate();
+ *aAddrLen = sizeof(addr->sun_family) + sockPath.Length() + 1; //+1 for NULL character
+ }
+ else if (buflen == 1)
+ {
+ addr->sun_path[0] = '\0';
+ }
+ return KErrNone;
+ }
+ else
+ {
+
+ ret = CSockDescBase::SockName(anEnd,lSockAddr);
+ if( ret == EFAULT )
+ return ret;
+
+ struct sockaddr_un* addr = (struct sockaddr_un*)aAddr;
+ // If the length passed is greater than or equal to 0 but less than the first field i.e sun_family , return kErrnone and dont fill any field into aAddr structure passed.
+ if( (aAddrLen != 0) && (*aAddrLen < sizeof(addr->sun_family)) )
+ {
+ return KErrNone;
+ }
+
+ if(ret == KErrNone)
+ {
+ ret = GetLocalSockAddrByPort((sockaddr_un*)aAddr,aAddrLen,lSockAddr.Port());
+ }
+ }
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------------
+// CFileSocketDesc::ValidateAddress
+// Utility function to check the validity of the socket address.
+// ---------------------------------------------------------------------------------
+//
+TInt CFileSocketDesc::ValidateAddress(const struct sockaddr_un* aAddr,unsigned long* aAddrLen)
+ {
+ if (aAddr == NULL)
+ {
+ return EFAULT;
+ }
+ if (aAddrLen == 0)
+ {
+ return EINVAL;
+ }
+ if( *aAddrLen < sizeof(aAddr->sun_family) )
+ {
+ return EINVAL;
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------------
+// CFileSocketDesc::GetLocalSockAddrByPort
+// Gets the file socket address associated with the port by querying the IPC server.
+// ---------------------------------------------------------------------------------
+//
+TInt CFileSocketDesc::GetLocalSockAddrByPort(struct sockaddr_un* aAddr,unsigned long* aAddrLen,TUint aPortNum)
+ {
+ TInt ret;
+ if((ret = ValidateAddress(aAddr,aAddrLen)) != KErrNone)
+ {
+ return ret;
+ }
+
+
+ TInt buflen = *aAddrLen - (sizeof(aAddr->sun_family) + sizeof(aAddr->sun_len));
+ TInt err;
+
+ aAddr->sun_family = AF_UNIX;
+ *aAddrLen = sizeof(aAddr->sun_family);
+ if(buflen > 1)
+ {
+ TPtr8 sockPath((TText8*)aAddr->sun_path,buflen-1);
+ if((err=Backend()->iIpcS.GetLocalSockAddrByPort(sockPath,aPortNum)) != KErrNone)
+ {
+ sockPath.ZeroTerminate();
+ *aAddrLen = 0;
+ return err;
+ }
+
+ aAddr->sun_path[sockPath.Length()] = '\0';
+ *aAddrLen = sizeof(aAddr->sun_family) + sockPath.Length() + 1; //+1 for NULL character
+ return KErrNone;
+ }
+ else if (buflen == 1)
+ {
+ aAddr->sun_path[0] = '\0';
+ }
+
+ return KErrNone;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::GetLocalSockPortByPath
+// Queries the IPC server to get the port associated with the path
+// -----------------------------------------------------------------------------
+
+TInt CFileSocketDesc::GetLocalSockPortByPath(const struct sockaddr_un* aAddr,unsigned long aAddrLen,TUint& aPortNum)
+ {
+ TInt err;
+ if((err = ValidateAddress(aAddr,&aAddrLen)) != KErrNone)
+ {
+ return err;
+ }
+
+ TInt buflen = aAddrLen - (sizeof(aAddr->sun_family) + sizeof(aAddr->sun_len));
+
+ if(buflen <= 1)
+ {
+ return EINVAL;
+ }
+
+ TBuf8<KMaxFileName> fullname;
+ err = GetFullFileUtf8(fullname, aAddr->sun_path, Backend()->FileSession());
+
+ return Backend()->iIpcS.GetLocalSockPortByPath(fullname, aPortNum);
+ }
+
+// -----------------------------------------------------------------------------
+// CFileSocketDesc::RemoveLocalSockAddr
+// Removes the local socket address from the IPCServer
+// -----------------------------------------------------------------------------
+
+TInt CFileSocketDesc::RemoveLocalSockAddr()
+ {
+ if(iPath.Length())
+ {
+ return Backend()->iIpcS.RemLocalSockAddr(iPath);
+ }
+ return KErrNone;
+ }
+