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