nsprpub/pr/src/io/prpolevt.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     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/. */
     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  */
    23 #include "prinit.h"
    24 #include "prio.h"
    25 #include "prmem.h"
    26 #include "prerror.h"
    27 #include "prlog.h"
    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);
    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 };
    48 static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd);
    50 static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
    51     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
    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 };
    92 static PRDescIdentity _pr_polevt_id;
    93 static PRCallOnceType _pr_polevt_once_control;
    94 static PRStatus PR_CALLBACK _pr_PolEvtInit(void);
    96 static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
    97     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
    98 {
    99     return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
   100 }
   102 static PRStatus PR_CALLBACK _pr_PolEvtInit(void)
   103 {
   104     _pr_polevt_id = PR_GetUniqueIdentity("NSPR pollable events");
   105     if (PR_INVALID_IO_LAYER == _pr_polevt_id) {
   106         return PR_FAILURE;
   107     }
   108     return PR_SUCCESS;
   109 }
   111 #if !defined(XP_UNIX)
   112 #define USE_TCP_SOCKETPAIR
   113 #endif
   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
   124     fd[0] = fd[1] = NULL;
   126     if (PR_CallOnce(&_pr_polevt_once_control, _pr_PolEvtInit) == PR_FAILURE) {
   127         return NULL;
   128     }
   130     event = PR_CreateIOLayerStub(_pr_polevt_id, &_pr_polevt_methods);
   131     if (NULL == event) {
   132         goto errorExit;
   133     } 
   134     event->secret = PR_NEW(PRFilePrivate);
   135     if (event->secret == NULL) {
   136         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   137         goto errorExit;
   138     }
   140 #ifndef USE_TCP_SOCKETPAIR
   141     if (PR_CreatePipe(&fd[0], &fd[1]) == PR_FAILURE) {
   142         fd[0] = fd[1] = NULL;
   143         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
   159     event->secret->writeEnd = fd[1];
   160     if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, event) == PR_FAILURE) {
   161         goto errorExit;
   162     }
   164     return fd[0];
   166 errorExit:
   167     if (fd[0]) {
   168         PR_Close(fd[0]);
   169         PR_Close(fd[1]);
   170     }
   171     if (event) {
   172         PR_DELETE(event->secret);
   173         event->dtor(event);
   174     }
   175     return NULL;
   176 }
   178 static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd)
   179 {
   180     PRFileDesc *event;
   182     event = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
   183     PR_ASSERT(NULL == event->higher && NULL == event->lower);
   184     PR_Close(fd);
   185     PR_Close(event->secret->writeEnd);
   186     PR_DELETE(event->secret);
   187     event->dtor(event);
   188     return PR_SUCCESS;
   189 }
   191 PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
   192 {
   193     return PR_Close(event);
   194 }
   196 static const char magicChar = '\x38';
   198 PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
   199 {
   200     if (PR_Write(event->secret->writeEnd, &magicChar, 1) != 1) {
   201         return PR_FAILURE;
   202     }
   203     return PR_SUCCESS;
   204 }
   206 PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
   207 {
   208     char buf[1024];
   209     PRInt32 nBytes;
   210 #ifdef DEBUG
   211     PRIntn i;
   212 #endif
   214     nBytes = PR_Read(event->lower, buf, sizeof(buf));
   215     if (nBytes == -1) {
   216         return PR_FAILURE;
   217     }
   219 #ifdef DEBUG
   220     /*
   221      * Make sure people do not write to the pollable event fd
   222      * directly.
   223      */
   224     for (i = 0; i < nBytes; i++) {
   225         PR_ASSERT(buf[i] == magicChar);
   226     }
   227 #endif
   229     return PR_SUCCESS;
   230 }

mercurial