genericopenlibs/cstdlib/USTLIB/USOCKET.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 	}