genericopenlibs/openenvcore/backend/src/corebackend/ufilesocket.cpp
changeset 0 e4d67989cc36
child 18 47c74d1534e1
child 33 6896b031c3e1
--- /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;
+	}
+