1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/USTLIB/USOCKET.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,337 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Implementation of STDLIB sockets.
1.18 +//
1.19 +//
1.20 +
1.21 +#include "FDESC.H"
1.22 +#include <sys/types.h>
1.23 +#include <string.h> // for memcpy
1.24 +#include <fcntl.h> // for struct stat
1.25 +#include <sys/errno.h> // for ENOTSOCK
1.26 +#include <sys/socket.h>
1.27 +#include <sys/ioctl.h>
1.28 +#include <libc/netinet/in.h> // for htons
1.29 +
1.30 +EXPORT_C unsigned short htons(unsigned short hs)
1.31 + { return ByteOrder::Swap16(hs); }
1.32 +EXPORT_C unsigned long htonl(unsigned long hl)
1.33 + { return ByteOrder::Swap32(hl); }
1.34 +
1.35 +// Support for struct sockaddr conversion
1.36 +
1.37 +TUSockAddr::TUSockAddr (TAny* aBuf)
1.38 + : TSockAddr()
1.39 + {
1.40 + Prepare(aBuf);
1.41 + }
1.42 +
1.43 +void TUSockAddr::Prepare (TAny* aBuf)
1.44 +//
1.45 +// Prepare a TUSockAddr to receive an address (used in RecvFrom)
1.46 +// Setting the length to 0 indicates that we don't really want this address anyway.
1.47 +//
1.48 + {
1.49 + if (aBuf==0)
1.50 + {
1.51 + SetLength(0);
1.52 + return;
1.53 + }
1.54 + }
1.55 +
1.56 +TUSockAddr::TUSockAddr (TAny* aBuf, TUint aLen)
1.57 + : TSockAddr()
1.58 + {
1.59 + Set(aBuf,aLen);
1.60 + }
1.61 +
1.62 +void TUSockAddr::Set (TAny* aBuf, TUint aLen)
1.63 +//
1.64 +// Construct an ESOCK TSockAddr from a struct sockaddr.
1.65 +// We have to deal with the network byte ordering of AF_INET addresses
1.66 +//
1.67 + {
1.68 + if (aBuf==0)
1.69 + {
1.70 + SetLength(0);
1.71 + return;
1.72 + }
1.73 + struct sockaddr* sp=(struct sockaddr*)aBuf;
1.74 + TUint8 *from=(TUint8*)aBuf;
1.75 + if (sp->sa_family==AF_INET)
1.76 + {
1.77 + // byte-swap sockaddr_in back into host ordering
1.78 + TUint port=(from[2]<<8)+from[3];
1.79 + from+=4;
1.80 + TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
1.81 + from+=4;
1.82 + SetFamily(AF_INET);
1.83 + SetPort(port);
1.84 + *(TUint32*)UserPtr()=addr;
1.85 + SetUserLen(4);
1.86 + return;
1.87 + }
1.88 + // expand the family and port
1.89 + SetFamily(sp->sa_family);
1.90 + SetPort(sp->sa_port);
1.91 + from+=4;
1.92 + // copy the rest of the data as given
1.93 + TUint8 *to=UserPtr();
1.94 + if (aLen<4)
1.95 + aLen=4;
1.96 + aLen-=4; // skip fmaily and port
1.97 + if (aLen>24)
1.98 + aLen=24;
1.99 + memcpy(to,from,aLen);
1.100 + SetUserLen(aLen);
1.101 + }
1.102 +
1.103 +void TUSockAddr::Get(TAny* addr, unsigned long* len)
1.104 +//
1.105 +// Extract a struct sockaddr from a TSockAddr
1.106 +//
1.107 + {
1.108 + if (addr==0)
1.109 + return;
1.110 + struct sockaddr* sp=(struct sockaddr*)addr;
1.111 + TUint16 port=(TUint16)Port();
1.112 + if (Family()==AF_INET)
1.113 + {
1.114 + sp->sa_family=AF_INET;
1.115 + sp->sa_port=htons(port);
1.116 + TUint8* from=UserPtr();
1.117 + TUint32 fromaddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
1.118 + *(TUint32*)sp->sa_data=fromaddr;
1.119 + *len=8;
1.120 + return;
1.121 + }
1.122 + else
1.123 + {
1.124 + sp->sa_family=(TUint16)Family();
1.125 + sp->sa_port=port;
1.126 + }
1.127 + TUint ulen=GetUserLen();
1.128 + if (ulen+4>(*len))
1.129 + ulen=(*len)-4;
1.130 + *len=ulen+4;
1.131 + memcpy(sp->sa_data,UserPtr(),ulen);
1.132 + }
1.133 +
1.134 +// The Socket descriptor class
1.135 +
1.136 +TInt CSocketDesc::isStream() const // inline, but private
1.137 + {
1.138 + return iStyle==SOCK_STREAM;
1.139 + }
1.140 +
1.141 +TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
1.142 + {
1.143 + if (protocol==0)
1.144 + protocol=KUndefinedProtocol;
1.145 + TInt err=iSocket.Open(aSs,family,style,protocol);
1.146 + if (err==KErrNone)
1.147 + iStyle=style;
1.148 + return err;
1.149 + }
1.150 +
1.151 +TInt CSocketDesc::FinalClose()
1.152 + {
1.153 + iSocket.Close();
1.154 + return KErrNone;
1.155 + }
1.156 +
1.157 +TInt CSocketDesc::LSeek (int&, int)
1.158 + {
1.159 + return ESPIPE; // can't seek on a socket
1.160 + }
1.161 +
1.162 +TInt CSocketDesc::FStat (struct stat *st)
1.163 + {
1.164 + // I am a socket about which little is known
1.165 + st->st_mode = S_IFSOCK;
1.166 + st->st_blksize=0;
1.167 + return KErrNone;
1.168 + }
1.169 +
1.170 +void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
1.171 + {
1.172 + iSocket.Recv(aBuf, 0, aStatus, iLength); // needs a completion which returns the length
1.173 + }
1.174 +void CSocketDesc::ReadCancel()
1.175 + {
1.176 + iSocket.CancelRecv();
1.177 + }
1.178 +
1.179 +void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
1.180 + {
1.181 + iSocket.Write(aBuf, aStatus);
1.182 + }
1.183 +void CSocketDesc::WriteCancel()
1.184 + {
1.185 + iSocket.CancelWrite();
1.186 + }
1.187 +
1.188 +
1.189 +TInt CSocketDesc::Bind(TSockAddr& anAddr)
1.190 + {
1.191 + return iSocket.Bind(anAddr);
1.192 + }
1.193 +
1.194 +TInt CSocketDesc::Listen(TUint qSize)
1.195 + {
1.196 + return iSocket.Listen(qSize);
1.197 + }
1.198 +
1.199 +TInt CSocketDesc::SockName(int anEnd, TSockAddr& anAddr)
1.200 + {
1.201 + const TUint KBadFamily = 0xFF000000;
1.202 + anAddr.SetFamily(KBadFamily);
1.203 + if (anEnd==0)
1.204 + iSocket.LocalName(anAddr);
1.205 + else
1.206 + iSocket.RemoteName(anAddr);
1.207 + if (anAddr.Family()==KBadFamily)
1.208 + return KErrGeneral; // assume that the call failed, but there is no way to find out why
1.209 + return KErrNone;
1.210 + }
1.211 +
1.212 +TInt CSocketDesc::GetSockOpt(TUint anOptionName, TUint anOptionLevel, TDes8& anOption)
1.213 + {
1.214 + return iSocket.GetOpt(anOptionName,anOptionLevel,anOption);
1.215 + }
1.216 +
1.217 +TInt CSocketDesc::SetSockOpt(TUint anOptionName, TUint anOptionLevel, TDesC8& anOption)
1.218 + {
1.219 + return iSocket.SetOpt(anOptionName,anOptionLevel,anOption);
1.220 + }
1.221 +
1.222 +void CSocketDesc::Sync (TRequestStatus& aStatus)
1.223 + {
1.224 + // Judging from the Solaris man pages, this does nothing.
1.225 + Complete(aStatus,KErrNone);
1.226 + }
1.227 +
1.228 +void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
1.229 + {
1.230 + if (isStream())
1.231 + {
1.232 + // recvfrom on a stream ignores the from address - get the peername
1.233 + if (from.Length())
1.234 + SockName(1,from);
1.235 + iSocket.RecvOneOrMore(aDesc,flags,aStatus,iLength);
1.236 + }
1.237 + else
1.238 + iSocket.RecvFrom(aDesc,from,flags,aStatus,iLength);
1.239 + }
1.240 +
1.241 +void CSocketDesc::RecvFromCancel()
1.242 + {
1.243 + iSocket.CancelRecv();
1.244 + }
1.245 +
1.246 +TInt CSocketDesc::RecvFromCompletion(TInt& aLength, TInt aStatus)
1.247 + {
1.248 + aLength=iLength(); // ignored if there's an error, 0 at EOF
1.249 + if (aStatus == KErrEof || aStatus == KErrDisconnected)
1.250 + return 0; // indicates graceful close at the other end
1.251 + return aStatus;
1.252 + }
1.253 +
1.254 +
1.255 +void CSocketDesc::SendTo(TDes8& aDesc, TSockAddr& to, int flags, TRequestStatus& aStatus)
1.256 + {
1.257 + if (to.Length()==0)
1.258 + iSocket.Send(aDesc,flags,aStatus);
1.259 + else
1.260 + {
1.261 + if (isStream())
1.262 + Complete(aStatus,KErrNotSupported); // can't sendto a stream
1.263 + else
1.264 + iSocket.SendTo(aDesc,to,flags,aStatus);
1.265 + }
1.266 + }
1.267 +
1.268 +void CSocketDesc::SendToCancel()
1.269 + {
1.270 + iSocket.CancelSend();
1.271 + }
1.272 +
1.273 +void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
1.274 + {
1.275 + aHow=(aHow+1)&0x3; // 0=>EStopInput, 1=>EStopOutput, 2=>EStopInOut
1.276 + iSocket.Shutdown(*REINTERPRET_CAST(RSocket::TShutdown*,&aHow),aStatus);
1.277 + }
1.278 +
1.279 +void CSocketDesc::Accept(CSocketDesc*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs)
1.280 + {
1.281 + aNewSocket= new CSocketDesc;
1.282 + TInt err=KErrNone;
1.283 + if (aNewSocket!=0)
1.284 + err=aNewSocket->iSocket.Open(aSs);
1.285 + if (aNewSocket==0 || err!=KErrNone)
1.286 + {
1.287 + Complete(aStatus,KErrNoMemory);
1.288 + delete aNewSocket;
1.289 + return;
1.290 + }
1.291 + aNewSocket->iStyle=SOCK_STREAM; /* necessarily */
1.292 + iSocket.Accept(aNewSocket->iSocket,aStatus);
1.293 + }
1.294 +
1.295 +void CSocketDesc::AcceptCancel()
1.296 + {
1.297 + iSocket.CancelAccept();
1.298 + }
1.299 +
1.300 +void CSocketDesc::Connect(TSockAddr& anAddr,TRequestStatus& aStatus)
1.301 + {
1.302 + iSocket.Connect(anAddr,aStatus);
1.303 + }
1.304 +
1.305 +void CSocketDesc::ConnectCancel()
1.306 + {
1.307 + iSocket.CancelConnect();
1.308 + }
1.309 +
1.310 +void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
1.311 + {
1.312 + TInt ret=KErrNone;
1.313 + int* param=REINTERPRET_CAST(int*,aParam);
1.314 + switch (aCmd)
1.315 + {
1.316 + case E32IONREAD:
1.317 + ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param);
1.318 + break;
1.319 + case E32IOSELECT:
1.320 + {
1.321 + iIoctlBuf.Set((TText8*)aParam,4,4);
1.322 + iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket);
1.323 + }
1.324 + return;
1.325 + default:
1.326 + ret=KErrNotSupported;
1.327 + break;
1.328 + }
1.329 + Complete(aStatus,ret);
1.330 + }
1.331 +
1.332 +TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
1.333 + {
1.334 + return aStatus;
1.335 + }
1.336 +
1.337 +void CSocketDesc::IoctlCancel()
1.338 + {
1.339 + iSocket.CancelIoctl();
1.340 + }