os/ossrv/genericopenlibs/cstdlib/USTLIB/USOCKET.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Implementation of STDLIB sockets.
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "FDESC.H"
sl@0
    19
#include <sys/types.h>
sl@0
    20
#include <string.h>		// for memcpy
sl@0
    21
#include <fcntl.h>		// for struct stat
sl@0
    22
#include <sys/errno.h>		// for ENOTSOCK
sl@0
    23
#include <sys/socket.h>
sl@0
    24
#include <sys/ioctl.h>
sl@0
    25
#include <libc/netinet/in.h>		// for htons
sl@0
    26
sl@0
    27
EXPORT_C unsigned short htons(unsigned short hs)
sl@0
    28
	{ return ByteOrder::Swap16(hs); }
sl@0
    29
EXPORT_C unsigned long  htonl(unsigned long hl)
sl@0
    30
	{ return ByteOrder::Swap32(hl); }
sl@0
    31
sl@0
    32
// Support for struct sockaddr conversion
sl@0
    33
sl@0
    34
TUSockAddr::TUSockAddr (TAny* aBuf) 
sl@0
    35
	: TSockAddr()
sl@0
    36
	{
sl@0
    37
	Prepare(aBuf);
sl@0
    38
	}
sl@0
    39
sl@0
    40
void TUSockAddr::Prepare (TAny* aBuf) 
sl@0
    41
//
sl@0
    42
// Prepare a TUSockAddr to receive an address (used in RecvFrom)
sl@0
    43
// Setting the length to 0 indicates that we don't really want this address anyway.
sl@0
    44
//
sl@0
    45
	{
sl@0
    46
	if (aBuf==0)
sl@0
    47
		{
sl@0
    48
		SetLength(0);
sl@0
    49
		return;
sl@0
    50
		}
sl@0
    51
	}
sl@0
    52
sl@0
    53
TUSockAddr::TUSockAddr (TAny* aBuf, TUint aLen) 
sl@0
    54
	: TSockAddr()
sl@0
    55
	{
sl@0
    56
	Set(aBuf,aLen);
sl@0
    57
	}
sl@0
    58
sl@0
    59
void TUSockAddr::Set (TAny* aBuf, TUint aLen) 
sl@0
    60
//
sl@0
    61
// Construct an ESOCK TSockAddr from a struct sockaddr.
sl@0
    62
// We have to deal with the network byte ordering of AF_INET addresses
sl@0
    63
//
sl@0
    64
	{
sl@0
    65
	if (aBuf==0)
sl@0
    66
		{
sl@0
    67
		SetLength(0);
sl@0
    68
		return;
sl@0
    69
		}
sl@0
    70
	struct sockaddr* sp=(struct sockaddr*)aBuf;
sl@0
    71
	TUint8 *from=(TUint8*)aBuf;
sl@0
    72
	if (sp->sa_family==AF_INET)
sl@0
    73
		{
sl@0
    74
		// byte-swap sockaddr_in back into host ordering
sl@0
    75
		TUint port=(from[2]<<8)+from[3];
sl@0
    76
		from+=4;
sl@0
    77
		TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
sl@0
    78
		from+=4;
sl@0
    79
		SetFamily(AF_INET);
sl@0
    80
		SetPort(port);
sl@0
    81
		*(TUint32*)UserPtr()=addr;
sl@0
    82
		SetUserLen(4);
sl@0
    83
		return;
sl@0
    84
		}
sl@0
    85
	// expand the family and port
sl@0
    86
	SetFamily(sp->sa_family);
sl@0
    87
	SetPort(sp->sa_port);
sl@0
    88
	from+=4;
sl@0
    89
	// copy the rest of the data as given
sl@0
    90
	TUint8 *to=UserPtr();
sl@0
    91
	if (aLen<4)
sl@0
    92
		aLen=4;
sl@0
    93
	aLen-=4;	// skip fmaily and port
sl@0
    94
	if (aLen>24)
sl@0
    95
		aLen=24;
sl@0
    96
	memcpy(to,from,aLen);
sl@0
    97
	SetUserLen(aLen);
sl@0
    98
	}
sl@0
    99
sl@0
   100
void TUSockAddr::Get(TAny* addr, unsigned long* len)
sl@0
   101
//
sl@0
   102
// Extract a struct sockaddr from a TSockAddr
sl@0
   103
//
sl@0
   104
	{
sl@0
   105
	if (addr==0)
sl@0
   106
		return;
sl@0
   107
	struct sockaddr* sp=(struct sockaddr*)addr;
sl@0
   108
	TUint16 port=(TUint16)Port();
sl@0
   109
	if (Family()==AF_INET)
sl@0
   110
		{
sl@0
   111
		sp->sa_family=AF_INET;
sl@0
   112
		sp->sa_port=htons(port);
sl@0
   113
		TUint8* from=UserPtr();
sl@0
   114
		TUint32 fromaddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
sl@0
   115
		*(TUint32*)sp->sa_data=fromaddr;
sl@0
   116
		*len=8;
sl@0
   117
		return;
sl@0
   118
		}
sl@0
   119
	else
sl@0
   120
		{
sl@0
   121
		sp->sa_family=(TUint16)Family();
sl@0
   122
		sp->sa_port=port;
sl@0
   123
		}
sl@0
   124
	TUint ulen=GetUserLen();
sl@0
   125
	if (ulen+4>(*len))
sl@0
   126
		ulen=(*len)-4;
sl@0
   127
	*len=ulen+4;
sl@0
   128
	memcpy(sp->sa_data,UserPtr(),ulen);
sl@0
   129
	}
