diff -r 000000000000 -r e4d67989cc36 genericopenlibs/cstdlib/USTLIB/USOCKET.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/cstdlib/USTLIB/USOCKET.CPP Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,337 @@ +// Copyright (c) 1997-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: +// Implementation of STDLIB sockets. +// +// + +#include "FDESC.H" +#include +#include // for memcpy +#include // for struct stat +#include // for ENOTSOCK +#include +#include +#include // for htons + +EXPORT_C unsigned short htons(unsigned short hs) + { return ByteOrder::Swap16(hs); } +EXPORT_C unsigned long htonl(unsigned long hl) + { return ByteOrder::Swap32(hl); } + +// Support for struct sockaddr conversion + +TUSockAddr::TUSockAddr (TAny* aBuf) + : TSockAddr() + { + Prepare(aBuf); + } + +void TUSockAddr::Prepare (TAny* aBuf) +// +// Prepare a TUSockAddr to receive an address (used in RecvFrom) +// Setting the length to 0 indicates that we don't really want this address anyway. +// + { + if (aBuf==0) + { + SetLength(0); + return; + } + } + +TUSockAddr::TUSockAddr (TAny* aBuf, TUint aLen) + : TSockAddr() + { + Set(aBuf,aLen); + } + +void TUSockAddr::Set (TAny* aBuf, TUint aLen) +// +// Construct an ESOCK TSockAddr from a struct sockaddr. +// We have to deal with the network byte ordering of AF_INET addresses +// + { + if (aBuf==0) + { + SetLength(0); + return; + } + struct sockaddr* sp=(struct sockaddr*)aBuf; + TUint8 *from=(TUint8*)aBuf; + if (sp->sa_family==AF_INET) + { + // byte-swap sockaddr_in back into host ordering + TUint port=(from[2]<<8)+from[3]; + from+=4; + TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3]; + from+=4; + SetFamily(AF_INET); + SetPort(port); + *(TUint32*)UserPtr()=addr; + SetUserLen(4); + return; + } + // expand the family and port + SetFamily(sp->sa_family); + SetPort(sp->sa_port); + from+=4; + // copy the rest of the data as given + TUint8 *to=UserPtr(); + if (aLen<4) + aLen=4; + aLen-=4; // skip fmaily and port + if (aLen>24) + aLen=24; + memcpy(to,from,aLen); + SetUserLen(aLen); + } + +void TUSockAddr::Get(TAny* addr, unsigned long* len) +// +// Extract a struct sockaddr from a TSockAddr +// + { + if (addr==0) + return; + struct sockaddr* sp=(struct sockaddr*)addr; + TUint16 port=(TUint16)Port(); + if (Family()==AF_INET) + { + sp->sa_family=AF_INET; + sp->sa_port=htons(port); + TUint8* from=UserPtr(); + TUint32 fromaddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3]; + *(TUint32*)sp->sa_data=fromaddr; + *len=8; + return; + } + else + { + sp->sa_family=(TUint16)Family(); + sp->sa_port=port; + } + TUint ulen=GetUserLen(); + if (ulen+4>(*len)) + ulen=(*len)-4; + *len=ulen+4; + memcpy(sp->sa_data,UserPtr(),ulen); + } + +// The Socket descriptor class + +TInt CSocketDesc::isStream() const // inline, but private + { + return iStyle==SOCK_STREAM; + } + +TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol) + { + if (protocol==0) + protocol=KUndefinedProtocol; + TInt err=iSocket.Open(aSs,family,style,protocol); + if (err==KErrNone) + iStyle=style; + return err; + } + +TInt CSocketDesc::FinalClose() + { + iSocket.Close(); + return KErrNone; + } + +TInt CSocketDesc::LSeek (int&, int) + { + return ESPIPE; // can't seek on a socket + } + +TInt CSocketDesc::FStat (struct stat *st) + { + // I am a socket about which little is known + st->st_mode = S_IFSOCK; + st->st_blksize=0; + return KErrNone; + } + +void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus) + { + iSocket.Recv(aBuf, 0, aStatus, iLength); // needs a completion which returns the length + } +void CSocketDesc::ReadCancel() + { + iSocket.CancelRecv(); + } + +void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus) + { + iSocket.Write(aBuf, aStatus); + } +void CSocketDesc::WriteCancel() + { + iSocket.CancelWrite(); + } + + +TInt CSocketDesc::Bind(TSockAddr& anAddr) + { + return iSocket.Bind(anAddr); + } + +TInt CSocketDesc::Listen(TUint qSize) + { + return iSocket.Listen(qSize); + } + +TInt CSocketDesc::SockName(int anEnd, TSockAddr& anAddr) + { + const TUint KBadFamily = 0xFF000000; + anAddr.SetFamily(KBadFamily); + if (anEnd==0) + iSocket.LocalName(anAddr); + else + iSocket.RemoteName(anAddr); + if (anAddr.Family()==KBadFamily) + return KErrGeneral; // assume that the call failed, but there is no way to find out why + return KErrNone; + } + +TInt CSocketDesc::GetSockOpt(TUint anOptionName, TUint anOptionLevel, TDes8& anOption) + { + return iSocket.GetOpt(anOptionName,anOptionLevel,anOption); + } + +TInt CSocketDesc::SetSockOpt(TUint anOptionName, TUint anOptionLevel, TDesC8& anOption) + { + return iSocket.SetOpt(anOptionName,anOptionLevel,anOption); + } + +void CSocketDesc::Sync (TRequestStatus& aStatus) + { + // Judging from the Solaris man pages, this does nothing. + Complete(aStatus,KErrNone); + } + +void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus) + { + if (isStream()) + { + // recvfrom on a stream ignores the from address - get the peername + if (from.Length()) + SockName(1,from); + iSocket.RecvOneOrMore(aDesc,flags,aStatus,iLength); + } + else + iSocket.RecvFrom(aDesc,from,flags,aStatus,iLength); + } + +void CSocketDesc::RecvFromCancel() + { + iSocket.CancelRecv(); + } + +TInt CSocketDesc::RecvFromCompletion(TInt& aLength, TInt aStatus) + { + aLength=iLength(); // ignored if there's an error, 0 at EOF + if (aStatus == KErrEof || aStatus == KErrDisconnected) + return 0; // indicates graceful close at the other end + return aStatus; + } + + +void CSocketDesc::SendTo(TDes8& aDesc, TSockAddr& to, int flags, TRequestStatus& aStatus) + { + if (to.Length()==0) + iSocket.Send(aDesc,flags,aStatus); + else + { + if (isStream()) + Complete(aStatus,KErrNotSupported); // can't sendto a stream + else + iSocket.SendTo(aDesc,to,flags,aStatus); + } + } + +void CSocketDesc::SendToCancel() + { + iSocket.CancelSend(); + } + +void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus) + { + aHow=(aHow+1)&0x3; // 0=>EStopInput, 1=>EStopOutput, 2=>EStopInOut + iSocket.Shutdown(*REINTERPRET_CAST(RSocket::TShutdown*,&aHow),aStatus); + } + +void CSocketDesc::Accept(CSocketDesc*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs) + { + aNewSocket= new CSocketDesc; + TInt err=KErrNone; + if (aNewSocket!=0) + err=aNewSocket->iSocket.Open(aSs); + if (aNewSocket==0 || err!=KErrNone) + { + Complete(aStatus,KErrNoMemory); + delete aNewSocket; + return; + } + aNewSocket->iStyle=SOCK_STREAM; /* necessarily */ + iSocket.Accept(aNewSocket->iSocket,aStatus); + } + +void CSocketDesc::AcceptCancel() + { + iSocket.CancelAccept(); + } + +void CSocketDesc::Connect(TSockAddr& anAddr,TRequestStatus& aStatus) + { + iSocket.Connect(anAddr,aStatus); + } + +void CSocketDesc::ConnectCancel() + { + iSocket.CancelConnect(); + } + +void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus) + { + TInt ret=KErrNone; + int* param=REINTERPRET_CAST(int*,aParam); + switch (aCmd) + { + case E32IONREAD: + ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param); + break; + case E32IOSELECT: + { + iIoctlBuf.Set((TText8*)aParam,4,4); + iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket); + } + return; + default: + ret=KErrNotSupported; + break; + } + Complete(aStatus,ret); + } + +TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus) + { + return aStatus; + } + +void CSocketDesc::IoctlCancel() + { + iSocket.CancelIoctl(); + }