nsprpub/pr/src/io/prlayer.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 ** File:        prlayer.c
     8 ** Description: Routines for handling pushable protocol modules on sockets.
     9 */
    11 #include "primpl.h"
    12 #include "prerror.h"
    13 #include "prmem.h"
    14 #include "prlock.h"
    15 #include "prlog.h"
    16 #include "prio.h"
    18 #include <string.h> /* for memset() */
    19 static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack);
    21 void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd)
    22 {
    23     PR_ASSERT(fd != NULL);
    24     if (NULL != fd->lower) fd->lower->higher = fd->higher;
    25     if (NULL != fd->higher) fd->higher->lower = fd->lower;
    26     PR_DELETE(fd);
    27 }
    29 /*
    30 ** Default methods that just call down to the next fd.
    31 */
    32 static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd)
    33 {
    34     PRFileDesc *top, *lower;
    35 	PRStatus rv;
    37     PR_ASSERT(fd != NULL);
    38     PR_ASSERT(fd->lower != NULL);
    39     PR_ASSERT(fd->secret == NULL);
    40     PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED);
    42 	if (PR_IO_LAYER_HEAD == fd->identity) {
    43 		/*
    44 		 * new style stack; close all the layers, before deleting the
    45 		 * stack head
    46 		 */
    47 		rv = fd->lower->methods->close(fd->lower);
    48 		_PR_DestroyIOLayer(fd);
    49 		return rv;
    50 	} else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) {
    51 		/*
    52 		 * lower layers of new style stack
    53 		 */
    54 		lower = fd->lower;
    55 		/*
    56 		 * pop and cleanup current layer
    57 		 */
    58     	top = PR_PopIOLayer(fd->higher, PR_TOP_IO_LAYER);
    59 		top->dtor(top);
    60 		/*
    61 		 * then call lower layer
    62 		 */
    63 		return (lower->methods->close(lower));
    64 	} else {
    65 		/* old style stack */
    66     	top = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
    67 		top->dtor(top);
    68 		return (fd->methods->close)(fd);
    69 	}
    70 }
    72 static PRInt32 PR_CALLBACK pl_DefRead (PRFileDesc *fd, void *buf, PRInt32 amount)
    73 {
    74     PR_ASSERT(fd != NULL);
    75     PR_ASSERT(fd->lower != NULL);
    77     return (fd->lower->methods->read)(fd->lower, buf, amount);
    78 }
    80 static PRInt32 PR_CALLBACK pl_DefWrite (
    81     PRFileDesc *fd, const void *buf, PRInt32 amount)
    82 {
    83     PR_ASSERT(fd != NULL);
    84     PR_ASSERT(fd->lower != NULL);
    86     return (fd->lower->methods->write)(fd->lower, buf, amount);
    87 }
    89 static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd)
    90 {
    91     PR_ASSERT(fd != NULL);
    92     PR_ASSERT(fd->lower != NULL);
    94     return (fd->lower->methods->available)(fd->lower);
    95 }
    97 static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd)
    98 {
    99     PR_ASSERT(fd != NULL);
   100     PR_ASSERT(fd->lower != NULL);
   102     return (fd->lower->methods->available64)(fd->lower);
   103 }
   105 static PRStatus PR_CALLBACK pl_DefFsync (PRFileDesc *fd)
   106 {
   107     PR_ASSERT(fd != NULL);
   108     PR_ASSERT(fd->lower != NULL);
   110     return (fd->lower->methods->fsync)(fd->lower);
   111 }
   113 static PRInt32 PR_CALLBACK pl_DefSeek (
   114     PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
   115 {
   116     PR_ASSERT(fd != NULL);
   117     PR_ASSERT(fd->lower != NULL);
   119     return (fd->lower->methods->seek)(fd->lower, offset, how);
   120 }
   122 static PRInt64 PR_CALLBACK pl_DefSeek64 (
   123     PRFileDesc *fd, PRInt64 offset, PRSeekWhence how)
   124 {
   125     PR_ASSERT(fd != NULL);
   126     PR_ASSERT(fd->lower != NULL);
   128     return (fd->lower->methods->seek64)(fd->lower, offset, how);
   129 }
   131 static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info)
   132 {
   133     PR_ASSERT(fd != NULL);
   134     PR_ASSERT(fd->lower != NULL);
   136     return (fd->lower->methods->fileInfo)(fd->lower, info);
   137 }
   139 static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info)
   140 {
   141     PR_ASSERT(fd != NULL);
   142     PR_ASSERT(fd->lower != NULL);
   144     return (fd->lower->methods->fileInfo64)(fd->lower, info);
   145 }
   147 static PRInt32 PR_CALLBACK pl_DefWritev (PRFileDesc *fd, const PRIOVec *iov,
   148     PRInt32 size, PRIntervalTime timeout)
   149 {
   150     PR_ASSERT(fd != NULL);
   151     PR_ASSERT(fd->lower != NULL);
   153     return (fd->lower->methods->writev)(fd->lower, iov, size, timeout);
   154 }
   156 static PRStatus PR_CALLBACK pl_DefConnect (
   157     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
   158 {
   159     PR_ASSERT(fd != NULL);
   160     PR_ASSERT(fd->lower != NULL);
   162     return (fd->lower->methods->connect)(fd->lower, addr, timeout);
   163 }
   165 static PRStatus PR_CALLBACK pl_DefConnectcontinue (
   166     PRFileDesc *fd, PRInt16 out_flags)
   167 {
   168     PR_ASSERT(fd != NULL);
   169     PR_ASSERT(fd->lower != NULL);
   171     return (fd->lower->methods->connectcontinue)(fd->lower, out_flags);
   172 }
   174 static PRFileDesc* PR_CALLBACK pl_TopAccept (
   175     PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
   176 {
   177     PRStatus rv;
   178     PRFileDesc *newfd, *layer = fd;
   179     PRFileDesc *newstack;
   180 	PRBool newstyle_stack = PR_FALSE;
   182     PR_ASSERT(fd != NULL);
   183     PR_ASSERT(fd->lower != NULL);
   185 	/* test for new style stack */
   186 	while (NULL != layer->higher)
   187 		layer = layer->higher;
   188 	newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
   189     newstack = PR_NEW(PRFileDesc);
   190     if (NULL == newstack)
   191     {
   192         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   193         return NULL;
   194     }
   195     *newstack = *fd;  /* make a copy of the accepting layer */
   197     newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
   198     if (NULL == newfd)
   199     {
   200         PR_DELETE(newstack);
   201         return NULL;
   202     }
   204     if (newstyle_stack) {
   205 		newstack->lower = newfd;
   206 		newfd->higher = newstack;
   207 		return newstack;
   208 	} else {
   209 		/* this PR_PushIOLayer call cannot fail */
   210 		rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
   211 		PR_ASSERT(PR_SUCCESS == rv);
   212     	return newfd;  /* that's it */
   213 	}
   214 }
   216 static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr)
   217 {
   218     PR_ASSERT(fd != NULL);
   219     PR_ASSERT(fd->lower != NULL);
   221     return (fd->lower->methods->bind)(fd->lower, addr);
   222 }
   224 static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog)
   225 {
   226     PR_ASSERT(fd != NULL);
   227     PR_ASSERT(fd->lower != NULL);
   229     return (fd->lower->methods->listen)(fd->lower, backlog);
   230 }
   232 static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how)
   233 {
   234     PR_ASSERT(fd != NULL);
   235     PR_ASSERT(fd->lower != NULL);
   237     return (fd->lower->methods->shutdown)(fd->lower, how);
   238 }
   240 static PRInt32 PR_CALLBACK pl_DefRecv (
   241     PRFileDesc *fd, void *buf, PRInt32 amount,
   242     PRIntn flags, PRIntervalTime timeout)
   243 {
   244     PR_ASSERT(fd != NULL);
   245     PR_ASSERT(fd->lower != NULL);
   247     return (fd->lower->methods->recv)(
   248         fd->lower, buf, amount, flags, timeout);
   249 }
   251 static PRInt32 PR_CALLBACK pl_DefSend (
   252     PRFileDesc *fd, const void *buf,
   253     PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
   254 {
   255     PR_ASSERT(fd != NULL);
   256     PR_ASSERT(fd->lower != NULL);
   258     return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout);
   259 }
   261 static PRInt32 PR_CALLBACK pl_DefRecvfrom (
   262     PRFileDesc *fd, void *buf, PRInt32 amount,
   263     PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
   264 {
   265     PR_ASSERT(fd != NULL);
   266     PR_ASSERT(fd->lower != NULL);
   268     return (fd->lower->methods->recvfrom)(
   269         fd->lower, buf, amount, flags, addr, timeout);
   270 }
   272 static PRInt32 PR_CALLBACK pl_DefSendto (
   273     PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
   274     const PRNetAddr *addr, PRIntervalTime timeout)
   275 {
   276     PR_ASSERT(fd != NULL);
   277     PR_ASSERT(fd->lower != NULL);
   279     return (fd->lower->methods->sendto)(
   280         fd->lower, buf, amount, flags, addr, timeout);
   281 }
   283 static PRInt16 PR_CALLBACK pl_DefPoll (
   284     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
   285 {
   286     PR_ASSERT(fd != NULL);
   287     PR_ASSERT(fd->lower != NULL);
   289     return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
   290 }
   292 static PRInt32 PR_CALLBACK pl_DefAcceptread (
   293     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf,
   294     PRInt32 amount, PRIntervalTime t)
   295 {
   296     PRInt32 nbytes;
   297     PRStatus rv;
   298     PRFileDesc *newstack;
   299     PRFileDesc *layer = sd;
   300 	PRBool newstyle_stack = PR_FALSE;
   302     PR_ASSERT(sd != NULL);
   303     PR_ASSERT(sd->lower != NULL);
   305 	/* test for new style stack */
   306 	while (NULL != layer->higher)
   307 		layer = layer->higher;
   308 	newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
   309     newstack = PR_NEW(PRFileDesc);
   310     if (NULL == newstack)
   311     {
   312         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   313         return -1;
   314     }
   315     *newstack = *sd;  /* make a copy of the accepting layer */
   317     nbytes = sd->lower->methods->acceptread(
   318         sd->lower, nd, raddr, buf, amount, t);
   319     if (-1 == nbytes)
   320     {
   321         PR_DELETE(newstack);
   322         return nbytes;
   323     }
   324     if (newstyle_stack) {
   325 		newstack->lower = *nd;
   326 		(*nd)->higher = newstack;
   327 		*nd = newstack;
   328 		return nbytes;
   329 	} else {
   330 		/* this PR_PushIOLayer call cannot fail */
   331 		rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
   332 		PR_ASSERT(PR_SUCCESS == rv);
   333 		return nbytes;
   334 	}
   335 }
   337 static PRInt32 PR_CALLBACK pl_DefTransmitfile (
   338     PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen,
   339     PRTransmitFileFlags flags, PRIntervalTime t)
   340 {
   341     PR_ASSERT(sd != NULL);
   342     PR_ASSERT(sd->lower != NULL);
   344     return sd->lower->methods->transmitfile(
   345         sd->lower, fd, headers, hlen, flags, t);
   346 }
   348 static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr)
   349 {
   350     PR_ASSERT(fd != NULL);
   351     PR_ASSERT(fd->lower != NULL);
   353     return (fd->lower->methods->getsockname)(fd->lower, addr);
   354 }
   356 static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr)
   357 {
   358     PR_ASSERT(fd != NULL);
   359     PR_ASSERT(fd->lower != NULL);
   361     return (fd->lower->methods->getpeername)(fd->lower, addr);
   362 }
   364 static PRStatus PR_CALLBACK pl_DefGetsocketoption (
   365     PRFileDesc *fd, PRSocketOptionData *data)
   366 {
   367     PR_ASSERT(fd != NULL);
   368     PR_ASSERT(fd->lower != NULL);
   370     return (fd->lower->methods->getsocketoption)(fd->lower, data);
   371 }
   373 static PRStatus PR_CALLBACK pl_DefSetsocketoption (
   374     PRFileDesc *fd, const PRSocketOptionData *data)
   375 {
   376     PR_ASSERT(fd != NULL);
   377     PR_ASSERT(fd->lower != NULL);
   379     return (fd->lower->methods->setsocketoption)(fd->lower, data);
   380 }
   382 static PRInt32 PR_CALLBACK pl_DefSendfile (
   383 	PRFileDesc *sd, PRSendFileData *sfd,
   384 	PRTransmitFileFlags flags, PRIntervalTime timeout)
   385 {
   386     PR_ASSERT(sd != NULL);
   387     PR_ASSERT(sd->lower != NULL);
   389     return sd->lower->methods->sendfile(
   390         sd->lower, sfd, flags, timeout);
   391 }
   393 /* Methods for the top of the stack.  Just call down to the next fd. */
   394 static PRIOMethods pl_methods = {
   395     PR_DESC_LAYERED,
   396     pl_TopClose,
   397     pl_DefRead,
   398     pl_DefWrite,
   399     pl_DefAvailable,
   400     pl_DefAvailable64,
   401     pl_DefFsync,
   402     pl_DefSeek,
   403     pl_DefSeek64,
   404     pl_DefFileInfo,
   405     pl_DefFileInfo64,
   406     pl_DefWritev,
   407     pl_DefConnect,
   408     pl_TopAccept,
   409     pl_DefBind,
   410     pl_DefListen,
   411     pl_DefShutdown,
   412     pl_DefRecv,
   413     pl_DefSend,
   414     pl_DefRecvfrom,
   415     pl_DefSendto,
   416     pl_DefPoll,
   417     pl_DefAcceptread,
   418     pl_DefTransmitfile,
   419     pl_DefGetsockname,
   420     pl_DefGetpeername,
   421     (PRReservedFN)_PR_InvalidInt,
   422     (PRReservedFN)_PR_InvalidInt,
   423     pl_DefGetsocketoption,
   424     pl_DefSetsocketoption,
   425     pl_DefSendfile,
   426     pl_DefConnectcontinue,
   427     (PRReservedFN)_PR_InvalidInt,
   428     (PRReservedFN)_PR_InvalidInt,
   429     (PRReservedFN)_PR_InvalidInt,
   430     (PRReservedFN)_PR_InvalidInt
   431 };
   433 PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void)
   434 {
   435     return &pl_methods;
   436 }  /* PR_GetDefaultIOMethods */
   438 PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub(
   439     PRDescIdentity ident, const PRIOMethods *methods)
   440 {
   441     PRFileDesc *fd = NULL;
   442     PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident));
   443     if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident))
   444         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   445     else
   446     {
   447         fd = PR_NEWZAP(PRFileDesc);
   448         if (NULL == fd)
   449             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   450         else
   451         {
   452             fd->methods = methods;
   453             fd->dtor = pl_FDDestructor;
   454             fd->identity = ident;
   455         }
   456     }
   457     return fd;
   458 }  /* PR_CreateIOLayerStub */
   460 /*
   461  * PR_CreateIOLayer
   462  *		Create a new style stack, where the stack top is a dummy header.
   463  *		Unlike the old style stacks, the contents of the stack head
   464  *		are not modified when a layer is pushed onto or popped from a new
   465  *		style stack.
   466  */
   468 PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top)
   469 {
   470     PRFileDesc *fd = NULL;
   472 	fd = PR_NEWZAP(PRFileDesc);
   473 	if (NULL == fd)
   474 		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   475 	else
   476 	{
   477 		fd->methods = &pl_methods;
   478 		fd->dtor = pl_FDDestructor;
   479 		fd->identity = PR_IO_LAYER_HEAD;
   480 		fd->higher = NULL;
   481 		fd->lower = top;
   482 		top->higher = fd;
   483 		top->lower = NULL;
   484 	}
   485     return fd;
   486 }  /* PR_CreateIOLayer */
   488 /*
   489  * _PR_DestroyIOLayer
   490  *		Delete the stack head of a new style stack.
   491  */
   493 static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack)
   494 {
   495     if (NULL == stack)
   496         return PR_FAILURE;
   497     else {
   498         PR_DELETE(stack);
   499     	return PR_SUCCESS;
   500     }
   501 }  /* _PR_DestroyIOLayer */
   503 PR_IMPLEMENT(PRStatus) PR_PushIOLayer(
   504     PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd)
   505 {
   506     PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id);
   508     PR_ASSERT(fd != NULL);
   509     PR_ASSERT(stack != NULL);
   510     PR_ASSERT(insert != NULL);
   511     PR_ASSERT(PR_IO_LAYER_HEAD != id);
   512     if ((NULL == stack) || (NULL == fd) || (NULL == insert))
   513     {
   514         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   515         return PR_FAILURE;
   516     }
   518     if (stack == insert)
   519     {
   520 		/* going on top of the stack */
   521 		/* old-style stack */	
   522 		PRFileDesc copy = *stack;
   523 		*stack = *fd;
   524 		*fd = copy;
   525 		fd->higher = stack;
   526 		if (fd->lower)
   527 		{
   528 			PR_ASSERT(fd->lower->higher == stack);
   529 			fd->lower->higher = fd;
   530 		}
   531 		stack->lower = fd;
   532 		stack->higher = NULL;
   533 	} else {
   534         /*
   535 		 * going somewhere in the middle of the stack for both old and new
   536 		 * style stacks, or going on top of stack for new style stack
   537 		 */
   538         fd->lower = insert;
   539         fd->higher = insert->higher;
   541         insert->higher->lower = fd;
   542         insert->higher = fd;
   543     }
   545     return PR_SUCCESS;
   546 }
   548 PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id)
   549 {
   550     PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id);
   552     PR_ASSERT(0 != id);
   553     PR_ASSERT(NULL != stack);
   554     PR_ASSERT(NULL != extract);
   555     if ((NULL == stack) || (0 == id) || (NULL == extract))
   556     {
   557         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   558         return NULL;
   559     }
   561     if (extract == stack) {
   562         /* popping top layer of the stack */
   563 		/* old style stack */
   564         PRFileDesc copy = *stack;
   565         extract = stack->lower;
   566         *stack = *extract;
   567         *extract = copy;
   568         stack->higher = NULL;
   569         if (stack->lower) {
   570             PR_ASSERT(stack->lower->higher == extract);
   571             stack->lower->higher = stack;
   572         }
   573 	} else if ((PR_IO_LAYER_HEAD == stack->identity) &&
   574 					(extract == stack->lower) && (extract->lower == NULL)) {
   575 			/*
   576 			 * new style stack
   577 			 * popping the only layer in the stack; delete the stack too
   578 			 */
   579 			stack->lower = NULL;
   580 			_PR_DestroyIOLayer(stack);
   581 	} else {
   582 		/* for both kinds of stacks */
   583         extract->lower->higher = extract->higher;
   584         extract->higher->lower = extract->lower;
   585     }
   586     extract->higher = extract->lower = NULL;
   587     return extract;
   588 }  /* PR_PopIOLayer */
   590 #define ID_CACHE_INCREMENT 16
   591 typedef struct _PRIdentity_cache
   592 {
   593     PRLock *ml;
   594     char **name;
   595     PRIntn length;
   596     PRDescIdentity ident;
   597 } _PRIdentity_cache;
   599 static _PRIdentity_cache identity_cache;
   601 PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name)
   602 {
   603     PRDescIdentity identity, length;
   604     char **names = NULL, *name = NULL, **old = NULL;
   606     if (!_pr_initialized) _PR_ImplicitInitialization();
   608     PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident);
   610     if (NULL != layer_name)
   611     {
   612         name = (char*)PR_Malloc(strlen(layer_name) + 1);
   613         if (NULL == name)
   614         {
   615             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   616             return PR_INVALID_IO_LAYER;
   617         }
   618         strcpy(name, layer_name);
   619     }
   621     /* this initial code runs unsafe */
   622 retry:
   623     PR_ASSERT(NULL == names);
   624     /*
   625      * In the initial round, both identity_cache.ident and
   626      * identity_cache.length are 0, so (identity_cache.ident + 1) is greater
   627      * than length.  In later rounds, identity_cache.ident is always less
   628      * than length, so (identity_cache.ident + 1) can be equal to but cannot
   629      * be greater than length.
   630      */
   631     length = identity_cache.length;
   632     if ((identity_cache.ident + 1) >= length)
   633     {
   634         length += ID_CACHE_INCREMENT;
   635         names = (char**)PR_CALLOC(length * sizeof(char*));
   636         if (NULL == names)
   637         {
   638             if (NULL != name) PR_DELETE(name);
   639             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   640             return PR_INVALID_IO_LAYER;
   641         }
   642     }
   644     /* now we get serious about thread safety */
   645     PR_Lock(identity_cache.ml);
   646     PR_ASSERT(identity_cache.length == 0 ||
   647               identity_cache.ident < identity_cache.length);
   648     identity = identity_cache.ident + 1;
   649     if (identity >= identity_cache.length)  /* there's no room */
   650     {
   651         /* we have to do something - hopefully it's already done */
   652         if ((NULL != names) && (identity < length))
   653         {
   654             /* what we did is still okay */
   655             memcpy(
   656                 names, identity_cache.name,
   657                 identity_cache.length * sizeof(char*));
   658             old = identity_cache.name;
   659             identity_cache.name = names;
   660             identity_cache.length = length;
   661             names = NULL;
   662         }
   663         else
   664         {
   665             PR_Unlock(identity_cache.ml);
   666             if (NULL != names) PR_DELETE(names);
   667             goto retry;
   668         }
   669     }
   670     if (NULL != name) /* there's a name to be stored */
   671     {
   672         identity_cache.name[identity] = name;
   673     }
   674     identity_cache.ident = identity;
   675     PR_ASSERT(identity_cache.ident < identity_cache.length);
   676     PR_Unlock(identity_cache.ml);
   678     if (NULL != old) PR_DELETE(old);
   679     if (NULL != names) PR_DELETE(names);
   681     return identity;
   682 }  /* PR_GetUniqueIdentity */
   684 PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident)
   685 {
   686     if (!_pr_initialized) _PR_ImplicitInitialization();
   688     if (PR_TOP_IO_LAYER == ident) return NULL;
   690     PR_ASSERT(ident <= identity_cache.ident);
   691     return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident];
   692 }  /* PR_GetNameForIdentity */
   694 PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd)
   695 {
   696     PR_ASSERT(NULL != fd);
   697     if (PR_IO_LAYER_HEAD == fd->identity) {
   698     	PR_ASSERT(NULL != fd->lower);
   699     	return fd->lower->identity;
   700 	} else
   701     	return fd->identity;
   702 }  /* PR_GetLayersIdentity */
   704 PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id)
   705 {
   706     PRFileDesc *layer = fd;
   708     if (PR_TOP_IO_LAYER == id) {
   709     	if (PR_IO_LAYER_HEAD == fd->identity)
   710 			return fd->lower;
   711 		else 
   712 			return fd;
   713 	}
   715     for (layer = fd; layer != NULL; layer = layer->lower)
   716     {
   717         if (id == layer->identity) return layer;
   718     }
   719     for (layer = fd; layer != NULL; layer = layer->higher)
   720     {
   721         if (id == layer->identity) return layer;
   722     }
   723     return NULL;
   724 }  /* PR_GetIdentitiesLayer */
   726 void _PR_InitLayerCache(void)
   727 {
   728     memset(&identity_cache, 0, sizeof(identity_cache));
   729     identity_cache.ml = PR_NewLock();
   730     PR_ASSERT(NULL != identity_cache.ml);
   731 }  /* _PR_InitLayerCache */
   733 void _PR_CleanupLayerCache(void)
   734 {
   735     if (identity_cache.ml)
   736     {
   737         PR_DestroyLock(identity_cache.ml);
   738         identity_cache.ml = NULL;
   739     }
   741     if (identity_cache.name)
   742     {
   743         PRDescIdentity ident;
   745         for (ident = 0; ident <= identity_cache.ident; ident++)
   746             PR_DELETE(identity_cache.name[ident]);
   748         PR_DELETE(identity_cache.name);
   749     }
   750 }  /* _PR_CleanupLayerCache */
   752 /* prlayer.c */

mercurial