LCOV - code coverage report
Current view: directory - nsprpub/pr/src/io - prlayer.c (source / functions) Found Hit Coverage
Test: app.info Lines: 330 115 34.8 %
Date: 2012-06-02 Functions: 42 13 31.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Netscape Portable Runtime (NSPR).
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998-2000
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /*
      39                 : ** File:        prlayer.c
      40                 : ** Description: Routines for handling pushable protocol modules on sockets.
      41                 : */
      42                 : 
      43                 : #include "primpl.h"
      44                 : #include "prerror.h"
      45                 : #include "prmem.h"
      46                 : #include "prlock.h"
      47                 : #include "prlog.h"
      48                 : #include "prio.h"
      49                 : 
      50                 : #include <string.h> /* for memset() */
      51                 : static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack);
      52                 : 
      53            1423 : void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd)
      54                 : {
      55            1423 :     PR_ASSERT(fd != NULL);
      56            1423 :     if (NULL != fd->lower) fd->lower->higher = fd->higher;
      57            1423 :     if (NULL != fd->higher) fd->higher->lower = fd->lower;
      58            1423 :     PR_DELETE(fd);
      59            1423 : }
      60                 : 
      61                 : /*
      62                 : ** Default methods that just call down to the next fd.
      63                 : */
      64               0 : static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd)
      65                 : {
      66                 :     PRFileDesc *top, *lower;
      67                 :         PRStatus rv;
      68                 : 
      69               0 :     PR_ASSERT(fd != NULL);
      70               0 :     PR_ASSERT(fd->lower != NULL);
      71               0 :     PR_ASSERT(fd->secret == NULL);
      72               0 :     PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED);
      73                 : 
      74               0 :         if (PR_IO_LAYER_HEAD == fd->identity) {
      75                 :                 /*
      76                 :                  * new style stack; close all the layers, before deleting the
      77                 :                  * stack head
      78                 :                  */
      79               0 :                 rv = fd->lower->methods->close(fd->lower);
      80               0 :                 _PR_DestroyIOLayer(fd);
      81               0 :                 return rv;
      82               0 :         } else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) {
      83                 :                 /*
      84                 :                  * lower layers of new style stack
      85                 :                  */
      86               0 :                 lower = fd->lower;
      87                 :                 /*
      88                 :                  * pop and cleanup current layer
      89                 :                  */
      90               0 :         top = PR_PopIOLayer(fd->higher, PR_TOP_IO_LAYER);
      91               0 :                 top->dtor(top);
      92                 :                 /*
      93                 :                  * then call lower layer
      94                 :                  */
      95               0 :                 return (lower->methods->close(lower));
      96                 :         } else {
      97                 :                 /* old style stack */
      98               0 :         top = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
      99               0 :                 top->dtor(top);
     100               0 :                 return (fd->methods->close)(fd);
     101                 :         }
     102                 : }
     103                 : 
     104               0 : static PRInt32 PR_CALLBACK pl_DefRead (PRFileDesc *fd, void *buf, PRInt32 amount)
     105                 : {
     106               0 :     PR_ASSERT(fd != NULL);
     107               0 :     PR_ASSERT(fd->lower != NULL);
     108                 : 
     109               0 :     return (fd->lower->methods->read)(fd->lower, buf, amount);
     110                 : }
     111                 : 
     112               0 : static PRInt32 PR_CALLBACK pl_DefWrite (
     113                 :     PRFileDesc *fd, const void *buf, PRInt32 amount)
     114                 : {
     115               0 :     PR_ASSERT(fd != NULL);
     116               0 :     PR_ASSERT(fd->lower != NULL);
     117                 : 
     118               0 :     return (fd->lower->methods->write)(fd->lower, buf, amount);
     119                 : }
     120                 : 
     121               0 : static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd)
     122                 : {
     123               0 :     PR_ASSERT(fd != NULL);
     124               0 :     PR_ASSERT(fd->lower != NULL);
     125                 : 
     126               0 :     return (fd->lower->methods->available)(fd->lower);
     127                 : }
     128                 : 
     129               0 : static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd)
     130                 : {
     131               0 :     PR_ASSERT(fd != NULL);
     132               0 :     PR_ASSERT(fd->lower != NULL);
     133                 : 
     134               0 :     return (fd->lower->methods->available64)(fd->lower);
     135                 : }
     136                 : 
     137               0 : static PRStatus PR_CALLBACK pl_DefFsync (PRFileDesc *fd)
     138                 : {
     139               0 :     PR_ASSERT(fd != NULL);
     140               0 :     PR_ASSERT(fd->lower != NULL);
     141                 : 
     142               0 :     return (fd->lower->methods->fsync)(fd->lower);
     143                 : }
     144                 : 
     145               0 : static PRInt32 PR_CALLBACK pl_DefSeek (
     146                 :     PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
     147                 : {
     148               0 :     PR_ASSERT(fd != NULL);
     149               0 :     PR_ASSERT(fd->lower != NULL);
     150                 : 
     151               0 :     return (fd->lower->methods->seek)(fd->lower, offset, how);
     152                 : }
     153                 : 
     154               0 : static PRInt64 PR_CALLBACK pl_DefSeek64 (
     155                 :     PRFileDesc *fd, PRInt64 offset, PRSeekWhence how)
     156                 : {
     157               0 :     PR_ASSERT(fd != NULL);
     158               0 :     PR_ASSERT(fd->lower != NULL);
     159                 : 
     160               0 :     return (fd->lower->methods->seek64)(fd->lower, offset, how);
     161                 : }
     162                 : 
     163               0 : static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info)
     164                 : {
     165               0 :     PR_ASSERT(fd != NULL);
     166               0 :     PR_ASSERT(fd->lower != NULL);
     167                 : 
     168               0 :     return (fd->lower->methods->fileInfo)(fd->lower, info);
     169                 : }
     170                 : 
     171               0 : static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info)
     172                 : {
     173               0 :     PR_ASSERT(fd != NULL);
     174               0 :     PR_ASSERT(fd->lower != NULL);
     175                 : 
     176               0 :     return (fd->lower->methods->fileInfo64)(fd->lower, info);
     177                 : }
     178                 : 
     179               0 : static PRInt32 PR_CALLBACK pl_DefWritev (PRFileDesc *fd, const PRIOVec *iov,
     180                 :     PRInt32 size, PRIntervalTime timeout)
     181                 : {
     182               0 :     PR_ASSERT(fd != NULL);
     183               0 :     PR_ASSERT(fd->lower != NULL);
     184                 : 
     185               0 :     return (fd->lower->methods->writev)(fd->lower, iov, size, timeout);
     186                 : }
     187                 : 
     188               0 : static PRStatus PR_CALLBACK pl_DefConnect (
     189                 :     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
     190                 : {
     191               0 :     PR_ASSERT(fd != NULL);
     192               0 :     PR_ASSERT(fd->lower != NULL);
     193                 : 
     194               0 :     return (fd->lower->methods->connect)(fd->lower, addr, timeout);
     195                 : }
     196                 : 
     197               8 : static PRStatus PR_CALLBACK pl_DefConnectcontinue (
     198                 :     PRFileDesc *fd, PRInt16 out_flags)
     199                 : {
     200               8 :     PR_ASSERT(fd != NULL);
     201               8 :     PR_ASSERT(fd->lower != NULL);
     202                 : 
     203               8 :     return (fd->lower->methods->connectcontinue)(fd->lower, out_flags);
     204                 : }
     205                 : 
     206               0 : static PRFileDesc* PR_CALLBACK pl_TopAccept (
     207                 :     PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
     208                 : {
     209                 :     PRStatus rv;
     210               0 :     PRFileDesc *newfd, *layer = fd;
     211                 :     PRFileDesc *newstack;
     212               0 :         PRBool newstyle_stack = PR_FALSE;
     213                 : 
     214               0 :     PR_ASSERT(fd != NULL);
     215               0 :     PR_ASSERT(fd->lower != NULL);
     216                 : 
     217                 :         /* test for new style stack */
     218               0 :         while (NULL != layer->higher)
     219               0 :                 layer = layer->higher;
     220               0 :         newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
     221               0 :     newstack = PR_NEW(PRFileDesc);
     222               0 :     if (NULL == newstack)
     223                 :     {
     224               0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     225               0 :         return NULL;
     226                 :     }
     227               0 :     *newstack = *fd;  /* make a copy of the accepting layer */
     228                 : 
     229               0 :     newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
     230               0 :     if (NULL == newfd)
     231                 :     {
     232               0 :         PR_DELETE(newstack);
     233               0 :         return NULL;
     234                 :     }
     235                 : 
     236               0 :     if (newstyle_stack) {
     237               0 :                 newstack->lower = newfd;
     238               0 :                 newfd->higher = newstack;
     239               0 :                 return newstack;
     240                 :         } else {
     241                 :                 /* this PR_PushIOLayer call cannot fail */
     242               0 :                 rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
     243               0 :                 PR_ASSERT(PR_SUCCESS == rv);
     244               0 :         return newfd;  /* that's it */
     245                 :         }
     246                 : }
     247                 : 
     248               0 : static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr)
     249                 : {
     250               0 :     PR_ASSERT(fd != NULL);
     251               0 :     PR_ASSERT(fd->lower != NULL);
     252                 : 
     253               0 :     return (fd->lower->methods->bind)(fd->lower, addr);
     254                 : }
     255                 : 
     256               0 : static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog)
     257                 : {
     258               0 :     PR_ASSERT(fd != NULL);
     259               0 :     PR_ASSERT(fd->lower != NULL);
     260                 : 
     261               0 :     return (fd->lower->methods->listen)(fd->lower, backlog);
     262                 : }
     263                 : 
     264               0 : static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how)
     265                 : {
     266               0 :     PR_ASSERT(fd != NULL);
     267               0 :     PR_ASSERT(fd->lower != NULL);
     268                 : 
     269               0 :     return (fd->lower->methods->shutdown)(fd->lower, how);
     270                 : }
     271                 : 
     272               0 : static PRInt32 PR_CALLBACK pl_DefRecv (
     273                 :     PRFileDesc *fd, void *buf, PRInt32 amount,
     274                 :     PRIntn flags, PRIntervalTime timeout)
     275                 : {
     276               0 :     PR_ASSERT(fd != NULL);
     277               0 :     PR_ASSERT(fd->lower != NULL);
     278                 : 
     279               0 :     return (fd->lower->methods->recv)(
     280                 :         fd->lower, buf, amount, flags, timeout);
     281                 : }
     282                 : 
     283               0 : static PRInt32 PR_CALLBACK pl_DefSend (
     284                 :     PRFileDesc *fd, const void *buf,
     285                 :     PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
     286                 : {
     287               0 :     PR_ASSERT(fd != NULL);
     288               0 :     PR_ASSERT(fd->lower != NULL);
     289                 : 
     290               0 :     return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout);
     291                 : }
     292                 : 
     293               0 : static PRInt32 PR_CALLBACK pl_DefRecvfrom (
     294                 :     PRFileDesc *fd, void *buf, PRInt32 amount,
     295                 :     PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
     296                 : {
     297               0 :     PR_ASSERT(fd != NULL);
     298               0 :     PR_ASSERT(fd->lower != NULL);
     299                 : 
     300               0 :     return (fd->lower->methods->recvfrom)(
     301                 :         fd->lower, buf, amount, flags, addr, timeout);
     302                 : }
     303                 : 
     304               0 : static PRInt32 PR_CALLBACK pl_DefSendto (
     305                 :     PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
     306                 :     const PRNetAddr *addr, PRIntervalTime timeout)
     307                 : {
     308               0 :     PR_ASSERT(fd != NULL);
     309               0 :     PR_ASSERT(fd->lower != NULL);
     310                 : 
     311               0 :     return (fd->lower->methods->sendto)(
     312                 :         fd->lower, buf, amount, flags, addr, timeout);
     313                 : }
     314                 : 
     315               0 : static PRInt16 PR_CALLBACK pl_DefPoll (
     316                 :     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
     317                 : {
     318               0 :     PR_ASSERT(fd != NULL);
     319               0 :     PR_ASSERT(fd->lower != NULL);
     320                 : 
     321               0 :     return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
     322                 : }
     323                 : 
     324               0 : static PRInt32 PR_CALLBACK pl_DefAcceptread (
     325                 :     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf,
     326                 :     PRInt32 amount, PRIntervalTime t)
     327                 : {
     328                 :     PRInt32 nbytes;
     329                 :     PRStatus rv;
     330                 :     PRFileDesc *newstack;
     331               0 :     PRFileDesc *layer = sd;
     332               0 :         PRBool newstyle_stack = PR_FALSE;
     333                 : 
     334               0 :     PR_ASSERT(sd != NULL);
     335               0 :     PR_ASSERT(sd->lower != NULL);
     336                 : 
     337                 :         /* test for new style stack */
     338               0 :         while (NULL != layer->higher)
     339               0 :                 layer = layer->higher;
     340               0 :         newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
     341               0 :     newstack = PR_NEW(PRFileDesc);
     342               0 :     if (NULL == newstack)
     343                 :     {
     344               0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     345               0 :         return -1;
     346                 :     }
     347               0 :     *newstack = *sd;  /* make a copy of the accepting layer */
     348                 : 
     349               0 :     nbytes = sd->lower->methods->acceptread(
     350                 :         sd->lower, nd, raddr, buf, amount, t);
     351               0 :     if (-1 == nbytes)
     352                 :     {
     353               0 :         PR_DELETE(newstack);
     354               0 :         return nbytes;
     355                 :     }
     356               0 :     if (newstyle_stack) {
     357               0 :                 newstack->lower = *nd;
     358               0 :                 (*nd)->higher = newstack;
     359               0 :                 *nd = newstack;
     360               0 :                 return nbytes;
     361                 :         } else {
     362                 :                 /* this PR_PushIOLayer call cannot fail */
     363               0 :                 rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
     364               0 :                 PR_ASSERT(PR_SUCCESS == rv);
     365               0 :                 return nbytes;
     366                 :         }
     367                 : }
     368                 : 
     369               0 : static PRInt32 PR_CALLBACK pl_DefTransmitfile (
     370                 :     PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen,
     371                 :     PRTransmitFileFlags flags, PRIntervalTime t)
     372                 : {
     373               0 :     PR_ASSERT(sd != NULL);
     374               0 :     PR_ASSERT(sd->lower != NULL);
     375                 : 
     376               0 :     return sd->lower->methods->transmitfile(
     377                 :         sd->lower, fd, headers, hlen, flags, t);
     378                 : }
     379                 : 
     380               0 : static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr)
     381                 : {
     382               0 :     PR_ASSERT(fd != NULL);
     383               0 :     PR_ASSERT(fd->lower != NULL);
     384                 : 
     385               0 :     return (fd->lower->methods->getsockname)(fd->lower, addr);
     386                 : }
     387                 : 
     388               0 : static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr)
     389                 : {
     390               0 :     PR_ASSERT(fd != NULL);
     391               0 :     PR_ASSERT(fd->lower != NULL);
     392                 : 
     393               0 :     return (fd->lower->methods->getpeername)(fd->lower, addr);
     394                 : }
     395                 : 
     396              16 : static PRStatus PR_CALLBACK pl_DefGetsocketoption (
     397                 :     PRFileDesc *fd, PRSocketOptionData *data)
     398                 : {
     399              16 :     PR_ASSERT(fd != NULL);
     400              16 :     PR_ASSERT(fd->lower != NULL);
     401                 : 
     402              16 :     return (fd->lower->methods->getsocketoption)(fd->lower, data);
     403                 : }
     404                 : 
     405              16 : static PRStatus PR_CALLBACK pl_DefSetsocketoption (
     406                 :     PRFileDesc *fd, const PRSocketOptionData *data)
     407                 : {
     408              16 :     PR_ASSERT(fd != NULL);
     409              16 :     PR_ASSERT(fd->lower != NULL);
     410                 : 
     411              16 :     return (fd->lower->methods->setsocketoption)(fd->lower, data);
     412                 : }
     413                 : 
     414               0 : static PRInt32 PR_CALLBACK pl_DefSendfile (
     415                 :         PRFileDesc *sd, PRSendFileData *sfd,
     416                 :         PRTransmitFileFlags flags, PRIntervalTime timeout)
     417                 : {
     418               0 :     PR_ASSERT(sd != NULL);
     419               0 :     PR_ASSERT(sd->lower != NULL);
     420                 : 
     421               0 :     return sd->lower->methods->sendfile(
     422                 :         sd->lower, sfd, flags, timeout);
     423                 : }
     424                 : 
     425                 : /* Methods for the top of the stack.  Just call down to the next fd. */
     426                 : static PRIOMethods pl_methods = {
     427                 :     PR_DESC_LAYERED,
     428                 :     pl_TopClose,
     429                 :     pl_DefRead,
     430                 :     pl_DefWrite,
     431                 :     pl_DefAvailable,
     432                 :     pl_DefAvailable64,
     433                 :     pl_DefFsync,
     434                 :     pl_DefSeek,
     435                 :     pl_DefSeek64,
     436                 :     pl_DefFileInfo,
     437                 :     pl_DefFileInfo64,
     438                 :     pl_DefWritev,
     439                 :     pl_DefConnect,
     440                 :     pl_TopAccept,
     441                 :     pl_DefBind,
     442                 :     pl_DefListen,
     443                 :     pl_DefShutdown,
     444                 :     pl_DefRecv,
     445                 :     pl_DefSend,
     446                 :     pl_DefRecvfrom,
     447                 :     pl_DefSendto,
     448                 :     pl_DefPoll,
     449                 :     pl_DefAcceptread,
     450                 :     pl_DefTransmitfile,
     451                 :     pl_DefGetsockname,
     452                 :     pl_DefGetpeername,
     453                 :     (PRReservedFN)_PR_InvalidInt,
     454                 :     (PRReservedFN)_PR_InvalidInt,
     455                 :     pl_DefGetsocketoption,
     456                 :     pl_DefSetsocketoption,
     457                 :     pl_DefSendfile,
     458                 :     pl_DefConnectcontinue,
     459                 :     (PRReservedFN)_PR_InvalidInt,
     460                 :     (PRReservedFN)_PR_InvalidInt,
     461                 :     (PRReservedFN)_PR_InvalidInt,
     462                 :     (PRReservedFN)_PR_InvalidInt
     463                 : };
     464                 : 
     465             332 : PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void)
     466                 : {
     467             332 :     return &pl_methods;
     468                 : }  /* PR_GetDefaultIOMethods */
     469                 : 
     470            1427 : PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub(
     471                 :     PRDescIdentity ident, const PRIOMethods *methods)
     472                 : {
     473            1427 :     PRFileDesc *fd = NULL;
     474            1427 :     PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident));
     475            1427 :     if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident))
     476               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     477                 :     else
     478                 :     {
     479            1427 :         fd = PR_NEWZAP(PRFileDesc);
     480            1427 :         if (NULL == fd)
     481               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     482                 :         else
     483                 :         {
     484            1427 :             fd->methods = methods;
     485            1427 :             fd->dtor = pl_FDDestructor;
     486            1427 :             fd->identity = ident;
     487                 :         }
     488                 :     }
     489            1427 :     return fd;
     490                 : }  /* PR_CreateIOLayerStub */
     491                 : 
     492                 : /*
     493                 :  * PR_CreateIOLayer
     494                 :  *              Create a new style stack, where the stack top is a dummy header.
     495                 :  *              Unlike the old style stacks, the contents of the stack head
     496                 :  *              are not modified when a layer is pushed onto or popped from a new
     497                 :  *              style stack.
     498                 :  */
     499                 : 
     500               0 : PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top)
     501                 : {
     502               0 :     PRFileDesc *fd = NULL;
     503                 : 
     504               0 :         fd = PR_NEWZAP(PRFileDesc);
     505               0 :         if (NULL == fd)
     506               0 :                 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     507                 :         else
     508                 :         {
     509               0 :                 fd->methods = &pl_methods;
     510               0 :                 fd->dtor = pl_FDDestructor;
     511               0 :                 fd->identity = PR_IO_LAYER_HEAD;
     512               0 :                 fd->higher = NULL;
     513               0 :                 fd->lower = top;
     514               0 :                 top->higher = fd;
     515               0 :                 top->lower = NULL;
     516                 :         }
     517               0 :     return fd;
     518                 : }  /* PR_CreateIOLayer */
     519                 : 
     520                 : /*
     521                 :  * _PR_DestroyIOLayer
     522                 :  *              Delete the stack head of a new style stack.
     523                 :  */
     524                 : 
     525               0 : static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack)
     526                 : {
     527               0 :     if (NULL == stack)
     528               0 :         return PR_FAILURE;
     529                 :     else {
     530               0 :         PR_DELETE(stack);
     531               0 :         return PR_SUCCESS;
     532                 :     }
     533                 : }  /* _PR_DestroyIOLayer */
     534                 : 
     535            1427 : PR_IMPLEMENT(PRStatus) PR_PushIOLayer(
     536                 :     PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd)
     537                 : {
     538            1427 :     PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id);
     539                 : 
     540            1427 :     PR_ASSERT(fd != NULL);
     541            1427 :     PR_ASSERT(stack != NULL);
     542            1427 :     PR_ASSERT(insert != NULL);
     543            1427 :     PR_ASSERT(PR_IO_LAYER_HEAD != id);
     544            1427 :     if ((NULL == stack) || (NULL == fd) || (NULL == insert))
     545                 :     {
     546               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     547               0 :         return PR_FAILURE;
     548                 :     }
     549                 : 
     550            1427 :     if (stack == insert)
     551                 :     {
     552                 :                 /* going on top of the stack */
     553                 :                 /* old-style stack */   
     554            1427 :                 PRFileDesc copy = *stack;
     555            1427 :                 *stack = *fd;
     556            1427 :                 *fd = copy;
     557            1427 :                 fd->higher = stack;
     558            1427 :                 stack->lower = fd;
     559            1427 :                 stack->higher = NULL;
     560                 :         } else {
     561                 :         /*
     562                 :                  * going somewhere in the middle of the stack for both old and new
     563                 :                  * style stacks, or going on top of stack for new style stack
     564                 :                  */
     565               0 :         fd->lower = insert;
     566               0 :         fd->higher = insert->higher;
     567                 : 
     568               0 :         insert->higher->lower = fd;
     569               0 :         insert->higher = fd;
     570                 :     }
     571                 : 
     572            1427 :     return PR_SUCCESS;
     573                 : }
     574                 : 
     575            1423 : PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id)
     576                 : {
     577            1423 :     PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id);
     578                 : 
     579            1423 :     PR_ASSERT(0 != id);
     580            1423 :     PR_ASSERT(NULL != stack);
     581            1423 :     PR_ASSERT(NULL != extract);
     582            1423 :     if ((NULL == stack) || (0 == id) || (NULL == extract))
     583                 :     {
     584               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     585               0 :         return NULL;
     586                 :     }
     587                 : 
     588            1423 :     if (extract == stack) {
     589                 :         /* popping top layer of the stack */
     590                 :                 /* old style stack */
     591            1423 :         PRFileDesc copy = *stack;
     592            1423 :         extract = stack->lower;
     593            1423 :         *stack = *extract;
     594            1423 :         *extract = copy;
     595            1423 :         stack->higher = NULL;
     596               0 :         } else if ((PR_IO_LAYER_HEAD == stack->identity) &&
     597               0 :                                         (extract == stack->lower) && (extract->lower == NULL)) {
     598                 :                         /*
     599                 :                          * new style stack
     600                 :                          * popping the only layer in the stack; delete the stack too
     601                 :                          */
     602               0 :                         stack->lower = NULL;
     603               0 :                         _PR_DestroyIOLayer(stack);
     604                 :         } else {
     605                 :                 /* for both kinds of stacks */
     606               0 :         extract->lower->higher = extract->higher;
     607               0 :         extract->higher->lower = extract->lower;
     608                 :     }
     609            1423 :     extract->higher = extract->lower = NULL;
     610            1423 :     return extract;
     611                 : }  /* PR_PopIOLayer */
     612                 : 
     613                 : #define ID_CACHE_INCREMENT 16
     614                 : typedef struct _PRIdentity_cache
     615                 : {
     616                 :     PRLock *ml;
     617                 :     char **name;
     618                 :     PRIntn length;
     619                 :     PRDescIdentity ident;
     620                 : } _PRIdentity_cache;
     621                 : 
     622                 : static _PRIdentity_cache identity_cache;
     623                 : 
     624            1751 : PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name)
     625                 : {
     626                 :     PRDescIdentity identity, length;
     627            1751 :     char **names = NULL, *name = NULL, **old = NULL;
     628                 : 
     629            1751 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     630                 : 
     631            1751 :     PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident);
     632                 : 
     633            1751 :     if (NULL != layer_name)
     634                 :     {
     635            1751 :         name = (char*)PR_Malloc(strlen(layer_name) + 1);
     636            1751 :         if (NULL == name)
     637                 :         {
     638               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     639               0 :             return PR_INVALID_IO_LAYER;
     640                 :         }
     641            1751 :         strcpy(name, layer_name);
     642                 :     }
     643                 : 
     644                 :     /* this initial code runs unsafe */
     645                 : retry:
     646            1751 :     PR_ASSERT(NULL == names);
     647            1751 :     length = identity_cache.length;
     648            1751 :     if (length < (identity_cache.ident + 1))
     649                 :     {
     650            1419 :         length += ID_CACHE_INCREMENT;
     651            1419 :         names = (char**)PR_CALLOC(length * sizeof(char*));
     652            1419 :         if (NULL == names)
     653                 :         {
     654               0 :             if (NULL != name) PR_DELETE(name);
     655               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     656               0 :             return PR_INVALID_IO_LAYER;
     657                 :         }
     658                 :     }
     659                 : 
     660                 :     /* now we get serious about thread safety */
     661            1751 :     PR_Lock(identity_cache.ml);
     662            1751 :     PR_ASSERT(identity_cache.ident <= identity_cache.length);
     663            1751 :     identity = identity_cache.ident + 1;
     664            1751 :     if (identity > identity_cache.length)  /* there's no room */
     665                 :     {
     666                 :         /* we have to do something - hopefully it's already done */
     667            1419 :         if ((NULL != names) && (length >= identity))
     668                 :         {
     669                 :             /* what we did is still okay */
     670            2838 :             memcpy(
     671            1419 :                 names, identity_cache.name,
     672            1419 :                 identity_cache.length * sizeof(char*));
     673            1419 :             old = identity_cache.name;
     674            1419 :             identity_cache.name = names;
     675            1419 :             identity_cache.length = length;
     676            1419 :             names = NULL;
     677                 :         }
     678                 :         else
     679                 :         {
     680               0 :             PR_ASSERT(identity_cache.ident <= identity_cache.length);
     681               0 :             PR_Unlock(identity_cache.ml);
     682               0 :             if (NULL != names) PR_DELETE(names);
     683               0 :             goto retry;
     684                 :         }
     685                 :     }
     686            1751 :     if (NULL != name) /* there's a name to be stored */
     687                 :     {
     688            1751 :         identity_cache.name[identity] = name;
     689                 :     }
     690            1751 :     identity_cache.ident = identity;
     691            1751 :     PR_ASSERT(identity_cache.ident <= identity_cache.length);
     692            1751 :     PR_Unlock(identity_cache.ml);
     693                 : 
     694            1751 :     if (NULL != old) PR_DELETE(old);
     695            1751 :     if (NULL != names) PR_DELETE(names);
     696                 : 
     697            1751 :     return identity;
     698                 : }  /* PR_GetUniqueIdentity */
     699                 : 
     700               0 : PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident)
     701                 : {
     702               0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     703                 : 
     704               0 :     if (PR_TOP_IO_LAYER == ident) return NULL;
     705                 : 
     706               0 :     PR_ASSERT(ident <= identity_cache.ident);
     707               0 :     return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident];
     708                 : }  /* PR_GetNameForIdentity */
     709                 : 
     710               4 : PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd)
     711                 : {
     712               4 :     PR_ASSERT(NULL != fd);
     713               4 :     if (PR_IO_LAYER_HEAD == fd->identity) {
     714               0 :         PR_ASSERT(NULL != fd->lower);
     715               0 :         return fd->lower->identity;
     716                 :         } else
     717               4 :         return fd->identity;
     718                 : }  /* PR_GetLayersIdentity */
     719                 : 
     720          209807 : PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id)
     721                 : {
     722          209807 :     PRFileDesc *layer = fd;
     723                 : 
     724          209807 :     if (PR_TOP_IO_LAYER == id) {
     725            2846 :         if (PR_IO_LAYER_HEAD == fd->identity)
     726               0 :                         return fd->lower;
     727                 :                 else 
     728            2846 :                         return fd;
     729                 :         }
     730                 : 
     731          268876 :     for (layer = fd; layer != NULL; layer = layer->lower)
     732                 :     {
     733          268876 :         if (id == layer->identity) return layer;
     734                 :     }
     735               0 :     for (layer = fd; layer != NULL; layer = layer->higher)
     736                 :     {
     737               0 :         if (id == layer->identity) return layer;
     738                 :     }
     739               0 :     return NULL;
     740                 : }  /* PR_GetIdentitiesLayer */
     741                 : 
     742           20034 : void _PR_InitLayerCache(void)
     743                 : {
     744           20034 :     memset(&identity_cache, 0, sizeof(identity_cache));
     745           20034 :     identity_cache.ml = PR_NewLock();
     746           20034 :     PR_ASSERT(NULL != identity_cache.ml);
     747           20034 : }  /* _PR_InitLayerCache */
     748                 : 
     749             140 : void _PR_CleanupLayerCache(void)
     750                 : {
     751             140 :     if (identity_cache.ml)
     752                 :     {
     753             140 :         PR_DestroyLock(identity_cache.ml);
     754             140 :         identity_cache.ml = NULL;
     755                 :     }
     756                 : 
     757             140 :     if (identity_cache.name)
     758                 :     {
     759                 :         PRDescIdentity ident;
     760                 : 
     761               0 :         for (ident = 0; ident <= identity_cache.ident; ident++)
     762               0 :             PR_DELETE(identity_cache.name[ident]);
     763                 : 
     764               0 :         PR_DELETE(identity_cache.name);
     765                 :     }
     766             140 : }  /* _PR_CleanupLayerCache */
     767                 : 
     768                 : /* prlayer.c */

Generated by: LCOV version 1.7