LCOV - app.info - nsprpub/pr/src/io/prlayer.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/io - prlayer.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 330 | 5 | 1.5 %
| Date: | 2012-04-07 | Functions: | 42 | 1 | 2.4 %

           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               0 : void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd)
          54                 : {
          55               0 :     PR_ASSERT(fd != NULL);
          56               0 :     if (NULL != fd->lower) fd->lower->higher = fd->higher;
          57               0 :     if (NULL != fd->higher) fd->higher->lower = fd->lower;
          58               0 :     PR_DELETE(fd);
          59               0 : }
          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               0 : static PRStatus PR_CALLBACK pl_DefConnectcontinue (
         198                 :     PRFileDesc *fd, PRInt16 out_flags)
         199                 : {
         200               0 :     PR_ASSERT(fd != NULL);
         201               0 :     PR_ASSERT(fd->lower != NULL);
         202                 :
         203               0 :     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               0 : static PRStatus PR_CALLBACK pl_DefGetsocketoption (
         397                 :     PRFileDesc *fd, PRSocketOptionData *data)
         398                 : {
         399               0 :     PR_ASSERT(fd != NULL);
         400               0 :     PR_ASSERT(fd->lower != NULL);
         401                 :
         402               0 :     return (fd->lower->methods->getsocketoption)(fd->lower, data);
         403                 : }
         404                 :
         405               0 : static PRStatus PR_CALLBACK pl_DefSetsocketoption (
         406                 :     PRFileDesc *fd, const PRSocketOptionData *data)
         407                 : {
         408               0 :     PR_ASSERT(fd != NULL);
         409               0 :     PR_ASSERT(fd->lower != NULL);
         410                 :
         411               0 :     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               0 : PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void)
         466                 : {
         467               0 :     return &pl_methods;
         468                 : }  /* PR_GetDefaultIOMethods */
         469                 :
         470               0 : PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub(
         471                 :     PRDescIdentity ident, const PRIOMethods *methods)
         472                 : {
         473               0 :     PRFileDesc *fd = NULL;
         474               0 :     PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident));
         475               0 :     if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident))
         476               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         477                 :     else
         478                 :     {
         479               0 :         fd = PR_NEWZAP(PRFileDesc);
         480               0 :         if (NULL == fd)
         481               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         482                 :         else
         483                 :         {
         484               0 :             fd->methods = methods;
         485               0 :             fd->dtor = pl_FDDestructor;
         486               0 :             fd->identity = ident;
         487                 :         }
         488                 :     }
         489               0 :     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               0 : PR_IMPLEMENT(PRStatus) PR_PushIOLayer(
         536                 :     PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd)
         537                 : {
         538               0 :     PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id);
         539                 :
         540               0 :     PR_ASSERT(fd != NULL);
         541               0 :     PR_ASSERT(stack != NULL);
         542               0 :     PR_ASSERT(insert != NULL);
         543               0 :     PR_ASSERT(PR_IO_LAYER_HEAD != id);
         544               0 :     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               0 :     if (stack == insert)
         551                 :     {
         552                 :                 /* going on top of the stack */
         553                 :                 /* old-style stack */
         554               0 :                 PRFileDesc copy = *stack;
         555               0 :                 *stack = *fd;
         556               0 :                 *fd = copy;
         557               0 :                 fd->higher = stack;
         558               0 :                 stack->lower = fd;
         559               0 :                 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               0 :     return PR_SUCCESS;
         573                 : }
         574                 :
         575               0 : PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id)
         576                 : {
         577               0 :     PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id);
         578                 :
         579               0 :     PR_ASSERT(0 != id);
         580               0 :     PR_ASSERT(NULL != stack);
         581               0 :     PR_ASSERT(NULL != extract);
         582               0 :     if ((NULL == stack) || (0 == id) || (NULL == extract))
         583                 :     {
         584               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         585               0 :         return NULL;
         586                 :     }
         587                 :
         588               0 :     if (extract == stack) {
         589                 :         /* popping top layer of the stack */
         590                 :                 /* old style stack */
         591               0 :         PRFileDesc copy = *stack;
         592               0 :         extract = stack->lower;
         593               0 :         *stack = *extract;
         594               0 :         *extract = copy;
         595               0 :         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               0 :     extract->higher = extract->lower = NULL;
         610               0 :     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               0 : PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name)
         625                 : {
         626                 :     PRDescIdentity identity, length;
         627               0 :     char **names = NULL, *name = NULL, **old = NULL;
         628                 :
         629               0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         630                 :
         631               0 :     PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident);
         632                 :
         633               0 :     if (NULL != layer_name)
         634                 :     {
         635               0 :         name = (char*)PR_Malloc(strlen(layer_name) + 1);
         636               0 :         if (NULL == name)
         637                 :         {
         638               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         639               0 :             return PR_INVALID_IO_LAYER;
         640                 :         }
         641               0 :         strcpy(name, layer_name);
         642                 :     }
         643                 :
         644                 :     /* this initial code runs unsafe */
         645                 : retry:
         646               0 :     PR_ASSERT(NULL == names);
         647               0 :     length = identity_cache.length;
         648               0 :     if (length < (identity_cache.ident + 1))
         649                 :     {
         650               0 :         length += ID_CACHE_INCREMENT;
         651               0 :         names = (char**)PR_CALLOC(length * sizeof(char*));
         652               0 :         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               0 :     PR_Lock(identity_cache.ml);
         662               0 :     PR_ASSERT(identity_cache.ident <= identity_cache.length);
         663               0 :     identity = identity_cache.ident + 1;
         664               0 :     if (identity > identity_cache.length)  /* there's no room */
         665                 :     {
         666                 :         /* we have to do something - hopefully it's already done */
         667               0 :         if ((NULL != names) && (length >= identity))
         668                 :         {
         669                 :             /* what we did is still okay */
         670               0 :             memcpy(
         671               0 :                 names, identity_cache.name,
         672               0 :                 identity_cache.length * sizeof(char*));
         673               0 :             old = identity_cache.name;
         674               0 :             identity_cache.name = names;
         675               0 :             identity_cache.length = length;
         676               0 :             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               0 :     if (NULL != name) /* there's a name to be stored */
         687                 :     {
         688               0 :         identity_cache.name[identity] = name;
         689                 :     }
         690               0 :     identity_cache.ident = identity;
         691               0 :     PR_ASSERT(identity_cache.ident <= identity_cache.length);
         692               0 :     PR_Unlock(identity_cache.ml);
         693                 :
         694               0 :     if (NULL != old) PR_DELETE(old);
         695               0 :     if (NULL != names) PR_DELETE(names);
         696                 :
         697               0 :     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               0 : PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd)
         711                 : {
         712               0 :     PR_ASSERT(NULL != fd);
         713               0 :     if (PR_IO_LAYER_HEAD == fd->identity) {
         714               0 :         PR_ASSERT(NULL != fd->lower);
         715               0 :         return fd->lower->identity;
         716                 :         } else
         717               0 :         return fd->identity;
         718                 : }  /* PR_GetLayersIdentity */
         719                 :
         720               0 : PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id)
         721                 : {
         722               0 :     PRFileDesc *layer = fd;
         723                 :
         724               0 :     if (PR_TOP_IO_LAYER == id) {
         725               0 :         if (PR_IO_LAYER_HEAD == fd->identity)
         726               0 :                         return fd->lower;
         727                 :                 else
         728               0 :                         return fd;
         729                 :         }
         730                 :
         731               0 :     for (layer = fd; layer != NULL; layer = layer->lower)
         732                 :     {
         733               0 :         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           18667 : void _PR_InitLayerCache(void)
         743                 : {
         744           18667 :     memset(&identity_cache, 0, sizeof(identity_cache));
         745           18667 :     identity_cache.ml = PR_NewLock();
         746           18667 :     PR_ASSERT(NULL != identity_cache.ml);
         747           18667 : }  /* _PR_InitLayerCache */
         748                 :
         749               0 : void _PR_CleanupLayerCache(void)
         750                 : {
         751               0 :     if (identity_cache.ml)
         752                 :     {
         753               0 :         PR_DestroyLock(identity_cache.ml);
         754               0 :         identity_cache.ml = NULL;
         755                 :     }
         756                 :
         757               0 :     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               0 : }  /* _PR_CleanupLayerCache */
         767                 :
         768                 : /* prlayer.c */

Generated by: LCOV version 1.7