sl@0
   130
sl@0
   131
// The Socket descriptor class
sl@0
   132
sl@0
   133
TInt CSocketDesc::isStream() const	// inline, but private
sl@0
   134
	{ 
sl@0
   135
	return iStyle==SOCK_STREAM; 
sl@0
   136
	}
sl@0
   137
sl@0
   138
TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
sl@0
   139
	{
sl@0
   140
	if (protocol==0)
sl@0
   141
		protocol=KUndefinedProtocol;
sl@0
   142
	TInt err=iSocket.Open(aSs,family,style,protocol);
sl@0
   143
	if (err==KErrNone)
sl@0
   144
		iStyle=style;
sl@0
   145
	return err;
sl@0
   146
	}
sl@0
   147
sl@0
   148
TInt CSocketDesc::FinalClose()
sl@0
   149
	{
sl@0
   150
	iSocket.Close();
sl@0
   151
	return KErrNone;
sl@0
   152
	}
sl@0
   153
sl@0
   154
TInt CSocketDesc::LSeek (int&, int)
sl@0
   155
	{
sl@0
   156
	return ESPIPE;	// can't seek on a socket
sl@0
   157
	}
sl@0
   158
sl@0
   159
TInt CSocketDesc::FStat (struct stat *st)
sl@0
   160
	{
sl@0
   161
	// I am a socket about which little is known
sl@0
   162
	st->st_mode = S_IFSOCK;
sl@0
   163
	st->st_blksize=0;
sl@0
   164
	return KErrNone;
sl@0
   165
	}
sl@0
   166
sl@0
   167
void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
sl@0
   168
	{
sl@0
   169
	iSocket.Recv(aBuf, 0, aStatus, iLength);	// needs a completion which returns the length
sl@0
   170
	}
sl@0
   171
void CSocketDesc::ReadCancel()
sl@0
   172
	{
sl@0
   173
	iSocket.CancelRecv();
sl@0
   174
	}
sl@0
   175
sl@0
   176
void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
sl@0
   177
	{
sl@0
   178
	iSocket.Write(aBuf, aStatus);
sl@0
   179
	}
sl@0
   180
void CSocketDesc::WriteCancel()
sl@0
   181
	{
sl@0
   182
	iSocket.CancelWrite();
sl@0
   183
	}
sl@0
   184
sl@0
   185
sl@0
   186
TInt CSocketDesc::Bind(TSockAddr& anAddr)
sl@0
   187
	{
sl@0
   188
	return iSocket.Bind(anAddr);
sl@0
   189
	}
sl@0
   190
sl@0
   191
TInt CSocketDesc::Listen(TUint qSize)
sl@0
   192
	{
sl@0
   193
	return iSocket.Listen(qSize);
sl@0
   194
	}
sl@0
   195
sl@0
   196
TInt CSocketDesc::SockName(int anEnd, TSockAddr& anAddr)
sl@0
   197
	{
sl@0
   198
	const TUint KBadFamily = 0xFF000000;
sl@0
   199
	anAddr.SetFamily(KBadFamily);
sl@0
   200
	if (anEnd==0)
sl@0
   201
		iSocket.LocalName(anAddr);
sl@0
   202
	else
sl@0
   203
		iSocket.RemoteName(anAddr);
sl@0
   204
	if (anAddr.Family()==KBadFamily)
sl@0
   205
		return KErrGeneral; // assume that the call failed, but there is no way to find out why
sl@0
   206
	return KErrNone;
sl@0
   207
	}
sl@0
   208
sl@0
   209
TInt CSocketDesc::GetSockOpt(TUint anOptionName, TUint anOptionLevel, TDes8& anOption)
sl@0
   210
	{
sl@0
   211
	return iSocket.GetOpt(anOptionName,anOptionLevel,anOption);
sl@0
   212
	}
sl@0
   213
sl@0
   214
TInt CSocketDesc::SetSockOpt(TUint anOptionName, TUint anOptionLevel, TDesC8& anOption)
sl@0
   215
	{
sl@0
   216
	return iSocket.SetOpt(anOptionName,anOptionLevel,anOption);
sl@0
   217
	}
sl@0
   218
sl@0
   219
void CSocketDesc::Sync (TRequestStatus& aStatus)
sl@0
   220
	{
sl@0
   221
	// Judging from the Solaris man pages, this does nothing.
sl@0
   222
	Complete(aStatus,KErrNone);
sl@0
   223
	}
sl@0
   224
sl@0
   225
