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