1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/io/prlayer.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,752 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: prlayer.c 1.11 +** Description: Routines for handling pushable protocol modules on sockets. 1.12 +*/ 1.13 + 1.14 +#include "primpl.h" 1.15 +#include "prerror.h" 1.16 +#include "prmem.h" 1.17 +#include "prlock.h" 1.18 +#include "prlog.h" 1.19 +#include "prio.h" 1.20 + 1.21 +#include <string.h> /* for memset() */ 1.22 +static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack); 1.23 + 1.24 +void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd) 1.25 +{ 1.26 + PR_ASSERT(fd != NULL); 1.27 + if (NULL != fd->lower) fd->lower->higher = fd->higher; 1.28 + if (NULL != fd->higher) fd->higher->lower = fd->lower; 1.29 + PR_DELETE(fd); 1.30 +} 1.31 + 1.32 +/* 1.33 +** Default methods that just call down to the next fd. 1.34 +*/ 1.35 +static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd) 1.36 +{ 1.37 + PRFileDesc *top, *lower; 1.38 + PRStatus rv; 1.39 + 1.40 + PR_ASSERT(fd != NULL); 1.41 + PR_ASSERT(fd->lower != NULL); 1.42 + PR_ASSERT(fd->secret == NULL); 1.43 + PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED); 1.44 + 1.45 + if (PR_IO_LAYER_HEAD == fd->identity) { 1.46 + /* 1.47 + * new style stack; close all the layers, before deleting the 1.48 + * stack head 1.49 + */ 1.50 + rv = fd->lower->methods->close(fd->lower); 1.51 + _PR_DestroyIOLayer(fd); 1.52 + return rv; 1.53 + } else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) { 1.54 + /* 1.55 + * lower layers of new style stack 1.56 + */ 1.57 + lower = fd->lower; 1.58 + /* 1.59 + * pop and cleanup current layer 1.60 + */ 1.61 + top = PR_PopIOLayer(fd->higher, PR_TOP_IO_LAYER); 1.62 + top->dtor(top); 1.63 + /* 1.64 + * then call lower layer 1.65 + */ 1.66 + return (lower->methods->close(lower)); 1.67 + } else { 1.68 + /* old style stack */ 1.69 + top = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); 1.70 + top->dtor(top); 1.71 + return (fd->methods->close)(fd); 1.72 + } 1.73 +} 1.74 + 1.75 +static PRInt32 PR_CALLBACK pl_DefRead (PRFileDesc *fd, void *buf, PRInt32 amount) 1.76 +{ 1.77 + PR_ASSERT(fd != NULL); 1.78 + PR_ASSERT(fd->lower != NULL); 1.79 + 1.80 + return (fd->lower->methods->read)(fd->lower, buf, amount); 1.81 +} 1.82 + 1.83 +static PRInt32 PR_CALLBACK pl_DefWrite ( 1.84 + PRFileDesc *fd, const void *buf, PRInt32 amount) 1.85 +{ 1.86 + PR_ASSERT(fd != NULL); 1.87 + PR_ASSERT(fd->lower != NULL); 1.88 + 1.89 + return (fd->lower->methods->write)(fd->lower, buf, amount); 1.90 +} 1.91 + 1.92 +static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd) 1.93 +{ 1.94 + PR_ASSERT(fd != NULL); 1.95 + PR_ASSERT(fd->lower != NULL); 1.96 + 1.97 + return (fd->lower->methods->available)(fd->lower); 1.98 +} 1.99 + 1.100 +static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd) 1.101 +{ 1.102 + PR_ASSERT(fd != NULL); 1.103 + PR_ASSERT(fd->lower != NULL); 1.104 + 1.105 + return (fd->lower->methods->available64)(fd->lower); 1.106 +} 1.107 + 1.108 +static PRStatus PR_CALLBACK pl_DefFsync (PRFileDesc *fd) 1.109 +{ 1.110 + PR_ASSERT(fd != NULL); 1.111 + PR_ASSERT(fd->lower != NULL); 1.112 + 1.113 + return (fd->lower->methods->fsync)(fd->lower); 1.114 +} 1.115 + 1.116 +static PRInt32 PR_CALLBACK pl_DefSeek ( 1.117 + PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) 1.118 +{ 1.119 + PR_ASSERT(fd != NULL); 1.120 + PR_ASSERT(fd->lower != NULL); 1.121 + 1.122 + return (fd->lower->methods->seek)(fd->lower, offset, how); 1.123 +} 1.124 + 1.125 +static PRInt64 PR_CALLBACK pl_DefSeek64 ( 1.126 + PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) 1.127 +{ 1.128 + PR_ASSERT(fd != NULL); 1.129 + PR_ASSERT(fd->lower != NULL); 1.130 + 1.131 + return (fd->lower->methods->seek64)(fd->lower, offset, how); 1.132 +} 1.133 + 1.134 +static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info) 1.135 +{ 1.136 + PR_ASSERT(fd != NULL); 1.137 + PR_ASSERT(fd->lower != NULL); 1.138 + 1.139 + return (fd->lower->methods->fileInfo)(fd->lower, info); 1.140 +} 1.141 + 1.142 +static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info) 1.143 +{ 1.144 + PR_ASSERT(fd != NULL); 1.145 + PR_ASSERT(fd->lower != NULL); 1.146 + 1.147 + return (fd->lower->methods->fileInfo64)(fd->lower, info); 1.148 +} 1.149 + 1.150 +static PRInt32 PR_CALLBACK pl_DefWritev (PRFileDesc *fd, const PRIOVec *iov, 1.151 + PRInt32 size, PRIntervalTime timeout) 1.152 +{ 1.153 + PR_ASSERT(fd != NULL); 1.154 + PR_ASSERT(fd->lower != NULL); 1.155 + 1.156 + return (fd->lower->methods->writev)(fd->lower, iov, size, timeout); 1.157 +} 1.158 + 1.159 +static PRStatus PR_CALLBACK pl_DefConnect ( 1.160 + PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) 1.161 +{ 1.162 + PR_ASSERT(fd != NULL); 1.163 + PR_ASSERT(fd->lower != NULL); 1.164 + 1.165 + return (fd->lower->methods->connect)(fd->lower, addr, timeout); 1.166 +} 1.167 + 1.168 +static PRStatus PR_CALLBACK pl_DefConnectcontinue ( 1.169 + PRFileDesc *fd, PRInt16 out_flags) 1.170 +{ 1.171 + PR_ASSERT(fd != NULL); 1.172 + PR_ASSERT(fd->lower != NULL); 1.173 + 1.174 + return (fd->lower->methods->connectcontinue)(fd->lower, out_flags); 1.175 +} 1.176 + 1.177 +static PRFileDesc* PR_CALLBACK pl_TopAccept ( 1.178 + PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) 1.179 +{ 1.180 + PRStatus rv; 1.181 + PRFileDesc *newfd, *layer = fd; 1.182 + PRFileDesc *newstack; 1.183 + PRBool newstyle_stack = PR_FALSE; 1.184 + 1.185 + PR_ASSERT(fd != NULL); 1.186 + PR_ASSERT(fd->lower != NULL); 1.187 + 1.188 + /* test for new style stack */ 1.189 + while (NULL != layer->higher) 1.190 + layer = layer->higher; 1.191 + newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE; 1.192 + newstack = PR_NEW(PRFileDesc); 1.193 + if (NULL == newstack) 1.194 + { 1.195 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.196 + return NULL; 1.197 + } 1.198 + *newstack = *fd; /* make a copy of the accepting layer */ 1.199 + 1.200 + newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout); 1.201 + if (NULL == newfd) 1.202 + { 1.203 + PR_DELETE(newstack); 1.204 + return NULL; 1.205 + } 1.206 + 1.207 + if (newstyle_stack) { 1.208 + newstack->lower = newfd; 1.209 + newfd->higher = newstack; 1.210 + return newstack; 1.211 + } else { 1.212 + /* this PR_PushIOLayer call cannot fail */ 1.213 + rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); 1.214 + PR_ASSERT(PR_SUCCESS == rv); 1.215 + return newfd; /* that's it */ 1.216 + } 1.217 +} 1.218 + 1.219 +static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr) 1.220 +{ 1.221 + PR_ASSERT(fd != NULL); 1.222 + PR_ASSERT(fd->lower != NULL); 1.223 + 1.224 + return (fd->lower->methods->bind)(fd->lower, addr); 1.225 +} 1.226 + 1.227 +static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog) 1.228 +{ 1.229 + PR_ASSERT(fd != NULL); 1.230 + PR_ASSERT(fd->lower != NULL); 1.231 + 1.232 + return (fd->lower->methods->listen)(fd->lower, backlog); 1.233 +} 1.234 + 1.235 +static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how) 1.236 +{ 1.237 + PR_ASSERT(fd != NULL); 1.238 + PR_ASSERT(fd->lower != NULL); 1.239 + 1.240 + return (fd->lower->methods->shutdown)(fd->lower, how); 1.241 +} 1.242 + 1.243 +static PRInt32 PR_CALLBACK pl_DefRecv ( 1.244 + PRFileDesc *fd, void *buf, PRInt32 amount, 1.245 + PRIntn flags, PRIntervalTime timeout) 1.246 +{ 1.247 + PR_ASSERT(fd != NULL); 1.248 + PR_ASSERT(fd->lower != NULL); 1.249 + 1.250 + return (fd->lower->methods->recv)( 1.251 + fd->lower, buf, amount, flags, timeout); 1.252 +} 1.253 + 1.254 +static PRInt32 PR_CALLBACK pl_DefSend ( 1.255 + PRFileDesc *fd, const void *buf, 1.256 + PRInt32 amount, PRIntn flags, PRIntervalTime timeout) 1.257 +{ 1.258 + PR_ASSERT(fd != NULL); 1.259 + PR_ASSERT(fd->lower != NULL); 1.260 + 1.261 + return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout); 1.262 +} 1.263 + 1.264 +static PRInt32 PR_CALLBACK pl_DefRecvfrom ( 1.265 + PRFileDesc *fd, void *buf, PRInt32 amount, 1.266 + PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) 1.267 +{ 1.268 + PR_ASSERT(fd != NULL); 1.269 + PR_ASSERT(fd->lower != NULL); 1.270 + 1.271 + return (fd->lower->methods->recvfrom)( 1.272 + fd->lower, buf, amount, flags, addr, timeout); 1.273 +} 1.274 + 1.275 +static PRInt32 PR_CALLBACK pl_DefSendto ( 1.276 + PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, 1.277 + const PRNetAddr *addr, PRIntervalTime timeout) 1.278 +{ 1.279 + PR_ASSERT(fd != NULL); 1.280 + PR_ASSERT(fd->lower != NULL); 1.281 + 1.282 + return (fd->lower->methods->sendto)( 1.283 + fd->lower, buf, amount, flags, addr, timeout); 1.284 +} 1.285 + 1.286 +static PRInt16 PR_CALLBACK pl_DefPoll ( 1.287 + PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) 1.288 +{ 1.289 + PR_ASSERT(fd != NULL); 1.290 + PR_ASSERT(fd->lower != NULL); 1.291 + 1.292 + return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags); 1.293 +} 1.294 + 1.295 +static PRInt32 PR_CALLBACK pl_DefAcceptread ( 1.296 + PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, 1.297 + PRInt32 amount, PRIntervalTime t) 1.298 +{ 1.299 + PRInt32 nbytes; 1.300 + PRStatus rv; 1.301 + PRFileDesc *newstack; 1.302 + PRFileDesc *layer = sd; 1.303 + PRBool newstyle_stack = PR_FALSE; 1.304 + 1.305 + PR_ASSERT(sd != NULL); 1.306 + PR_ASSERT(sd->lower != NULL); 1.307 + 1.308 + /* test for new style stack */ 1.309 + while (NULL != layer->higher) 1.310 + layer = layer->higher; 1.311 + newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE; 1.312 + newstack = PR_NEW(PRFileDesc); 1.313 + if (NULL == newstack) 1.314 + { 1.315 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.316 + return -1; 1.317 + } 1.318 + *newstack = *sd; /* make a copy of the accepting layer */ 1.319 + 1.320 + nbytes = sd->lower->methods->acceptread( 1.321 + sd->lower, nd, raddr, buf, amount, t); 1.322 + if (-1 == nbytes) 1.323 + { 1.324 + PR_DELETE(newstack); 1.325 + return nbytes; 1.326 + } 1.327 + if (newstyle_stack) { 1.328 + newstack->lower = *nd; 1.329 + (*nd)->higher = newstack; 1.330 + *nd = newstack; 1.331 + return nbytes; 1.332 + } else { 1.333 + /* this PR_PushIOLayer call cannot fail */ 1.334 + rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); 1.335 + PR_ASSERT(PR_SUCCESS == rv); 1.336 + return nbytes; 1.337 + } 1.338 +} 1.339 + 1.340 +static PRInt32 PR_CALLBACK pl_DefTransmitfile ( 1.341 + PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, 1.342 + PRTransmitFileFlags flags, PRIntervalTime t) 1.343 +{ 1.344 + PR_ASSERT(sd != NULL); 1.345 + PR_ASSERT(sd->lower != NULL); 1.346 + 1.347 + return sd->lower->methods->transmitfile( 1.348 + sd->lower, fd, headers, hlen, flags, t); 1.349 +} 1.350 + 1.351 +static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr) 1.352 +{ 1.353 + PR_ASSERT(fd != NULL); 1.354 + PR_ASSERT(fd->lower != NULL); 1.355 + 1.356 + return (fd->lower->methods->getsockname)(fd->lower, addr); 1.357 +} 1.358 + 1.359 +static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr) 1.360 +{ 1.361 + PR_ASSERT(fd != NULL); 1.362 + PR_ASSERT(fd->lower != NULL); 1.363 + 1.364 + return (fd->lower->methods->getpeername)(fd->lower, addr); 1.365 +} 1.366 + 1.367 +static PRStatus PR_CALLBACK pl_DefGetsocketoption ( 1.368 + PRFileDesc *fd, PRSocketOptionData *data) 1.369 +{ 1.370 + PR_ASSERT(fd != NULL); 1.371 + PR_ASSERT(fd->lower != NULL); 1.372 + 1.373 + return (fd->lower->methods->getsocketoption)(fd->lower, data); 1.374 +} 1.375 + 1.376 +static PRStatus PR_CALLBACK pl_DefSetsocketoption ( 1.377 + PRFileDesc *fd, const PRSocketOptionData *data) 1.378 +{ 1.379 + PR_ASSERT(fd != NULL); 1.380 + PR_ASSERT(fd->lower != NULL); 1.381 + 1.382 + return (fd->lower->methods->setsocketoption)(fd->lower, data); 1.383 +} 1.384 + 1.385 +static PRInt32 PR_CALLBACK pl_DefSendfile ( 1.386 + PRFileDesc *sd, PRSendFileData *sfd, 1.387 + PRTransmitFileFlags flags, PRIntervalTime timeout) 1.388 +{ 1.389 + PR_ASSERT(sd != NULL); 1.390 + PR_ASSERT(sd->lower != NULL); 1.391 + 1.392 + return sd->lower->methods->sendfile( 1.393 + sd->lower, sfd, flags, timeout); 1.394 +} 1.395 + 1.396 +/* Methods for the top of the stack. Just call down to the next fd. */ 1.397 +static PRIOMethods pl_methods = { 1.398 + PR_DESC_LAYERED, 1.399 + pl_TopClose, 1.400 + pl_DefRead, 1.401 + pl_DefWrite, 1.402 + pl_DefAvailable, 1.403 + pl_DefAvailable64, 1.404 + pl_DefFsync, 1.405 + pl_DefSeek, 1.406 + pl_DefSeek64, 1.407 + pl_DefFileInfo, 1.408 + pl_DefFileInfo64, 1.409 + pl_DefWritev, 1.410 + pl_DefConnect, 1.411 + pl_TopAccept, 1.412 + pl_DefBind, 1.413 + pl_DefListen, 1.414 + pl_DefShutdown, 1.415 + pl_DefRecv, 1.416 + pl_DefSend, 1.417 + pl_DefRecvfrom, 1.418 + pl_DefSendto, 1.419 + pl_DefPoll, 1.420 + pl_DefAcceptread, 1.421 + pl_DefTransmitfile, 1.422 + pl_DefGetsockname, 1.423 + pl_DefGetpeername, 1.424 + (PRReservedFN)_PR_InvalidInt, 1.425 + (PRReservedFN)_PR_InvalidInt, 1.426 + pl_DefGetsocketoption, 1.427 + pl_DefSetsocketoption, 1.428 + pl_DefSendfile, 1.429 + pl_DefConnectcontinue, 1.430 + (PRReservedFN)_PR_InvalidInt, 1.431 + (PRReservedFN)_PR_InvalidInt, 1.432 + (PRReservedFN)_PR_InvalidInt, 1.433 + (PRReservedFN)_PR_InvalidInt 1.434 +}; 1.435 + 1.436 +PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void) 1.437 +{ 1.438 + return &pl_methods; 1.439 +} /* PR_GetDefaultIOMethods */ 1.440 + 1.441 +PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub( 1.442 + PRDescIdentity ident, const PRIOMethods *methods) 1.443 +{ 1.444 + PRFileDesc *fd = NULL; 1.445 + PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident)); 1.446 + if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident)) 1.447 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.448 + else 1.449 + { 1.450 + fd = PR_NEWZAP(PRFileDesc); 1.451 + if (NULL == fd) 1.452 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.453 + else 1.454 + { 1.455 + fd->methods = methods; 1.456 + fd->dtor = pl_FDDestructor; 1.457 + fd->identity = ident; 1.458 + } 1.459 + } 1.460 + return fd; 1.461 +} /* PR_CreateIOLayerStub */ 1.462 + 1.463 +/* 1.464 + * PR_CreateIOLayer 1.465 + * Create a new style stack, where the stack top is a dummy header. 1.466 + * Unlike the old style stacks, the contents of the stack head 1.467 + * are not modified when a layer is pushed onto or popped from a new 1.468 + * style stack. 1.469 + */ 1.470 + 1.471 +PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top) 1.472 +{ 1.473 + PRFileDesc *fd = NULL; 1.474 + 1.475 + fd = PR_NEWZAP(PRFileDesc); 1.476 + if (NULL == fd) 1.477 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.478 + else 1.479 + { 1.480 + fd->methods = &pl_methods; 1.481 + fd->dtor = pl_FDDestructor; 1.482 + fd->identity = PR_IO_LAYER_HEAD; 1.483 + fd->higher = NULL; 1.484 + fd->lower = top; 1.485 + top->higher = fd; 1.486 + top->lower = NULL; 1.487 + } 1.488 + return fd; 1.489 +} /* PR_CreateIOLayer */ 1.490 + 1.491 +/* 1.492 + * _PR_DestroyIOLayer 1.493 + * Delete the stack head of a new style stack. 1.494 + */ 1.495 + 1.496 +static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack) 1.497 +{ 1.498 + if (NULL == stack) 1.499 + return PR_FAILURE; 1.500 + else { 1.501 + PR_DELETE(stack); 1.502 + return PR_SUCCESS; 1.503 + } 1.504 +} /* _PR_DestroyIOLayer */ 1.505 + 1.506 +PR_IMPLEMENT(PRStatus) PR_PushIOLayer( 1.507 + PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd) 1.508 +{ 1.509 + PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id); 1.510 + 1.511 + PR_ASSERT(fd != NULL); 1.512 + PR_ASSERT(stack != NULL); 1.513 + PR_ASSERT(insert != NULL); 1.514 + PR_ASSERT(PR_IO_LAYER_HEAD != id); 1.515 + if ((NULL == stack) || (NULL == fd) || (NULL == insert)) 1.516 + { 1.517 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.518 + return PR_FAILURE; 1.519 + } 1.520 + 1.521 + if (stack == insert) 1.522 + { 1.523 + /* going on top of the stack */ 1.524 + /* old-style stack */ 1.525 + PRFileDesc copy = *stack; 1.526 + *stack = *fd; 1.527 + *fd = copy; 1.528 + fd->higher = stack; 1.529 + if (fd->lower) 1.530 + { 1.531 + PR_ASSERT(fd->lower->higher == stack); 1.532 + fd->lower->higher = fd; 1.533 + } 1.534 + stack->lower = fd; 1.535 + stack->higher = NULL; 1.536 + } else { 1.537 + /* 1.538 + * going somewhere in the middle of the stack for both old and new 1.539 + * style stacks, or going on top of stack for new style stack 1.540 + */ 1.541 + fd->lower = insert; 1.542 + fd->higher = insert->higher; 1.543 + 1.544 + insert->higher->lower = fd; 1.545 + insert->higher = fd; 1.546 + } 1.547 + 1.548 + return PR_SUCCESS; 1.549 +} 1.550 + 1.551 +PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id) 1.552 +{ 1.553 + PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id); 1.554 + 1.555 + PR_ASSERT(0 != id); 1.556 + PR_ASSERT(NULL != stack); 1.557 + PR_ASSERT(NULL != extract); 1.558 + if ((NULL == stack) || (0 == id) || (NULL == extract)) 1.559 + { 1.560 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.561 + return NULL; 1.562 + } 1.563 + 1.564 + if (extract == stack) { 1.565 + /* popping top layer of the stack */ 1.566 + /* old style stack */ 1.567 + PRFileDesc copy = *stack; 1.568 + extract = stack->lower; 1.569 + *stack = *extract; 1.570 + *extract = copy; 1.571 + stack->higher = NULL; 1.572 + if (stack->lower) { 1.573 + PR_ASSERT(stack->lower->higher == extract); 1.574 + stack->lower->higher = stack; 1.575 + } 1.576 + } else if ((PR_IO_LAYER_HEAD == stack->identity) && 1.577 + (extract == stack->lower) && (extract->lower == NULL)) { 1.578 + /* 1.579 + * new style stack 1.580 + * popping the only layer in the stack; delete the stack too 1.581 + */ 1.582 + stack->lower = NULL; 1.583 + _PR_DestroyIOLayer(stack); 1.584 + } else { 1.585 + /* for both kinds of stacks */ 1.586 + extract->lower->higher = extract->higher; 1.587 + extract->higher->lower = extract->lower; 1.588 + } 1.589 + extract->higher = extract->lower = NULL; 1.590 + return extract; 1.591 +} /* PR_PopIOLayer */ 1.592 + 1.593 +#define ID_CACHE_INCREMENT 16 1.594 +typedef struct _PRIdentity_cache 1.595 +{ 1.596 + PRLock *ml; 1.597 + char **name; 1.598 + PRIntn length; 1.599 + PRDescIdentity ident; 1.600 +} _PRIdentity_cache; 1.601 + 1.602 +static _PRIdentity_cache identity_cache; 1.603 + 1.604 +PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name) 1.605 +{ 1.606 + PRDescIdentity identity, length; 1.607 + char **names = NULL, *name = NULL, **old = NULL; 1.608 + 1.609 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.610 + 1.611 + PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident); 1.612 + 1.613 + if (NULL != layer_name) 1.614 + { 1.615 + name = (char*)PR_Malloc(strlen(layer_name) + 1); 1.616 + if (NULL == name) 1.617 + { 1.618 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.619 + return PR_INVALID_IO_LAYER; 1.620 + } 1.621 + strcpy(name, layer_name); 1.622 + } 1.623 + 1.624 + /* this initial code runs unsafe */ 1.625 +retry: 1.626 + PR_ASSERT(NULL == names); 1.627 + /* 1.628 + * In the initial round, both identity_cache.ident and 1.629 + * identity_cache.length are 0, so (identity_cache.ident + 1) is greater 1.630 + * than length. In later rounds, identity_cache.ident is always less 1.631 + * than length, so (identity_cache.ident + 1) can be equal to but cannot 1.632 + * be greater than length. 1.633 + */ 1.634 + length = identity_cache.length; 1.635 + if ((identity_cache.ident + 1) >= length) 1.636 + { 1.637 + length += ID_CACHE_INCREMENT; 1.638 + names = (char**)PR_CALLOC(length * sizeof(char*)); 1.639 + if (NULL == names) 1.640 + { 1.641 + if (NULL != name) PR_DELETE(name); 1.642 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.643 + return PR_INVALID_IO_LAYER; 1.644 + } 1.645 + } 1.646 + 1.647 + /* now we get serious about thread safety */ 1.648 + PR_Lock(identity_cache.ml); 1.649 + PR_ASSERT(identity_cache.length == 0 || 1.650 + identity_cache.ident < identity_cache.length); 1.651 + identity = identity_cache.ident + 1; 1.652 + if (identity >= identity_cache.length) /* there's no room */ 1.653 + { 1.654 + /* we have to do something - hopefully it's already done */ 1.655 + if ((NULL != names) && (identity < length)) 1.656 + { 1.657 + /* what we did is still okay */ 1.658 + memcpy( 1.659 + names, identity_cache.name, 1.660 + identity_cache.length * sizeof(char*)); 1.661 + old = identity_cache.name; 1.662 + identity_cache.name = names; 1.663 + identity_cache.length = length; 1.664 + names = NULL; 1.665 + } 1.666 + else 1.667 + { 1.668 + PR_Unlock(identity_cache.ml); 1.669 + if (NULL != names) PR_DELETE(names); 1.670 + goto retry; 1.671 + } 1.672 + } 1.673 + if (NULL != name) /* there's a name to be stored */ 1.674 + { 1.675 + identity_cache.name[identity] = name; 1.676 + } 1.677 + identity_cache.ident = identity; 1.678 + PR_ASSERT(identity_cache.ident < identity_cache.length); 1.679 + PR_Unlock(identity_cache.ml); 1.680 + 1.681 + if (NULL != old) PR_DELETE(old); 1.682 + if (NULL != names) PR_DELETE(names); 1.683 + 1.684 + return identity; 1.685 +} /* PR_GetUniqueIdentity */ 1.686 + 1.687 +PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident) 1.688 +{ 1.689 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.690 + 1.691 + if (PR_TOP_IO_LAYER == ident) return NULL; 1.692 + 1.693 + PR_ASSERT(ident <= identity_cache.ident); 1.694 + return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident]; 1.695 +} /* PR_GetNameForIdentity */ 1.696 + 1.697 +PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd) 1.698 +{ 1.699 + PR_ASSERT(NULL != fd); 1.700 + if (PR_IO_LAYER_HEAD == fd->identity) { 1.701 + PR_ASSERT(NULL != fd->lower); 1.702 + return fd->lower->identity; 1.703 + } else 1.704 + return fd->identity; 1.705 +} /* PR_GetLayersIdentity */ 1.706 + 1.707 +PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id) 1.708 +{ 1.709 + PRFileDesc *layer = fd; 1.710 + 1.711 + if (PR_TOP_IO_LAYER == id) { 1.712 + if (PR_IO_LAYER_HEAD == fd->identity) 1.713 + return fd->lower; 1.714 + else 1.715 + return fd; 1.716 + } 1.717 + 1.718 + for (layer = fd; layer != NULL; layer = layer->lower) 1.719 + { 1.720 + if (id == layer->identity) return layer; 1.721 + } 1.722 + for (layer = fd; layer != NULL; layer = layer->higher) 1.723 + { 1.724 + if (id == layer->identity) return layer; 1.725 + } 1.726 + return NULL; 1.727 +} /* PR_GetIdentitiesLayer */ 1.728 + 1.729 +void _PR_InitLayerCache(void) 1.730 +{ 1.731 + memset(&identity_cache, 0, sizeof(identity_cache)); 1.732 + identity_cache.ml = PR_NewLock(); 1.733 + PR_ASSERT(NULL != identity_cache.ml); 1.734 +} /* _PR_InitLayerCache */ 1.735 + 1.736 +void _PR_CleanupLayerCache(void) 1.737 +{ 1.738 + if (identity_cache.ml) 1.739 + { 1.740 + PR_DestroyLock(identity_cache.ml); 1.741 + identity_cache.ml = NULL; 1.742 + } 1.743 + 1.744 + if (identity_cache.name) 1.745 + { 1.746 + PRDescIdentity ident; 1.747 + 1.748 + for (ident = 0; ident <= identity_cache.ident; ident++) 1.749 + PR_DELETE(identity_cache.name[ident]); 1.750 + 1.751 + PR_DELETE(identity_cache.name); 1.752 + } 1.753 +} /* _PR_CleanupLayerCache */ 1.754 + 1.755 +/* prlayer.c */