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 #include "oscl_socket_tuneables.h"
19
20 #if(PV_SOCKET_SERVER)
21
22 #include "oscl_socket_imp.h"
23 #include "oscl_socket_serv_imp.h"
24 #include "oscl_scheduler_ao.h"
25 #include "oscl_socket_method.h"
26 #include "oscl_error.h"
27
28 /** This file contains all the routines called by
29 * the PV Socket server ProcessSocketRequests routine to process active
30 * requests in the select loop.
31 */
32
33 //Logger macro for socket server logging.
34 #if(PV_OSCL_SOCKET_SERVER_LOGGER_OUTPUT)
35 #include "pvlogger.h"
36 #define LOGSERV(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iSocketServ->iLogger,PVLOGMSG_DEBUG,m);
37 #else
38 #define LOGSERV(m)
39 #endif
40 /*
41 //disable this if it's too much
42 #undef LOGSERV
43 #define LOGSERV
44 */
45
46 //Stats macros for use with OsclSocketI
47 #if(PV_OSCL_SOCKET_STATS_LOGGING)
48 #define ADD_STATS(x,y) iStats.Add(x,y)
49 #define ADD_STATSP(x,y,z) iStats.Add(x,y,z)
50 #define CONSTRUCT_STATS(x,y) iStats.Construct(x,y)
51 #else
52 #define ADD_STATS(x,y)
53 #define ADD_STATSP(x,y,z)
54 #define CONSTRUCT_STATS(x,y)
55 #endif
56
57 /**
58 * Server calls this to process an active Connect request.
59 *
60 * This is called under the server thread or server AO during
61 * the select loop.
62 *
63 * This routine may complete the request, or may set flags in the
64 * read/write/except set to be monitored during the next select call.
65 *
66 */
ProcessConnect(OsclSocketServRequestQElem * aElem)67 void OsclSocketI::ProcessConnect(OsclSocketServRequestQElem* aElem)
68 {
69 bool iscomplete = false;
70 int sockerr = 0;
71 int32 complete = 0;
72 OsclSocketRequest *req = aElem->iSocketRequest;
73 if (aElem->iSelect)
74 {
75 //check for completion by examining
76 //writeset and exceptset
77 bool ok, success, fail;
78 #if (PV_SOCKET_SERVER_SELECT)
79 OsclConnectComplete(iSocket,
80 iSocketServ->iWriteset,
81 iSocketServ->iExceptset,
82 success,
83 fail,
84 ok,
85 sockerr);
86 #else
87 //since there was no select call we have to do it now.
88 fd_set readset, writeset, exceptset;
89 FD_ZERO(&writeset);
90 FD_ZERO(&readset);
91 FD_ZERO(&exceptset);
92 FD_SET(iSocket, &writeset);
93 FD_SET(iSocket, &exceptset);
94 timeval timeout;
95 timeout.tv_sec = 0;
96 timeout.tv_usec = 0;
97 int nfds = iSocket + 1;
98 int serverr;
99 int nhandles;
100 OsclSocketSelect(nfds, readset, writeset, exceptset, timeout, ok, serverr, nhandles);
101 if (!ok)
102 {
103 //select failed.
104 sockerr = serverr;
105 complete = OSCL_REQUEST_ERR_GENERAL;
106 iscomplete = true;
107 }
108 else if (!nhandles)
109 {
110 //keep waiting.
111 success = fail = false;
112 }
113 else
114 {
115 //examine results
116 OsclConnectComplete(iSocket,
117 writeset,
118 exceptset,
119 success,
120 fail,
121 ok,
122 sockerr);
123 }
124 #endif
125
126 if (success)
127 {
128 //done, no error.
129 ADD_STATS(req->iParam->iFxn, EOsclSocket_Writable);
130
131 iSocketConnected = true;
132 complete = OSCL_REQUEST_ERR_NONE;
133 iscomplete = true;
134 }
135 else if (fail)
136 {
137 //done, with error.
138 ADD_STATS(req->iParam->iFxn, EOsclSocket_Except);
139
140 complete = OSCL_REQUEST_ERR_GENERAL;
141 iscomplete = true;
142 }
143 else
144 {
145 //keep waiting
146 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
147 }
148 }
149 else
150 {
151 //Start connecting
152 ConnectParam *param = (ConnectParam*)req->iParam;
153 TOsclSockAddr addr;
154 MakeAddr(param->iAddr, addr);
155 bool ok, wouldblock;
156 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
157 OsclConnect(iSocket, addr, ok, sockerr, wouldblock);
158 if (!ok)
159 {
160 if (wouldblock)
161 {
162 //we expect a non-blocking socket to return an error...
163 //start monitoring the writeset and exceptset.
164 aElem->iSelect = (OSCL_WRITESET_FLAG | OSCL_EXCEPTSET_FLAG);
165 }
166 else
167 {
168 //connect error.
169 complete = OSCL_REQUEST_ERR_GENERAL;
170 iscomplete = true;
171 }
172 }
173 else
174 {
175 //Finished.
176 iSocketConnected = true;
177 complete = OSCL_REQUEST_ERR_NONE;
178 iscomplete = true;
179 }
180 }
181
182 //either keep monitoring activity, or complete the request.
183 if (!iscomplete)
184 {
185 LOGSERV((0, "OsclSocketI::ProcessConnect (0x%x) select=true", this));
186 OSCL_ASSERT(aElem->iSelect);//should have bits set.
187 }
188 else
189 {
190 LOGSERV((0, "OsclSocketI::ProcessConnect (0x%x) request complete %d sockerr %d", this, complete, sockerr));
191 req->Complete(aElem, complete, sockerr);
192 }
193 }
194
195 /**
196 * Server calls this to process an active Shutdown request.
197 *
198 * This is called under the server thread or server AO during
199 * the select loop.
200 *
201 * This routine may complete the request, or may set flags in the
202 * read/write/except set to be monitored during the next select call.
203 *
204 */
ProcessShutdown(OsclSocketServRequestQElem * aElem)205 void OsclSocketI::ProcessShutdown(OsclSocketServRequestQElem* aElem)
206 {
207 int err = 0;
208 int32 complete = 0;
209
210 OsclSocketRequest *req = aElem->iSocketRequest;
211 {
212 ShutdownParam* param = (ShutdownParam*)req->iParam;
213 int how = GetShutdown(param->iHow);
214 bool ok;
215 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
216 OsclShutdown(iSocket, how, ok, err);
217 if (!ok)
218 {
219 //shutdown error
220 complete = OSCL_REQUEST_ERR_GENERAL;
221 }
222 else
223 {
224 complete = OSCL_REQUEST_ERR_NONE;
225 }
226 }
227 LOGSERV((0, "OsclSocketI::ProcessShutdown (0x%x) request complete %d sockerr %d", this, complete, err));
228 req->Complete(aElem, complete, err);
229 }
230
231 /**
232 * Server calls this to process an active Accept request.
233 *
234 * This is called under the server thread or server AO during
235 * the select loop.
236 *
237 * This routine may complete the request, or may set flags in the
238 * read/write/except set to be monitored during the next select call.
239 *
240 */
ProcessAccept(OsclSocketServRequestQElem * aElem)241 void OsclSocketI::ProcessAccept(OsclSocketServRequestQElem* aElem)
242 {
243 bool iscomplete = false;
244 int sockerr = 0;
245 int32 complete = 0;
246 OsclSocketRequest *req = aElem->iSocketRequest;
247 if (!aElem->iSelect)
248 {
249 //start monitoring.
250 AcceptParam* param = (AcceptParam*)req->iParam;
251 if (!param->iBlankSocket)
252 {
253 //bad request.
254 complete = OSCL_REQUEST_ERR_GENERAL;
255 iscomplete = true;
256 sockerr = PVSOCK_ERR_BAD_PARAM;//unexpected
257 }
258 else
259 {
260 aElem->iSelect = (OSCL_READSET_FLAG | OSCL_EXCEPTSET_FLAG);
261 }
262 }
263 #if (PV_SOCKET_SERVER_SELECT)
264 else if (FD_ISSET(iSocket, &iSocketServ->iExceptset))
265 {
266 ADD_STATS(req->iParam->iFxn, EOsclSocket_Except);
267
268 bool ok;
269 OsclGetAsyncSockErr(iSocket, ok, sockerr);
270 complete = OSCL_REQUEST_ERR_GENERAL;
271 iscomplete = true;
272 }
273 else if (FD_ISSET(iSocket, &iSocketServ->iReadset))
274 {
275 //socket is readable, we can do an accept call now.
276 ADD_STATS(req->iParam->iFxn, EOsclSocket_Readable);
277 #else
278 {
279 //try the accept.
280 #endif
281 TOsclSocket acceptsock;
282 bool ok, wouldblock;
283 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
284 OsclAccept(iSocket, acceptsock, ok, sockerr, wouldblock);
285 if (!ok)
286 {
287 if (wouldblock)
288 {
289 #if (PV_SOCKET_SERVER_SELECT)
290 //we don't expect wouldblock when socket is readable.
291 complete = OSCL_REQUEST_ERR_GENERAL;
292 iscomplete = true;
293 #else
294 //keep waiting for socket to be readable.
295 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
296 #endif
297 }
298 else
299 {
300 //accept error
301 complete = OSCL_REQUEST_ERR_GENERAL;
302 iscomplete = true;
303 }
304 }
305 else
306 {
307 //Set accept socket to non-blocking mode.
308 OsclSetNonBlocking(acceptsock, ok, sockerr);
309 if (!ok)
310 {
311 OsclCloseSocket(acceptsock, ok, sockerr);
312 complete = OSCL_REQUEST_ERR_GENERAL;
313 iscomplete = true;
314 }
315 else
316 {
317 //Save the accept socket in the blank socket that was provided
318 //in the Accept command.
319 AcceptParam* param = (AcceptParam*)req->iParam;
320 param->iBlankSocket->iSocket = acceptsock;
321 //the blank socket is now valid and connected.
322 param->iBlankSocket->InitSocket(true);
323 param->iBlankSocket->iSocketConnected = true;
324 complete = OSCL_REQUEST_ERR_NONE;
325 iscomplete = true;
326 }
327 }
328 }
329 #if (PV_SOCKET_SERVER_SELECT)
330 else
331 {
332 //keep waiting for socket to be readable.
333 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
334 }
335 #endif
336
337 //either keep monitoring activity, or complete the request.
338 if (!iscomplete)
339 {
340 LOGSERV((0, "OsclSocketI::ProcessAccept (0x%x) select=true", this));
341 OSCL_ASSERT(aElem->iSelect);
342 }
343 else
344 {
345 LOGSERV((0, "OsclSocketI::ProcessAccept (0x%x) request complete %d sockerr %d", this, complete, sockerr));
346 req->Complete(aElem, complete, sockerr);
347 }
348 }
349
350 /**
351 * Server calls this to process an active Send request.
352 *
353 * This is called under the server thread or server AO during
354 * the select loop.
355 *
356 * This routine may complete the request, or may set flags in the
357 * read/write/except set to be monitored during the next select call.
358 *
359 */
360 void OsclSocketI::ProcessSend(OsclSocketServRequestQElem* aElem)
361 {
362 bool iscomplete = false;
363 int32 complete = 0;
364 int sockerr = 0;
365 OsclSocketRequest *req = aElem->iSocketRequest;
366 if (!aElem->iSelect)
367 {
368 //start monitoring.
369 //don't monitor exceptset b/c windows reports some false errors.
370 SendParam *param = (SendParam*)req->iParam;
371 if (!param->iBufSend.iPtr)
372 {
373 //bad request
374 complete = OSCL_REQUEST_ERR_GENERAL;
375 iscomplete = true;
376 sockerr = PVSOCK_ERR_BAD_PARAM;
377 }
378 else
379 {
380 aElem->iSelect = (OSCL_WRITESET_FLAG);
381 }
382 }
383 #if (PV_SOCKET_SERVER_SELECT)
384 else if (FD_ISSET(iSocket, &iSocketServ->iWriteset))
385 {
386 //socket is writable, send data
387 ADD_STATS(req->iParam->iFxn, EOsclSocket_Writable);
388 #else
389 {
390 //go ahead and try to send
391 #endif
392 SendParam *param = (SendParam*)req->iParam;
393 int nbytes;
394 bool ok, wouldblock;
395 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
396 OsclSend(iSocket,
397 param->iBufSend.iPtr + param->iXferLen,
398 param->iBufSend.iLen - param->iXferLen,
399 ok,
400 sockerr,
401 nbytes,
402 wouldblock);
403
404 //check send result...
405 if (!ok)
406 {
407 if (wouldblock)
408 {
409 //non-blocking sockets return this when there's no receiver.
410 //just keep waiting.
411 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
412 }
413 else
414 {
415 //send error
416 complete = OSCL_REQUEST_ERR_GENERAL;
417 iscomplete = true;
418 }
419 }
420 else
421 {
422 //sent data.
423 ADD_STATSP(req->iParam->iFxn, EOsclSocket_DataSent, nbytes);
424
425 param->iXferLen += nbytes;
426
427 //Check for completion
428 if (param->iXferLen == param->iBufSend.iLen)
429 {
430 //all data sent.
431 complete = OSCL_REQUEST_ERR_NONE;
432 iscomplete = true;
433 }
434 else if (nbytes == 0)
435 {
436 //connection closed
437 complete = OSCL_REQUEST_ERR_GENERAL;
438 iscomplete = true;
439 //(sockerr will be zero in this case.)
440 }
441 else
442 {
443 //keep sending data.
444 ;
445 }
446 }
447 }
448 #if (PV_SOCKET_SERVER_SELECT)
449 else
450 {
451 //keep waiting for socket to be writable.
452 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
453 }
454 #endif
455
456 //either keep monitoring activity, or complete the request.
457 if (!iscomplete)
458 {
459 LOGSERV((0, "OsclSocketI::ProcessSend (0x%x) select=true", this));
460 OSCL_ASSERT(aElem->iSelect);
461 }
462 else
463 {
464 LOGSERV((0, "OsclSocketI::ProcessSend (0x%x) request complete %d sockerr %d", this, complete, sockerr));
465 req->Complete(aElem, complete, sockerr);
466 }
467 }
468
469 /**
470 * Server calls this to process an active SendTo request.
471 *
472 * This is called under the server thread or server AO during
473 * the select loop.
474 *
475 * This routine may complete the request, or may set flags in the
476 * read/write/except set to be monitored during the next select call.
477 *
478 */
479 void OsclSocketI::ProcessSendTo(OsclSocketServRequestQElem* aElem)
480 {
481 bool iscomplete = false;
482 int32 complete = 0;
483 int sockerr = 0;
484 OsclSocketRequest *req = aElem->iSocketRequest;
485 if (!aElem->iSelect)
486 {
487 //start monitoring. don't monitor exceptset b/c windows reports some false errors.
488 SendToParam *param = (SendToParam*)req->iParam;
489 if (!param->iBufSend.iPtr)
490 {
491 //bad request
492 complete = OSCL_REQUEST_ERR_GENERAL;
493 iscomplete = true;
494 sockerr = PVSOCK_ERR_BAD_PARAM;//unexpected
495 }
496 else
497 {
498 aElem->iSelect = (OSCL_WRITESET_FLAG);
499 }
500 }
501 #if (PV_SOCKET_SERVER_SELECT)
502 else if (FD_ISSET(iSocket, &iSocketServ->iWriteset))
503 {
504 //socket is writable, send data
505 ADD_STATS(req->iParam->iFxn, EOsclSocket_Writable);
506 #else
507 {
508 //go ahead and try to send
509 #endif
510
511 SendToParam *param = (SendToParam*)req->iParam;
512 int nbytes;
513 bool wouldblock, ok;
514 TOsclSockAddr toaddr;
515 MakeAddr(param->iAddr, toaddr);
516 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
517 OsclSendTo(iSocket,
518 param->iBufSend.iPtr + param->iXferLen,
519 param->iBufSend.iLen - param->iXferLen,
520 toaddr,
521 ok,
522 sockerr,
523 nbytes,
524 wouldblock);
525
526 if (!ok)
527 {
528 if (wouldblock)
529 {
530 //nonblocking socket returns this error
531 //just keep waiting
532 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
533 }
534 else
535 {
536 //sendto error
537 complete = OSCL_REQUEST_ERR_GENERAL;
538 iscomplete = true;
539 }
540 }
541 else
542 {
543 //sent data.
544 ADD_STATSP(req->iParam->iFxn, EOsclSocket_DataSent, nbytes);
545
546 param->iXferLen += nbytes;
547
548 //Check for completion
549 if (param->iXferLen == param->iBufSend.iLen)
550 {
551 //all data sent.
552 complete = OSCL_REQUEST_ERR_NONE;
553 iscomplete = true;
554 }
555 else if (nbytes == 0)
556 {
557 //connection closed
558 complete = OSCL_REQUEST_ERR_GENERAL;
559 iscomplete = true;
560 //(sockerr will be zero in this case)
561 }
562 else
563 {
564 //keep sending data.
565 ;
566 }
567 }
568 }
569 #if (PV_SOCKET_SERVER_SELECT)
570 else
571 {
572 //keep waiting for socket to be writable.
573 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
574 }
575 #endif
576
577 //either keep monitoring activity, or complete the request.
578 if (!iscomplete)
579 {
580 LOGSERV((0, "OsclSocketI::ProcessSendTo (0x%x) select=true", this));
581 OSCL_ASSERT(aElem->iSelect);
582 }
583 else
584 {
585 LOGSERV((0, "OsclSocketI::ProcessSendTo (0x%x) request complete %d sockerr %d", this, complete, sockerr));
586 req->Complete(aElem, complete, sockerr);
587 }
588 }
589
590 /**
591 * Server calls this to process an active Recv request.
592 *
593 * This is called under the server thread or server AO during
594 * the select loop.
595 *
596 * This routine may complete the request, or may set flags in the
597 * read/write/except set to be monitored during the next select call.
598 *
599 */
600 void OsclSocketI::ProcessRecv(OsclSocketServRequestQElem* aElem)
601 {
602 bool iscomplete = false;
603 int sockerr = 0;
604 int32 complete = 0;
605 OsclSocketRequest *req = aElem->iSocketRequest;
606 if (!aElem->iSelect)
607 {
608 //start monitoring. don't monitor exceptset b/c windows reports some false errors.
609 RecvParam* param = (RecvParam*)req->iParam;
610 if (!param->iBufRecv.iPtr)
611 {
612 //bad request.
613 complete = OSCL_REQUEST_ERR_GENERAL;
614 iscomplete = true;
615 sockerr = PVSOCK_ERR_BAD_PARAM;//unexpected
616 }
617 else
618 {
619 aElem->iSelect = (OSCL_READSET_FLAG);
620 }
621 }
622 #if (PV_SOCKET_SERVER_SELECT)
623 else if (FD_ISSET(iSocket, &iSocketServ->iReadset))
624 {
625 //socket is readable, get data.
626 ADD_STATS(req->iParam->iFxn, EOsclSocket_Readable);
627 #else
628 {
629 //try to read
630 #endif
631 RecvParam* param = (RecvParam*)req->iParam;
632 int nbytes;
633 bool ok, wouldblock;
634 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
635 OsclRecv(iSocket,
636 param->iBufRecv.iPtr + param->iBufRecv.iLen,
637 param->iBufRecv.iMaxLen - param->iBufRecv.iLen,
638 ok,
639 sockerr,
640 nbytes,
641 wouldblock);
642
643 //Check for completion or error.
644 if (!ok)
645 {
646 if (wouldblock)
647 {
648 //nonblocking sockets return this when there's no
649 //data.
650 //keep waiting for data.
651 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
652 }
653 else
654 {
655 //recv error
656 complete = OSCL_REQUEST_ERR_GENERAL;
657 iscomplete = true;
658 }
659 }
660 else if (nbytes > 0)
661 {
662 //got some data
663 ADD_STATSP(req->iParam->iFxn, EOsclSocket_DataRecv, nbytes);
664
665 param->iBufRecv.iLen += nbytes;
666
667 complete = OSCL_REQUEST_ERR_NONE;
668 iscomplete = true;
669 }
670 else
671 {
672 //this usually means connection was closed.
673 complete = OSCL_REQUEST_ERR_GENERAL;
674 iscomplete = true;
675 //(sockerr will be zero in this case)
676 }
677 }
678 #if (PV_SOCKET_SERVER_SELECT)
679 else
680 {
681 //keep waiting for socket to be readable.
682 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
683 }
684 #endif
685
686 //either keep monitoring activity, or complete the request.
687 if (!iscomplete)
688 {
689 LOGSERV((0, "OsclSocketI::ProcessRecv (0x%x) select=true", this));
690 OSCL_ASSERT(aElem->iSelect);
691 }
692 else
693 {
694 LOGSERV((0, "OsclSocketI::ProcessRecv (0x%x) request complete %d sockerr %d", this, complete, sockerr));
695 req->Complete(aElem, complete, sockerr);
696 }
697 }
698
699 /**
700 * Server calls this to process an active RecvFrom request.
701 *
702 * This is called under the server thread or server AO during
703 * the select loop.
704 *
705 * This routine may complete the request, or may set flags in the
706 * read/write/except set to be monitored during the next select call.
707 *
708 */
709 void OsclSocketI::ProcessRecvFrom(OsclSocketServRequestQElem* aElem)
710 {
711 bool iscomplete = false;
712 int sockerr = 0;
713 int32 complete = 0;
714 OsclSocketRequest *req = aElem->iSocketRequest;
715 if (!aElem->iSelect)
716 {
717 //start monitoring. don't monitor exceptset b/c windows reports some false errors.
718 RecvFromParam* param = (RecvFromParam*)req->iParam;
719 if (!param->iBufRecv.iPtr)
720 {
721 //bad request.
722 complete = OSCL_REQUEST_ERR_GENERAL;
723 iscomplete = true;
724 sockerr = PVSOCK_ERR_BAD_PARAM;//unexpected
725 }
726 else
727 {
728 aElem->iSelect = (OSCL_READSET_FLAG);
729 }
730 }
731 #if (PV_SOCKET_SERVER_SELECT)
732 else if (FD_ISSET(iSocket, &iSocketServ->iReadset))
733 {
734 //socket is readable, get data.
735 ADD_STATS(req->iParam->iFxn, EOsclSocket_Readable);
736 #else
737 {
738 //try the read
739 #endif
740
741 //we loop through multiple "recvfrom" calls and stop when
742 //either a byte limit is reached or else no more data is available
743 //without waiting.
744 bool loop;
745 uint32 loopcount;
746 for (loop = true, loopcount = 0; loop; loopcount++)
747 {
748 loop = false;
749
750 RecvFromParam* param = (RecvFromParam*)req->iParam;
751 int nbytes;
752 bool ok, wouldblock;
753 TOsclSockAddr sourceaddr;
754 TOsclSockAddrLen sourceaddrlen = sizeof(sourceaddr);
755 ADD_STATS(req->iParam->iFxn, EOsclSocket_OS);
756 OsclRecvFrom(iSocket,
757 param->iBufRecv.iPtr + param->iBufRecv.iLen,
758 param->iBufRecv.iMaxLen - param->iBufRecv.iLen,
759 &sourceaddr,
760 &sourceaddrlen,
761 ok,
762 sockerr,
763 nbytes,
764 wouldblock);
765
766 //Check for completion or error.
767 if (!ok)
768 {
769 if (wouldblock)
770 {
771 //nonblocking sockets will return an error when
772 //there's no data.
773 if (loopcount == 0)
774 {
775 //keep waiting for data.
776 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
777 }
778 else
779 {
780 //if we already got some data, don't wait for more.
781 complete = OSCL_REQUEST_ERR_NONE;
782 iscomplete = true;
783 }
784 }
785 else
786 {
787 //recvfrom error
788 complete = OSCL_REQUEST_ERR_GENERAL;
789 iscomplete = true;
790 }
791 }
792 else if (nbytes > 0)
793 {
794 //got some data.
795 ADD_STATSP(req->iParam->iFxn, EOsclSocket_DataRecv, nbytes);
796
797 param->iBufRecv.iLen += nbytes;
798 if (param->iPacketLen)
799 param->iPacketLen->push_back(nbytes);
800
801 if (sourceaddrlen > 0)
802 {
803 //convert the source address.
804 MakeAddr(sourceaddr, param->iAddr);
805 if (param->iPacketSource)
806 param->iPacketSource->push_back(param->iAddr);
807 }
808
809 //see whether to try and recv another packet
810 //when multi-packet recv is enabled, keep receiving
811 //as long as the free space is >= the multi recv limit.
812 if (param->iMultiMaxLen > 0
813 && (param->iBufRecv.iMaxLen - param->iBufRecv.iLen) >= param->iMultiMaxLen)
814 {
815 loop = true;
816 }
817 else
818 {
819 complete = OSCL_REQUEST_ERR_NONE;
820 iscomplete = true;
821 }
822 }
823 else
824 {
825 //this usually means connection was closed.
826 complete = OSCL_REQUEST_ERR_GENERAL;
827 iscomplete = true;
828 //(sockerr will be zero in this case)
829 }
830 }//for loop
831 }
832 #if (PV_SOCKET_SERVER_SELECT)
833 else
834 {
835 //keep waiting for socket to be readable.
836 ADD_STATS(req->iParam->iFxn, EOsclSocket_ServPoll);
837 }
838 #endif
839
840 //either keep monitoring activity, or complete the request.
841 if (!iscomplete)
842 {
843 LOGSERV((0, "OsclSocketI::ProcessRecvFrom (0x%x) select=true", this));
844 OSCL_ASSERT(aElem->iSelect);
845 }
846 else
847 {
848 LOGSERV((0, "OsclSocketI::ProcessRecvFrom (0x%x) request complete %d sockerr %d", this, complete, sockerr));
849 req->Complete(aElem, complete, sockerr);
850 }
851 }
852
853 #endif //PV_SOCKET_SERVER
854
855
856
857
858
859