os/ossrv/genericopenlibs/cstdlib/USTLIB/USOCKET.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // Implementation of STDLIB sockets.
    15 // 
    16 //
    17 
    18 #include "FDESC.H"
    19 #include <sys/types.h>
    20 #include <string.h>		// for memcpy
    21 #include <fcntl.h>		// for struct stat
    22 #include <sys/errno.h>		// for ENOTSOCK
    23 #include <sys/socket.h>
    24 #include <sys/ioctl.h>
    25 #include <libc/netinet/in.h>		// for htons
    26 
    27 EXPORT_C unsigned short htons(unsigned short hs)
    28 	{ return ByteOrder::Swap16(hs); }
    29 EXPORT_C unsigned long  htonl(unsigned long hl)
    30 	{ return ByteOrder::Swap32(hl); }
    31 
    32 // Support for struct sockaddr conversion
    33 
    34 TUSockAddr::TUSockAddr (TAny* aBuf) 
    35 	: TSockAddr()
    36 	{
    37 	Prepare(aBuf);
    38 	}
    39 
    40 void TUSockAddr::Prepare (TAny* aBuf) 
    41 //
    42 // Prepare a TUSockAddr to receive an address (used in RecvFrom)
    43 // Setting the length to 0 indicates that we don't really want this address anyway.
    44 //
    45 	{
    46 	if (aBuf==0)
    47 		{
    48 		SetLength(0);
    49 		return;
    50 		}
    51 	}
    52 
    53 TUSockAddr::TUSockAddr (TAny* aBuf, TUint aLen) 
    54 	: TSockAddr()
    55 	{
    56 	Set(aBuf,aLen);
    57 	}
    58 
    59 void TUSockAddr::Set (TAny* aBuf, TUint aLen) 
    60 //
    61 // Construct an ESOCK TSockAddr from a struct sockaddr.
    62 // We have to deal with the network byte ordering of AF_INET addresses
    63 //
    64 	{
    65 	if (aBuf==0)
    66 		{
    67 		SetLength(0);
    68 		return;
    69 		}
    70 	struct sockaddr* sp=(struct sockaddr*)aBuf;
    71 	TUint8 *from=(TUint8*)aBuf;
    72 	if (sp->sa_family==AF_INET)
    73 		{
    74 		// byte-swap sockaddr_in back into host ordering
    75 		TUint port=(from[2]<<8)+from[3];
    76 		from+=4;
    77 		TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
    78 		from+=4;
    79 		SetFamily(AF_INET);
    80 		SetPort(port);
    81 		*(TUint32*)UserPtr()=addr;
    82 		SetUserLen(4);
    83 		return;
    84 		}
    85 	// expand the family and port
    86 	SetFamily(sp->sa_family);
    87 	SetPort(sp->sa_port);
    88 	from+=4;
    89 	// copy the rest of the data as given
    90 	TUint8 *to=UserPtr();
    91 	if (aLen<4)
    92 		aLen=4;
    93 	aLen-=4;	// skip fmaily and port
    94 	if (aLen>24)
    95 		aLen=24;
    96 	memcpy(to,from,aLen);
    97 	SetUserLen(aLen);
    98 	}
    99 
   100 void TUSockAddr::Get(TAny* addr, unsigned long* len)
   101 //
   102 // Extract a struct sockaddr from a TSockAddr
   103 //
   104 	{
   105 	if (addr==0)
   106 		return;
   107 	struct sockaddr* sp=(struct sockaddr*)addr;
   108 	TUint16 port=(TUint16)Port();
   109 	if (Family()==AF_INET)
   110 		{
   111 		sp->sa_family=AF_INET;
   112 		sp->sa_port=htons(port);
   113 		TUint8* from=UserPtr();
   114 		TUint32 fromaddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
   115 		*(TUint32*)sp->sa_data=fromaddr;
   116 		*len=8;
   117 		return;
   118 		}
   119 	else
   120 		{
   121 		sp->sa_family=(TUint16)Family();
   122 		sp->sa_port=port;
   123 		}
   124 	TUint ulen=GetUserLen();
   125 	if (ulen+4>(*len))
   126 		ulen=(*len)-4;
   127 	*len=ulen+4;
   128 	memcpy(sp->sa_data,UserPtr(),ulen);
   129 	}
   130 
   131 // The Socket descriptor class
   132 
   133 TInt CSocketDesc::isStream() const	// inline, but private
   134 	{ 
   135 	return iStyle==SOCK_STREAM; 
   136 	}
   137 
   138 TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
   139 	{
   140 	if (protocol==0)
   141 		protocol=KUndefinedProtocol;
   142 	TInt err=iSocket.Open(aSs,family,style,protocol);
   143 	if (err==KErrNone)
   144 		iStyle=style;
   145 	return err;
   146 	}
   147 
   148 TInt CSocketDesc::FinalClose()
   149 	{
   150 	iSocket.Close();
   151 	return KErrNone;
   152 	}
   153 
   154 TInt CSocketDesc::LSeek (int&, int)
   155 	{
   156 	return ESPIPE;	// can't seek on a socket
   157 	}
   158 
   159 TInt CSocketDesc::FStat (struct stat *st)
   160 	{
   161 	// I am a socket about which little is known
   162 	st->st_mode = S_IFSOCK;
   163 	st->st_blksize=0;
   164 	return KErrNone;
   165 	}
   166 
   167 void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
   168 	{
   169 	iSocket.Recv(aBuf, 0, aStatus, iLength);	// needs a completion which returns the length
   170 	}
   171 void CSocketDesc::ReadCancel()
   172 	{
   173 	iSocket.CancelRecv();
   174 	}
   175 
   176 void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
   177 	{
   178 	iSocket.Write(aBuf, aStatus);
   179 	}
   180 void CSocketDesc::WriteCancel()
   181 	{
   182 	iSocket.CancelWrite();
   183 	}
   184 
   185 
   186 TInt CSocketDesc::Bind(TSockAddr& anAddr)
   187 	{
   188 	return iSocket.Bind(anAddr);
   189 	}
   190 
   191 TInt CSocketDesc::Listen(TUint qSize)
   192 	{
   193 	return iSocket.Listen(qSize);
   194 	}
   195 
   196 TInt CSocketDesc::SockName(int anEnd, TSockAddr& anAddr)
   197 	{
   198 	const TUint KBadFamily = 0xFF000000;
   199 	anAddr.SetFamily(KBadFamily);
   200 	if (anEnd==0)
   201 		iSocket.LocalName(anAddr);
   202 	else
   203 		iSocket.RemoteName(anAddr);
   204 	if (anAddr.Family()==KBadFamily)
   205 		return KErrGeneral; // assume that the call failed, but there is no way to find out why
   206 	return KErrNone;
   207 	}
   208 
   209 TInt CSocketDesc::GetSockOpt(TUint anOptionName, TUint anOptionLevel, TDes8& anOption)
   210 	{
   211 	return iSocket.GetOpt(anOptionName,anOptionLevel,anOption);
   212 	}
   213 
   214 TInt CSocketDesc::SetSockOpt(TUint anOptionName, TUint anOptionLevel, TDesC8& anOption)
   215 	{
   216 	return iSocket.SetOpt(anOptionName,anOptionLevel,anOption);
   217 	}
   218 
   219 void CSocketDesc::Sync (TRequestStatus& aStatus)
   220 	{
   221 	// Judging from the Solaris man pages, this does nothing.
   222 	Complete(aStatus,KErrNone);
   223 	}
   224 
   225 void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
   226 	{
   227 	if (isStream())
   228 		{
   229 		// recvfrom on a stream ignores the from address - get the peername
   230 		if (from.Length())
   231 			SockName(1,from);
   232 		iSocket.RecvOneOrMore(aDesc,flags,aStatus,iLength);
   233 		}
   234 	else
   235 		iSocket.RecvFrom(aDesc,from,flags,aStatus,iLength);
   236 	}
   237 
   238 void CSocketDesc::RecvFromCancel()
   239 	{
   240 	iSocket.CancelRecv();
   241 	}
   242 
   243 TInt CSocketDesc::RecvFromCompletion(TInt& aLength, TInt aStatus)
   244         {
   245         aLength=iLength();      // ignored if there's an error, 0 at EOF
   246         if (aStatus == KErrEof || aStatus == KErrDisconnected)
   247                 return 0;       // indicates graceful close at the other end
   248         return aStatus;
   249         }
   250 
   251 
   252 void CSocketDesc::SendTo(TDes8& aDesc, TSockAddr& to, int flags, TRequestStatus& aStatus)
   253 	{
   254 	if (to.Length()==0)
   255 		iSocket.Send(aDesc,flags,aStatus);
   256 	else
   257 		{
   258 		if (isStream())
   259 			Complete(aStatus,KErrNotSupported);	// can't sendto a stream
   260 		else
   261 			iSocket.SendTo(aDesc,to,flags,aStatus);
   262 		}
   263 	}
   264 
   265 void CSocketDesc::SendToCancel()
   266 	{
   267 	iSocket.CancelSend();
   268 	}
   269 
   270 void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
   271 	{
   272 	aHow=(aHow+1)&0x3;	// 0=>EStopInput, 1=>EStopOutput, 2=>EStopInOut
   273 	iSocket.Shutdown(*REINTERPRET_CAST(RSocket::TShutdown*,&aHow),aStatus);
   274 	}
   275 
   276 void CSocketDesc::Accept(CSocketDesc*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs)
   277 	{
   278 	aNewSocket= new CSocketDesc;
   279 	TInt err=KErrNone;
   280 	if (aNewSocket!=0)
   281 		err=aNewSocket->iSocket.Open(aSs);
   282 	if (aNewSocket==0 || err!=KErrNone)
   283 		{
   284 		Complete(aStatus,KErrNoMemory);
   285 		delete aNewSocket;
   286 		return;
   287 		}
   288 	aNewSocket->iStyle=SOCK_STREAM;	/* necessarily */
   289 	iSocket.Accept(aNewSocket->iSocket,aStatus);
   290 	}
   291 
   292 void CSocketDesc::AcceptCancel()
   293 	{
   294 	iSocket.CancelAccept();
   295 	}
   296 
   297 void CSocketDesc::Connect(TSockAddr& anAddr,TRequestStatus& aStatus)
   298 	{
   299 	iSocket.Connect(anAddr,aStatus);
   300 	}
   301 
   302 void CSocketDesc::ConnectCancel()
   303 	{
   304 	iSocket.CancelConnect();
   305 	}
   306 
   307 void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
   308 	{
   309 	TInt ret=KErrNone;
   310 	int* param=REINTERPRET_CAST(int*,aParam);
   311 	switch (aCmd)
   312 		{
   313 	case E32IONREAD:
   314 		ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param);
   315 		break;
   316 	case E32IOSELECT:
   317 		{
   318 		iIoctlBuf.Set((TText8*)aParam,4,4);
   319 		iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket);
   320 		}
   321 		return;
   322 	default:
   323 		ret=KErrNotSupported;
   324 		break;
   325 		}
   326 	Complete(aStatus,ret);
   327 	}
   328 
   329 TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
   330 	{
   331 	return aStatus;
   332 	}
   333 
   334 void CSocketDesc::IoctlCancel()
   335 	{
   336 	iSocket.CancelIoctl();
   337 	}