void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
sl@0
   226
	{
sl@0
   227
	if (isStream())
sl@0
   228
		{
sl@0
   229
		// recvfrom on a stream ignores the from address - get the peername
sl@0
   230
		if (from.Length())
sl@0
   231
			SockName(1,from);
sl@0
   232
		iSocket.RecvOneOrMore(aDesc,flags,aStatus,iLength);
sl@0
   233
		}
sl@0
   234
	else
sl@0
   235
		iSocket.RecvFrom(aDesc,from,flags,aStatus,iLength);
sl@0
   236
	}
sl@0
   237
sl@0
   238
void CSocketDesc::RecvFromCancel()
sl@0
   239
	{
sl@0
   240
	iSocket.CancelRecv();
sl@0
   241
	}
sl@0
   242
sl@0
   243
TInt CSocketDesc::RecvFromCompletion(TInt& aLength, TInt aStatus)
sl@0
   244
        {
sl@0
   245
        aLength=iLength();      // ignored if there's an error, 0 at EOF
sl@0
   246
        if (aStatus == KErrEof || aStatus == KErrDisconnected)
sl@0
   247
                return 0;       // indicates graceful close at the other end
sl@0
   248
        return aStatus;
sl@0
   249
        }
sl@0
   250
sl@0
   251
sl@0
   252
void CSocketDesc::SendTo(TDes8& aDesc, TSockAddr& to, int flags, TRequestStatus& aStatus)
sl@0
   253
	{
sl@0
   254
	if (to.Length()==0)
sl@0
   255
		iSocket.Send(aDesc,flags,aStatus);
sl@0
   256
	else
sl@0
   257
		{
sl@0
   258
		if (isStream())
sl@0
   259
			Complete(aStatus,KErrNotSupported);	// can't sendto a stream
sl@0
   260
		else
sl@0
   261
			iSocket.SendTo(aDesc,to,flags,aStatus);
sl@0
   262
		}
sl@0
   263
	}
sl@0
   264
sl@0
   265
void CSocketDesc::SendToCancel()
sl@0
   266
	{
sl@0
   267
	iSocket.CancelSend();
sl@0
   268
	}
sl@0
   269
sl@0
   270
void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
sl@0
   271
	{
sl@0
   272
	aHow=(aHow+1)&0x3;	// 0=>EStopInput, 1=>EStopOutput, 2=>EStopInOut
sl@0
   273
	iSocket.Shutdown(*REINTERPRET_CAST(RSocket::TShutdown*,&aHow),aStatus);
sl@0
   274
	}
sl@0
   275
sl@0
   276
void CSocketDesc::Accept(CSocketDesc*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs)
sl@0
   277
	{
sl@0
   278
	aNewSocket= new CSocketDesc;
sl@0
   279
	TInt err=KErrNone;
sl@0
   280
	if (aNewSocket!=0)
sl@0
   281
		err=aNewSocket->iSocket.Open(aSs);
sl@0
   282
	if (aNewSocket==0 || err!=KErrNone)
sl@0
   283
		{
sl@0
   284
		Complete(aStatus,KErrNoMemory);
sl@0
   285
		delete aNewSocket;
sl@0
   286
		return;
sl@0
   287
		}
sl@0
   288
	aNewSocket->iStyle=SOCK_STREAM;	/* necessarily */
sl@0
   289
	iSocket.Accept(aNewSocket->iSocket,aStatus);
sl@0
   290
	}
sl@0
   291
sl@0
   292
void CSocketDesc::AcceptCancel()
sl@0
   293
	{
sl@0
   294
	iSocket.CancelAccept();
sl@0
   295
	}
sl@0
   296
sl@0
   297
void CSocketDesc::Connect(TSockAddr& anAddr,TRequestStatus& aStatus)
sl@0
   298
	{
sl@0
   299
	iSocket.Connect(anAddr,aStatus);
sl@0
   300
	}
sl@0
   301
sl@0
   302
void CSocketDesc::ConnectCancel()
sl@0
   303
	{
sl@0
   304
	iSocket.CancelConnect();
sl@0
   305
	}
sl@0
   306
sl@0
   307
void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
sl@0
   308
	{
sl@0
   309
	TInt ret=KErrNone;
sl@0
   310
	int* param=REINTERPRET_CAST(int*,aParam);
sl@0
   311
	switch (aCmd)
sl@0
   312
		{
sl@0
   313
	case E32IONREAD:
sl@0
   314
		ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param);
sl@0
   315
		break;
sl@0
   316
	case E32IOSELECT:
sl@0
   317
		{
sl@0
   318
		iIoctlBuf.Set((TText8*)aParam,4,4);
sl@0
   319
		iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket);
sl@0
   320
		}
sl@0
   321
		return;
sl@0
   322
	default:
sl@0
   323
		ret=KErrNotSupported;
sl@0
   324
		break;
sl@0
   325
		}
sl@0
   326
	Complete(aStatus,ret);
sl@0
   327
	}
sl@0
   328
sl@0
   329
TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
sl@0
   330
	{
sl@0
   331
	return aStatus;
sl@0
   332
	}
sl@0
   333
sl@0
   334
void CSocketDesc::IoctlCancel()
sl@0
   335
	{
sl@0
   336
	iSocket.CancelIoctl();
sl@0
   337
	}