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