• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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