LCOV - code coverage report
Current view: top level - nsprpub/pr/src/io - prpolevt.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 49 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  *********************************************************************
       8             :  *
       9             :  * Pollable events
      10             :  *
      11             :  * Pollable events are implemented using layered I/O.  The only
      12             :  * I/O methods that are implemented for pollable events are poll
      13             :  * and close.  No other methods can be invoked on a pollable
      14             :  * event.
      15             :  *
      16             :  * A pipe or socket pair is created and the pollable event layer
      17             :  * is pushed onto the read end.  A pointer to the write end is
      18             :  * saved in the PRFilePrivate structure of the pollable event.
      19             :  *
      20             :  *********************************************************************
      21             :  */
      22             : 
      23             : #include "prinit.h"
      24             : #include "prio.h"
      25             : #include "prmem.h"
      26             : #include "prerror.h"
      27             : #include "prlog.h"
      28             : 
      29             : /*
      30             :  * These internal functions are declared in primpl.h,
      31             :  * but we can't include primpl.h because the definition
      32             :  * of struct PRFilePrivate in this file (for the pollable
      33             :  * event layer) will conflict with the definition of
      34             :  * struct PRFilePrivate in primpl.h (for the NSPR layer).
      35             :  */
      36             : extern PRIntn _PR_InvalidInt(void);
      37             : extern PRInt64 _PR_InvalidInt64(void);
      38             : extern PRStatus _PR_InvalidStatus(void);
      39             : extern PRFileDesc *_PR_InvalidDesc(void);
      40             : 
      41             : /*
      42             :  * PRFilePrivate structure for the NSPR pollable events layer
      43             :  */
      44             : struct PRFilePrivate {
      45             :     PRFileDesc *writeEnd;  /* the write end of the pipe/socketpair */
      46             : };
      47             : 
      48             : static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd);
      49             : 
      50             : static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
      51             :     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
      52             : 
      53             : static PRIOMethods _pr_polevt_methods = {
      54             :     PR_DESC_LAYERED,
      55             :     _pr_PolEvtClose,
      56             :     (PRReadFN)_PR_InvalidInt,
      57             :     (PRWriteFN)_PR_InvalidInt,
      58             :     (PRAvailableFN)_PR_InvalidInt,
      59             :     (PRAvailable64FN)_PR_InvalidInt64,
      60             :     (PRFsyncFN)_PR_InvalidStatus,
      61             :     (PRSeekFN)_PR_InvalidInt,
      62             :     (PRSeek64FN)_PR_InvalidInt64,
      63             :     (PRFileInfoFN)_PR_InvalidStatus,
      64             :     (PRFileInfo64FN)_PR_InvalidStatus,
      65             :     (PRWritevFN)_PR_InvalidInt,        
      66             :     (PRConnectFN)_PR_InvalidStatus,        
      67             :     (PRAcceptFN)_PR_InvalidDesc,        
      68             :     (PRBindFN)_PR_InvalidStatus,        
      69             :     (PRListenFN)_PR_InvalidStatus,        
      70             :     (PRShutdownFN)_PR_InvalidStatus,    
      71             :     (PRRecvFN)_PR_InvalidInt,        
      72             :     (PRSendFN)_PR_InvalidInt,        
      73             :     (PRRecvfromFN)_PR_InvalidInt,    
      74             :     (PRSendtoFN)_PR_InvalidInt,        
      75             :     _pr_PolEvtPoll,
      76             :     (PRAcceptreadFN)_PR_InvalidInt,   
      77             :     (PRTransmitfileFN)_PR_InvalidInt, 
      78             :     (PRGetsocknameFN)_PR_InvalidStatus,    
      79             :     (PRGetpeernameFN)_PR_InvalidStatus,    
      80             :     (PRReservedFN)_PR_InvalidInt,    
      81             :     (PRReservedFN)_PR_InvalidInt,    
      82             :     (PRGetsocketoptionFN)_PR_InvalidStatus,
      83             :     (PRSetsocketoptionFN)_PR_InvalidStatus,
      84             :     (PRSendfileFN)_PR_InvalidInt, 
      85             :     (PRConnectcontinueFN)_PR_InvalidStatus, 
      86             :     (PRReservedFN)_PR_InvalidInt, 
      87             :     (PRReservedFN)_PR_InvalidInt, 
      88             :     (PRReservedFN)_PR_InvalidInt, 
      89             :     (PRReservedFN)_PR_InvalidInt
      90             : };
      91             : 
      92             : static PRDescIdentity _pr_polevt_id;
      93             : static PRCallOnceType _pr_polevt_once_control;
      94             : static PRStatus PR_CALLBACK _pr_PolEvtInit(void);
      95             : 
      96           0 : static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
      97             :     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
      98             : {
      99           0 :     return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
     100             : }
     101             : 
     102           0 : static PRStatus PR_CALLBACK _pr_PolEvtInit(void)
     103             : {
     104           0 :     _pr_polevt_id = PR_GetUniqueIdentity("NSPR pollable events");
     105           0 :     if (PR_INVALID_IO_LAYER == _pr_polevt_id) {
     106           0 :         return PR_FAILURE;
     107             :     }
     108           0 :     return PR_SUCCESS;
     109             : }
     110             : 
     111             : #if !defined(XP_UNIX)
     112             : #define USE_TCP_SOCKETPAIR
     113             : #endif
     114             : 
     115             : PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
     116             : {
     117             :     PRFileDesc *event;
     118             :     PRFileDesc *fd[2]; /* fd[0] is the read end; fd[1] is the write end */
     119             : #ifdef USE_TCP_SOCKETPAIR
     120             :     PRSocketOptionData socket_opt;
     121             :     PRStatus rv;
     122             : #endif
     123             : 
     124           0 :     fd[0] = fd[1] = NULL;
     125             : 
     126           0 :     if (PR_CallOnce(&_pr_polevt_once_control, _pr_PolEvtInit) == PR_FAILURE) {
     127           0 :         return NULL;
     128             :     }
     129             : 
     130           0 :     event = PR_CreateIOLayerStub(_pr_polevt_id, &_pr_polevt_methods);
     131           0 :     if (NULL == event) {
     132           0 :         goto errorExit;
     133             :     } 
     134           0 :     event->secret = PR_NEW(PRFilePrivate);
     135           0 :     if (event->secret == NULL) {
     136           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     137           0 :         goto errorExit;
     138             :     }
     139             : 
     140             : #ifndef USE_TCP_SOCKETPAIR
     141           0 :     if (PR_CreatePipe(&fd[0], &fd[1]) == PR_FAILURE) {
     142           0 :         fd[0] = fd[1] = NULL;
     143           0 :         goto errorExit;
     144             :     }
     145             : #else
     146             :     if (PR_NewTCPSocketPair(fd) == PR_FAILURE) {
     147             :         fd[0] = fd[1] = NULL;
     148             :         goto errorExit;
     149             :     }
     150             :         /*
     151             :          * set the TCP_NODELAY option to reduce notification latency
     152             :          */
     153             :     socket_opt.option = PR_SockOpt_NoDelay;
     154             :     socket_opt.value.no_delay = PR_TRUE;
     155             :     rv = PR_SetSocketOption(fd[1], &socket_opt);
     156             :     PR_ASSERT(PR_SUCCESS == rv);
     157             : #endif
     158             : 
     159           0 :     event->secret->writeEnd = fd[1];
     160           0 :     if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, event) == PR_FAILURE) {
     161           0 :         goto errorExit;
     162             :     }
     163             : 
     164           0 :     return fd[0];
     165             : 
     166             : errorExit:
     167           0 :     if (fd[0]) {
     168           0 :         PR_Close(fd[0]);
     169           0 :         PR_Close(fd[1]);
     170             :     }
     171           0 :     if (event) {
     172           0 :         PR_DELETE(event->secret);
     173           0 :         event->dtor(event);
     174             :     }
     175           0 :     return NULL;
     176             : }
     177             : 
     178           0 : static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd)
     179             : {
     180             :     PRFileDesc *event;
     181             : 
     182           0 :     event = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
     183           0 :     PR_ASSERT(NULL == event->higher && NULL == event->lower);
     184           0 :     PR_Close(fd);
     185           0 :     PR_Close(event->secret->writeEnd);
     186           0 :     PR_DELETE(event->secret);
     187           0 :     event->dtor(event);
     188           0 :     return PR_SUCCESS;
     189             : }
     190             : 
     191             : PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
     192             : {
     193           0 :     return PR_Close(event);
     194             : }
     195             : 
     196             : static const char magicChar = '\x38';
     197             : 
     198             : PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
     199             : {
     200           0 :     if (PR_Write(event->secret->writeEnd, &magicChar, 1) != 1) {
     201           0 :         return PR_FAILURE;
     202             :     }
     203           0 :     return PR_SUCCESS;
     204             : }
     205             : 
     206             : PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
     207             : {
     208             :     char buf[1024];
     209             :     PRInt32 nBytes;
     210             : #ifdef DEBUG
     211             :     PRIntn i;
     212             : #endif
     213             : 
     214           0 :     nBytes = PR_Read(event->lower, buf, sizeof(buf));
     215           0 :     if (nBytes == -1) {
     216           0 :         return PR_FAILURE;
     217             :     }
     218             : 
     219             : #ifdef DEBUG
     220             :     /*
     221             :      * Make sure people do not write to the pollable event fd
     222             :      * directly.
     223             :      */
     224           0 :     for (i = 0; i < nBytes; i++) {
     225           0 :         PR_ASSERT(buf[i] == magicChar);
     226             :     }
     227             : #endif
     228             : 
     229           0 :     return PR_SUCCESS;
     230             : }

Generated by: LCOV version 1.13