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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Implementation of STDLIB sockets.
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
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); }
32 // Support for struct sockaddr conversion
34 TUSockAddr::TUSockAddr (TAny* aBuf)
40 void TUSockAddr::Prepare (TAny* aBuf)
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.
53 TUSockAddr::TUSockAddr (TAny* aBuf, TUint aLen)
59 void TUSockAddr::Set (TAny* aBuf, TUint aLen)
61 // Construct an ESOCK TSockAddr from a struct sockaddr.
62 // We have to deal with the network byte ordering of AF_INET addresses
70 struct sockaddr* sp=(struct sockaddr*)aBuf;
71 TUint8 *from=(TUint8*)aBuf;
72 if (sp->sa_family==AF_INET)
74 // byte-swap sockaddr_in back into host ordering
75 TUint port=(from[2]<<8)+from[3];
77 TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
81 *(TUint32*)UserPtr()=addr;
85 // expand the family and port
86 SetFamily(sp->sa_family);
89 // copy the rest of the data as given
93 aLen-=4; // skip fmaily and port
100 void TUSockAddr::Get(TAny* addr, unsigned long* len)
102 // Extract a struct sockaddr from a TSockAddr
107 struct sockaddr* sp=(struct sockaddr*)addr;
108 TUint16 port=(TUint16)Port();
109 if (Family()==AF_INET)
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;
121 sp->sa_family=(TUint16)Family();
124 TUint ulen=GetUserLen();
128 memcpy(sp->sa_data,UserPtr(),ulen);
131 // The Socket descriptor class
133 TInt CSocketDesc::isStream() const // inline, but private
135 return iStyle==SOCK_STREAM;
138 TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
141 protocol=KUndefinedProtocol;
142 TInt err=iSocket.Open(aSs,family,style,protocol);
148 TInt CSocketDesc::FinalClose()
154 TInt CSocketDesc::LSeek (int&, int)
156 return ESPIPE; // can't seek on a socket
159 TInt CSocketDesc::FStat (struct stat *st)
161 // I am a socket about which little is known
162 st->st_mode = S_IFSOCK;
167 void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
169 iSocket.Recv(aBuf, 0, aStatus, iLength); // needs a completion which returns the length
171 void CSocketDesc::ReadCancel()
173 iSocket.CancelRecv();
176 void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
178 iSocket.Write(aBuf, aStatus);
180 void CSocketDesc::WriteCancel()
182 iSocket.CancelWrite();
186 TInt CSocketDesc::Bind(TSockAddr& anAddr)
188 return iSocket.Bind(anAddr);
191 TInt CSocketDesc::Listen(TUint qSize)
193 return iSocket.Listen(qSize);
196 TInt CSocketDesc::SockName(int anEnd, TSockAddr& anAddr)
198 const TUint KBadFamily = 0xFF000000;
199 anAddr.SetFamily(KBadFamily);
201 iSocket.LocalName(anAddr);
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
209 TInt CSocketDesc::GetSockOpt(TUint anOptionName, TUint anOptionLevel, TDes8& anOption)
211 return iSocket.GetOpt(anOptionName,anOptionLevel,anOption);
214 TInt CSocketDesc::SetSockOpt(TUint anOptionName, TUint anOptionLevel, TDesC8& anOption)
216 return iSocket.SetOpt(anOptionName,anOptionLevel,anOption);
219 void CSocketDesc::Sync (TRequestStatus& aStatus)
221 // Judging from the Solaris man pages, this does nothing.
222 Complete(aStatus,KErrNone);
225 void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
229 // recvfrom on a stream ignores the from address - get the peername
232 iSocket.RecvOneOrMore(aDesc,flags,aStatus,iLength);
235 iSocket.RecvFrom(aDesc,from,flags,aStatus,iLength);
238 void CSocketDesc::RecvFromCancel()
240 iSocket.CancelRecv();
243 TInt CSocketDesc::RecvFromCompletion(TInt& aLength, TInt aStatus)
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
252 void CSocketDesc::SendTo(TDes8& aDesc, TSockAddr& to, int flags, TRequestStatus& aStatus)
255 iSocket.Send(aDesc,flags,aStatus);
259 Complete(aStatus,KErrNotSupported); // can't sendto a stream
261 iSocket.SendTo(aDesc,to,flags,aStatus);
265 void CSocketDesc::SendToCancel()
267 iSocket.CancelSend();
270 void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
272 aHow=(aHow+1)&0x3; // 0=>EStopInput, 1=>EStopOutput, 2=>EStopInOut
273 iSocket.Shutdown(*REINTERPRET_CAST(RSocket::TShutdown*,&aHow),aStatus);
276 void CSocketDesc::Accept(CSocketDesc*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs)
278 aNewSocket= new CSocketDesc;
281 err=aNewSocket->iSocket.Open(aSs);
282 if (aNewSocket==0 || err!=KErrNone)
284 Complete(aStatus,KErrNoMemory);
288 aNewSocket->iStyle=SOCK_STREAM; /* necessarily */
289 iSocket.Accept(aNewSocket->iSocket,aStatus);
292 void CSocketDesc::AcceptCancel()
294 iSocket.CancelAccept();
297 void CSocketDesc::Connect(TSockAddr& anAddr,TRequestStatus& aStatus)
299 iSocket.Connect(anAddr,aStatus);
302 void CSocketDesc::ConnectCancel()
304 iSocket.CancelConnect();
307 void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
310 int* param=REINTERPRET_CAST(int*,aParam);
314 ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param);
318 iIoctlBuf.Set((TText8*)aParam,4,4);
319 iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket);
323 ret=KErrNotSupported;
326 Complete(aStatus,ret);
329 TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
334 void CSocketDesc::IoctlCancel()
336 iSocket.CancelIoctl();