1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /*!
19 ** Socket implementation for PV socket server
20 */
21
22 #include "oscl_socket_tuneables.h"
23 #if(PV_SOCKET_SERVER)
24 #include "oscl_socket_imp_pv.h"
25 #include "oscl_socket_serv_imp_pv.h"
26 #include "oscl_socket_method.h"
27
28 //Stats macros for use with OsclSocketI
29 #if(PV_OSCL_SOCKET_STATS_LOGGING)
30 #define ADD_STATS(x,y) iStats.Add(x,y)
31 #define CONSTRUCT_STATS(x,y) iStats.Construct(x,y)
32 #else
33 #define ADD_STATS(x,y)
34 #define CONSTRUCT_STATS(x,y)
35 #endif
36
OsclSocketI(Oscl_DefAlloc & a)37 OsclSocketI::OsclSocketI(Oscl_DefAlloc &a) : OsclSocketIBase(a)
38 {
39 iSocketServ = NULL;
40 InitSocket(false);
41
42 iSockServAcceptRequest.iSocketI = this;
43 iSockServConnectRequest.iSocketI = this;
44 iSockServRecvRequest.iSocketI = this;
45 iSockServRecvFromRequest.iSocketI = this;
46 iSockServSendRequest.iSocketI = this;
47 iSockServSendToRequest.iSocketI = this;
48 iSockServShutdownRequest.iSocketI = this;
49 iLogger = PVLogger::GetLoggerObject("osclsocket");
50 }
51
~OsclSocketI()52 OsclSocketI::~OsclSocketI()
53 {
54 Close();
55 }
56
NewL(Oscl_DefAlloc & a)57 OsclSocketI* OsclSocketI::NewL(Oscl_DefAlloc &a)
58 {
59 OsclAny*p = a.ALLOCATE(sizeof(OsclSocketI));
60 OsclError::LeaveIfNull(p);
61 OsclSocketI *self = OSCL_PLACEMENT_NEW(p, OsclSocketI(a));
62 OsclError::LeaveIfNull(self);
63 return self;
64 }
65
Close()66 int32 OsclSocketI::Close()
67 {
68 int sockerr = 0;
69
70 //cleanup the OS-level socket
71 if (iSocketValid)
72 {
73 #ifdef OsclCloseSocket
74 //call the platform socket close routine...
75 bool ok;
76 OsclCloseSocket(iSocket, ok, sockerr);
77 #else
78 sockerr = PVSOCK_ERR_NOT_IMPLEMENTED;
79 #endif
80 }
81
82 InitSocket(false);
83 return sockerr;
84
85 }
86
HasAsyncBind()87 bool OsclSocketIBase::HasAsyncBind()
88 {
89 return false;
90 }
91
Bind(OsclNetworkAddress & anAddr)92 int32 OsclSocketI::Bind(OsclNetworkAddress& anAddr)
93 {
94 #ifdef OsclBind
95 TOsclSockAddr addr;
96 MakeAddr(anAddr, addr);
97 int err;
98 bool ok;
99 OsclBind(iSocket, addr, ok, err);
100 if (!ok)
101 return err;
102 #if (PV_OSCL_SOCKET_1MB_RECV_BUF)
103 int bufsize = (1024 * 1024);
104 OsclSetRecvBufferSize(iSocket, bufsize, ok, err);
105 #endif
106 return OsclErrNone;
107 #else
108 return PVSOCK_ERR_NOT_IMPLEMENTED;
109 #endif
110 }
111
Join(OsclNetworkAddress & anAddr)112 int32 OsclSocketI::Join(OsclNetworkAddress& anAddr)
113 {
114 #ifdef OsclJoin
115 TOsclSockAddr addr;
116 MakeAddr(anAddr, addr);
117 int err;
118 bool ok;
119 OsclJoin(iSocket, addr, ok, err);
120 if (!ok)
121 return err;
122 return OsclErrNone;
123 #else
124 OSCL_UNUSED_ARG(anAddr);
125 OSCL_LEAVE(OsclErrNotSupported);
126 return 0;
127 #endif
128 }
129
HasAsyncListen()130 bool OsclSocketIBase::HasAsyncListen()
131 {
132 return false;
133 }
134
Listen(uint32 qSize)135 int32 OsclSocketI::Listen(uint32 qSize)
136 {
137 #ifdef OsclListen
138 //note: it's ok to do multiple listens to update the queue size
139 bool ok;
140 int err;
141 OsclListen(iSocket, qSize, ok, err);
142 if (!ok)
143 return err;
144 return OsclErrNone;
145 #else
146 OSCL_UNUSED_ARG(qSize);
147 return PVSOCK_ERR_NOT_IMPLEMENTED;
148 #endif
149 }
150
SetRecvBufferSize(uint32 size)151 int32 OsclSocketI::SetRecvBufferSize(uint32 size)
152 {
153 #ifdef OsclSetRecvBufferSize
154 int err;
155 int ok;
156 OsclSetRecvBufferSize(iSocket, size, ok, err);
157 if (!ok)
158 return err;
159 return OsclErrNone;
160 #else
161 OSCL_UNUSED_ARG(size);
162 OSCL_LEAVE(OsclErrNotSupported);
163 return 0;
164 #endif
165 }
166
Send(SendParam & param,OsclSocketRequestAO & ao)167 inline void OsclSocketI::Send(SendParam ¶m, OsclSocketRequestAO& ao)
168 {
169 if (!IsReady(ao))
170 return;
171 //send/recv behavior is undefined when socket is
172 //not connected, so disallow it.
173 if (!IsConnected(ao))
174 return ;
175 iSockServSendRequest.Activate(¶m, ao);
176 }
177
SendSuccess(SendParam & param)178 inline void OsclSocketI::SendSuccess(SendParam ¶m)
179 {
180 //nothing needed
181 OSCL_UNUSED_ARG(param);
182 }
183
CancelSend()184 inline void OsclSocketI::CancelSend()
185 {
186 iSockServSendRequest.CancelRequest();
187 }
188
SendTo(SendToParam & param,OsclSocketRequestAO & ao)189 inline void OsclSocketI::SendTo(SendToParam ¶m, OsclSocketRequestAO& ao)
190 {
191 if (!IsReady(ao))
192 return;
193 iSockServSendToRequest.Activate(¶m, ao);
194 }
195
SendToSuccess(SendToParam & param)196 inline void OsclSocketI::SendToSuccess(SendToParam ¶m)
197 {
198 //nothing needed
199 OSCL_UNUSED_ARG(param);
200 }
201
CancelSendTo()202 inline void OsclSocketI::CancelSendTo()
203 {
204 iSockServSendToRequest.CancelRequest();
205 }
206
Recv(RecvParam & param,OsclSocketRequestAO & ao)207 inline void OsclSocketI::Recv(RecvParam& param, OsclSocketRequestAO& ao)
208 {
209 if (!IsReady(ao))
210 return;
211 //send/recv behavior is undefined when socket is
212 //not connected, so disallow it.
213 if (!IsConnected(ao))
214 return ;
215 iSockServRecvRequest.Activate(¶m, ao);
216 }
217
RecvSuccess(RecvParam & param)218 inline void OsclSocketI::RecvSuccess(RecvParam& param)
219 {
220 //nothing needed
221 OSCL_UNUSED_ARG(param);
222 }
223
CancelRecv()224 inline void OsclSocketI::CancelRecv()
225 {
226 iSockServRecvRequest.CancelRequest();
227 }
228
RecvFrom(RecvFromParam & param,OsclSocketRequestAO & ao)229 inline void OsclSocketI::RecvFrom(RecvFromParam ¶m, OsclSocketRequestAO& ao)
230 {
231 if (!IsReady(ao))
232 return;
233 iSockServRecvFromRequest.Activate(¶m, ao);
234 }
235
RecvFromSuccess(RecvFromParam & param)236 inline void OsclSocketI::RecvFromSuccess(RecvFromParam& param)
237 {
238 //nothing needed
239 OSCL_UNUSED_ARG(param);
240 }
241
CancelRecvFrom()242 inline void OsclSocketI::CancelRecvFrom()
243 {
244 iSockServRecvFromRequest.CancelRequest();
245 }
246
Connect(ConnectParam & param,OsclSocketRequestAO & ao)247 inline void OsclSocketI::Connect(ConnectParam ¶m, OsclSocketRequestAO& ao)
248 {
249 if (!IsReady(ao))
250 return;
251 iSockServConnectRequest.Activate(¶m, ao);
252 }
253
CancelConnect()254 inline void OsclSocketI::CancelConnect()
255 {
256 iSockServConnectRequest.CancelRequest();
257 }
258
Accept(AcceptParam & param,OsclSocketRequestAO & ao)259 inline void OsclSocketI::Accept(AcceptParam& param, OsclSocketRequestAO& ao)
260 {
261 if (!IsReady(ao))
262 return;
263 iSockServAcceptRequest.Activate(¶m, ao);
264 }
265
CancelAccept()266 inline void OsclSocketI::CancelAccept()
267 {
268 iSockServAcceptRequest.CancelRequest();
269 }
270
Shutdown(ShutdownParam & param,OsclSocketRequestAO & ao)271 inline void OsclSocketI::Shutdown(ShutdownParam ¶m, OsclSocketRequestAO& ao)
272 {
273 if (!IsReady(ao))
274 return;
275 iSockServShutdownRequest.Activate(¶m, ao);
276 }
277
CancelShutdown()278 inline void OsclSocketI::CancelShutdown()
279 {
280 iSockServShutdownRequest.CancelRequest();
281 }
282
MakeAddr(OsclNetworkAddress & in,TOsclSockAddr & addr)283 bool OsclSocketI::MakeAddr(OsclNetworkAddress& in, TOsclSockAddr& addr)
284 {
285 //convert OsclNetworkAddress to TOsclSockAddr.
286 #ifdef OsclMakeSockAddr
287 bool ok;
288 OsclMakeSockAddr(addr, in.port, in.ipAddr.Str(), ok);
289 return ok;
290 #else
291 //default-- for older configurations that don't have the OsclMakeSockAddr macro.
292 addr.sin_family = OSCL_AF_INET;
293 addr.sin_port = htons(in.port);
294 addr.sin_addr.s_addr = inet_addr((const char*)in.ipAddr.Str());
295 return (addr.sin_addr.s_addr != INADDR_NONE);
296 #endif
297 }
298
MakeAddr(TOsclSockAddr & in,OsclNetworkAddress & addr)299 void OsclSocketI::MakeAddr(TOsclSockAddr& in, OsclNetworkAddress& addr)
300 {
301 #ifdef OsclUnMakeSockAddr
302 //convert TOsclSockAddrOut to OsclNetworkAddress
303 char* str;
304 OsclUnMakeSockAddr(in, str);
305 addr.ipAddr.Set(str);
306 #else
307 addr.ipAddr.Set(inet_ntoa(in.sin_addr));
308 #endif
309 }
310
Open(OsclSocketServI & aServer,uint32 addrFamily,uint32 sockType,uint32 protocol)311 int32 OsclSocketI::Open(OsclSocketServI& aServer, uint32 addrFamily, uint32 sockType, uint32 protocol)
312 //used to open a new tcp or udp socket.
313 {
314 #if(PV_OSCL_SOCKET_STATS_LOGGING)
315 iStats.Construct(this, &aServer);
316 #endif
317
318 bool ok;
319 int err = 0;
320
321 //create OS level socket.
322 #ifdef OsclSocket
323 OsclSocket(iSocket, addrFamily, sockType, protocol, ok, err);
324 #else
325 OSCL_UNUSED_ARG(addrFamily);
326 OSCL_UNUSED_ARG(sockType);
327 OSCL_UNUSED_ARG(protocol);
328 ok = false;
329 err = PVSOCK_ERR_NOT_IMPLEMENTED;
330 #endif
331
332 InitSocket(ok);
333 if (!ok)
334 return err;
335
336 if (protocol == OSCL_IPPROTO_UDP)
337 {
338 int32 bufsize = 65536;
339 OsclSetRecvBufferSize(iSocket, bufsize, ok, err);
340 }
341
342 //set socket to non-blocking mode.
343 #ifdef OsclSetNonBlocking
344 OsclSetNonBlocking(iSocket, ok, err);
345 #else
346 ok = false;
347 err = PVSOCK_ERR_NOT_IMPLEMENTED;
348 #endif
349
350 if (!ok)
351 {
352 Close();
353 return err;
354 }
355 return Open(aServer);
356 }
357
Open(OsclSocketServI & aServer)358 int32 OsclSocketI::Open(OsclSocketServI& aServer)
359 //used to open an accepted socket.
360 {
361 CONSTRUCT_STATS(this, &aServer);
362
363 iSocketServ = &aServer;
364
365 //nothing needed-- the pv server doesn't need
366 //to know about the socket yet.
367 return OsclErrNone;
368 }
369
IsOpen()370 inline bool OsclSocketI::IsOpen()
371 //see whether socket has been opened successfully.
372 {
373 return iSocketValid;
374 }
375
IsReady(OsclSocketRequestAO & ao)376 bool OsclSocketI::IsReady(OsclSocketRequestAO& ao)
377 //this routine does some error checks and will
378 //set socket error and complete the request for errors.
379 {
380 //make sure this socket is open
381 if (!IsOpen())
382 {
383 ao.iSocketError = PVSOCK_ERR_SOCK_NOT_OPEN;
384 ao.PendComplete(OSCL_REQUEST_ERR_GENERAL);
385 return false;
386 }
387 //make sure server is ok.
388 if (!iSocketServ)
389 {
390 ao.iSocketError = PVSOCK_ERR_SOCK_NO_SERV;
391 ao.PendComplete(OSCL_REQUEST_ERR_GENERAL);
392 return false;
393 }
394 if (!iSocketServ->IsServConnected())
395 {
396 //report the error from the server, if any.
397 ao.iSocketError = iSocketServ->iServError;
398 if (ao.iSocketError == 0)
399 ao.iSocketError = PVSOCK_ERR_SERV_NOT_CONNECTED;
400 ao.PendComplete(OSCL_REQUEST_ERR_GENERAL);
401 return false;
402 }
403 return true;
404 }
405
IsConnected(OsclSocketRequestAO & ao)406 bool OsclSocketI::IsConnected(OsclSocketRequestAO& ao)
407 {
408 if (!iSocketConnected)
409 {
410 ao.iSocketError = PVSOCK_ERR_SOCK_NOT_CONNECTED;
411 ao.PendComplete(OSCL_REQUEST_ERR_GENERAL);
412 return false;
413 }
414 return true;
415 }
416
InitSocket(bool valid)417 void OsclSocketI::InitSocket(bool valid)
418 {
419 iSocketValid = valid;
420 iSocketConnected = false;
421 }
422
423 #endif //pv socket server
424
425
426
427
428
429
430
431
432