Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/io/prlayer.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 { | |
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 } | |
28 | |
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; | |
36 | |
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); | |
41 | |
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 } | |
71 | |
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); | |
76 | |
77 return (fd->lower->methods->read)(fd->lower, buf, amount); | |
78 } | |
79 | |
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); | |
85 | |
86 return (fd->lower->methods->write)(fd->lower, buf, amount); | |
87 } | |
88 | |
89 static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd) | |
90 { | |
91 PR_ASSERT(fd != NULL); | |
92 PR_ASSERT(fd->lower != NULL); | |
93 | |
94 return (fd->lower->methods->available)(fd->lower); | |
95 } | |
96 | |
97 static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd) | |
98 { | |
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 { | |
107 PR_ASSERT(fd != NULL); | |
108 PR_ASSERT(fd->lower != NULL); | |
109 | |
110 return (fd->lower->methods->fsync)(fd->lower); | |
111 } | |
112 | |
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); | |
118 | |
119 return (fd->lower->methods->seek)(fd->lower, offset, how); | |
120 } | |
121 | |
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); | |
127 | |
128 return (fd->lower->methods->seek64)(fd->lower, offset, how); | |
129 } | |
130 | |
131 static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info) | |
132 { | |
133 PR_ASSERT(fd != NULL); | |
134 PR_ASSERT(fd->lower != NULL); | |
135 | |
136 return (fd->lower->methods->fileInfo)(fd->lower, info); | |
137 } | |
138 | |
139 static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info) | |
140 { | |
141 PR_ASSERT(fd != NULL); | |
142 PR_ASSERT(fd->lower != NULL); | |
143 | |
144 return (fd->lower->methods->fileInfo64)(fd->lower, info); | |
145 } | |
146 | |
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); | |
152 | |
153 return (fd->lower->methods->writev)(fd->lower, iov, size, timeout); | |
154 } | |
155 | |
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); | |
161 | |
162 return (fd->lower->methods->connect)(fd->lower, addr, timeout); | |
163 } | |
164 | |
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); | |
170 | |
171 return (fd->lower->methods->connectcontinue)(fd->lower, out_flags); | |
172 } | |
173 | |
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; | |
181 | |
182 PR_ASSERT(fd != NULL); | |
183 PR_ASSERT(fd->lower != NULL); | |
184 | |
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 */ | |
196 | |
197 newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout); | |
198 if (NULL == newfd) | |
199 { | |
200 PR_DELETE(newstack); | |
201 return NULL; | |
202 } | |
203 | |
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 } | |
215 | |
216 static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr) | |
217 { | |
218 PR_ASSERT(fd != NULL); | |
219 PR_ASSERT(fd->lower != NULL); | |
220 | |
221 return (fd->lower->methods->bind)(fd->lower, addr); | |
222 } | |
223 | |
224 static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog) | |
225 { | |
226 PR_ASSERT(fd != NULL); | |
227 PR_ASSERT(fd->lower != NULL); | |
228 | |
229 return (fd->lower->methods->listen)(fd->lower, backlog); | |
230 } | |
231 | |
232 static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how) | |
233 { | |
234 PR_ASSERT(fd != NULL); | |
235 PR_ASSERT(fd->lower != NULL); | |
236 | |
237 return (fd->lower->methods->shutdown)(fd->lower, how); | |
238 } | |
239 | |
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); | |
246 | |
247 return (fd->lower->methods->recv)( | |
248 fd->lower, buf, amount, flags, timeout); | |
249 } | |
250 | |
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); | |
257 | |
258 return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout); | |
259 } | |
260 | |
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); | |
267 | |
268 return (fd->lower->methods->recvfrom)( | |
269 fd->lower, buf, amount, flags, addr, timeout); | |
270 } | |
271 | |
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); | |
278 | |
279 return (fd->lower->methods->sendto)( | |
280 fd->lower, buf, amount, flags, addr, timeout); | |
281 } | |
282 | |
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); | |
288 | |
289 return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags); | |
290 } | |
291 | |
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; | |
301 | |
302 PR_ASSERT(sd != NULL); | |
303 PR_ASSERT(sd->lower != NULL); | |
304 | |
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 */ | |
316 | |
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 } | |
336 | |
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); | |
343 | |
344 return sd->lower->methods->transmitfile( | |
345 sd->lower, fd, headers, hlen, flags, t); | |
346 } | |
347 | |
348 static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr) | |
349 { | |
350 PR_ASSERT(fd != NULL); | |
351 PR_ASSERT(fd->lower != NULL); | |
352 | |
353 return (fd->lower->methods->getsockname)(fd->lower, addr); | |
354 } | |
355 | |
356 static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr) | |
357 { | |
358 PR_ASSERT(fd != NULL); | |
359 PR_ASSERT(fd->lower != NULL); | |
360 | |
361 return (fd->lower->methods->getpeername)(fd->lower, addr); | |
362 } | |
363 | |
364 static PRStatus PR_CALLBACK pl_DefGetsocketoption ( | |
365 PRFileDesc *fd, PRSocketOptionData *data) | |
366 { | |
367 PR_ASSERT(fd != NULL); | |
368 PR_ASSERT(fd->lower != NULL); | |
369 | |
370 return (fd->lower->methods->getsocketoption)(fd->lower, data); | |
371 } | |
372 | |
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); | |
378 | |
379 return (fd->lower->methods->setsocketoption)(fd->lower, data); | |
380 } | |
381 | |
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); | |
388 | |
389 return sd->lower->methods->sendfile( | |
390 sd->lower, sfd, flags, timeout); | |
391 } | |
392 | |
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 }; | |
432 | |
433 PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void) | |
434 { | |
435 return &pl_methods; | |
436 } /* PR_GetDefaultIOMethods */ | |
437 | |
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 */ | |
459 | |
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 */ | |
467 | |
468 PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top) | |
469 { | |
470 PRFileDesc *fd = NULL; | |
471 | |
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 */ | |
487 | |
488 /* | |
489 * _PR_DestroyIOLayer | |
490 * Delete the stack head of a new style stack. | |
491 */ | |
492 | |
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 */ | |
502 | |
503 PR_IMPLEMENT(PRStatus) PR_PushIOLayer( | |
504 PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd) | |
505 { | |
506 PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id); | |
507 | |
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 } | |
517 | |
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; | |
540 | |
541 insert->higher->lower = fd; | |
542 insert->higher = fd; | |
543 } | |
544 | |
545 return PR_SUCCESS; | |
546 } | |
547 | |
548 PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id) | |
549 { | |
550 PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id); | |
551 | |
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 } | |
560 | |
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 */ | |
589 | |
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; | |
598 | |
599 static _PRIdentity_cache identity_cache; | |
600 | |
601 PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name) | |
602 { | |
603 PRDescIdentity identity, length; | |
604 char **names = NULL, *name = NULL, **old = NULL; | |
605 | |
606 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
607 | |
608 PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident); | |
609 | |
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 } | |
620 | |
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 } | |
643 | |
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); | |
677 | |
678 if (NULL != old) PR_DELETE(old); | |
679 if (NULL != names) PR_DELETE(names); | |
680 | |
681 return identity; | |
682 } /* PR_GetUniqueIdentity */ | |
683 | |
684 PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident) | |
685 { | |
686 if (!_pr_initialized) _PR_ImplicitInitialization(); | |
687 | |
688 if (PR_TOP_IO_LAYER == ident) return NULL; | |
689 | |
690 PR_ASSERT(ident <= identity_cache.ident); | |
691 return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident]; | |
692 } /* PR_GetNameForIdentity */ | |
693 | |
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 */ | |
703 | |
704 PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id) | |
705 { | |
706 PRFileDesc *layer = fd; | |
707 | |
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 } | |
714 | |
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 */ | |
725 | |
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 */ | |
732 | |
733 void _PR_CleanupLayerCache(void) | |
734 { | |
735 if (identity_cache.ml) | |
736 { | |
737 PR_DestroyLock(identity_cache.ml); | |
738 identity_cache.ml = NULL; | |
739 } | |
740 | |
741 if (identity_cache.name) | |
742 { | |
743 PRDescIdentity ident; | |
744 | |
745 for (ident = 0; ident <= identity_cache.ident; ident++) | |
746 PR_DELETE(identity_cache.name[ident]); | |
747 | |
748 PR_DELETE(identity_cache.name); | |
749 } | |
750 } /* _PR_CleanupLayerCache */ | |
751 | |
752 /* prlayer.c */ |