| OLD | NEW |
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // Written in NSPR style to also be suitable for adding to the NSS demo suite | 4 // Written in NSPR style to also be suitable for adding to the NSS demo suite |
| 5 | 5 |
| 6 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 7 // for details. All rights reserved. Use of this source code is governed by a |
| 8 // BSD-style license that can be found in the LICENSE file. |
| 9 |
| 10 // This file is a modified copy of Chromium's src/net/base/nss_memio.c. |
| 11 // char* has been changed to uint8_t* everywhere, and C++ casts are used. |
| 12 // Revision 257452 (this should agree with "nss_rev" in DEPS). |
| 13 |
| 14 |
| 6 /* memio is a simple NSPR I/O layer that lets you decouple NSS from | 15 /* memio is a simple NSPR I/O layer that lets you decouple NSS from |
| 7 * the real network. It's rather like openssl's memory bio, | 16 * the real network. It's rather like openssl's memory bio, |
| 8 * and is useful when your app absolutely, positively doesn't | 17 * and is useful when your app absolutely, positively doesn't |
| 9 * want to let NSS do its own networking. | 18 * want to let NSS do its own networking. |
| 10 */ | 19 */ |
| 11 #include "bin/net/nss_memio.h" | 20 #include "bin/net/nss_memio.h" |
| 12 | 21 |
| 13 #include <stdio.h> | 22 #include <stdio.h> |
| 14 #include <stdlib.h> | 23 #include <stdlib.h> |
| 15 #include <string.h> | 24 #include <string.h> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 struct memio_buffer readbuf; | 57 struct memio_buffer readbuf; |
| 49 | 58 |
| 50 /* write requests are satisfied from this buffer */ | 59 /* write requests are satisfied from this buffer */ |
| 51 struct memio_buffer writebuf; | 60 struct memio_buffer writebuf; |
| 52 | 61 |
| 53 /* SSL needs to know socket peer's name */ | 62 /* SSL needs to know socket peer's name */ |
| 54 PRNetAddr peername; | 63 PRNetAddr peername; |
| 55 | 64 |
| 56 /* if set, empty I/O returns EOF instead of EWOULDBLOCK */ | 65 /* if set, empty I/O returns EOF instead of EWOULDBLOCK */ |
| 57 int eof; | 66 int eof; |
| 67 |
| 68 /* if set, the number of bytes requested from readbuf that were not |
| 69 * fulfilled (due to readbuf being empty) */ |
| 70 int read_requested; |
| 58 }; | 71 }; |
| 59 | 72 |
| 60 /*--------------- private memio_buffer functions ---------------------*/ | 73 /*--------------- private memio_buffer functions ---------------------*/ |
| 61 | 74 |
| 62 /* Forward declarations. */ | 75 /* Forward declarations. */ |
| 63 | 76 |
| 64 /* Allocate a memio_buffer of given size. */ | 77 /* Allocate a memio_buffer of given size. */ |
| 65 static void memio_buffer_new(struct memio_buffer *mb, int size); | 78 static void memio_buffer_new(struct memio_buffer *mb, int size); |
| 66 | 79 |
| 67 /* Deallocate a memio_buffer allocated by memio_buffer_new. */ | 80 /* Deallocate a memio_buffer allocated by memio_buffer_new. */ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 87 mb->head = 0; | 100 mb->head = 0; |
| 88 mb->tail = 0; | 101 mb->tail = 0; |
| 89 mb->bufsize = size; | 102 mb->bufsize = size; |
| 90 mb->buf = static_cast<uint8_t*>(malloc(size)); | 103 mb->buf = static_cast<uint8_t*>(malloc(size)); |
| 91 } | 104 } |
| 92 | 105 |
| 93 /* Deallocate a memio_buffer allocated by memio_buffer_new. */ | 106 /* Deallocate a memio_buffer allocated by memio_buffer_new. */ |
| 94 static void memio_buffer_destroy(struct memio_buffer *mb) { | 107 static void memio_buffer_destroy(struct memio_buffer *mb) { |
| 95 free(mb->buf); | 108 free(mb->buf); |
| 96 mb->buf = NULL; | 109 mb->buf = NULL; |
| 110 mb->bufsize = 0; |
| 97 mb->head = 0; | 111 mb->head = 0; |
| 98 mb->tail = 0; | 112 mb->tail = 0; |
| 99 } | 113 } |
| 100 | 114 |
| 101 /* How many bytes can be read out of the buffer without wrapping */ | 115 /* How many bytes can be read out of the buffer without wrapping */ |
| 102 static int memio_buffer_used_contiguous(const struct memio_buffer *mb) { | 116 static int memio_buffer_used_contiguous(const struct memio_buffer *mb) { |
| 103 return (((mb->tail >= mb->head) ? mb->tail : mb->bufsize) - mb->head); | 117 return (((mb->tail >= mb->head) ? mb->tail : mb->bufsize) - mb->head); |
| 104 } | 118 } |
| 105 | 119 |
| 106 /* How many bytes exist after the wrap? */ | 120 /* How many bytes exist after the wrap? */ |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 if (flags) { | 225 if (flags) { |
| 212 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); | 226 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); |
| 213 return -1; | 227 return -1; |
| 214 } | 228 } |
| 215 | 229 |
| 216 secret = fd->secret; | 230 secret = fd->secret; |
| 217 mb = &secret->readbuf; | 231 mb = &secret->readbuf; |
| 218 PR_ASSERT(mb->bufsize); | 232 PR_ASSERT(mb->bufsize); |
| 219 rv = memio_buffer_get(mb, buf, len); | 233 rv = memio_buffer_get(mb, buf, len); |
| 220 if (rv == 0 && !secret->eof) { | 234 if (rv == 0 && !secret->eof) { |
| 235 secret->read_requested = len; |
| 236 /* If there is no more data in the buffer, report any pending errors |
| 237 * that were previously observed. Note that both the readbuf and the |
| 238 * writebuf are checked for errors, since the application may have |
| 239 * encountered a socket error while writing that would otherwise not |
| 240 * be reported until the application attempted to write again - which |
| 241 * it may never do. |
| 242 */ |
| 221 if (mb->last_err) | 243 if (mb->last_err) |
| 222 PR_SetError(mb->last_err, 0); | 244 PR_SetError(mb->last_err, 0); |
| 245 else if (secret->writebuf.last_err) |
| 246 PR_SetError(secret->writebuf.last_err, 0); |
| 223 else | 247 else |
| 224 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | 248 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
| 225 return -1; | 249 return -1; |
| 226 } | 250 } |
| 227 | 251 |
| 252 secret->read_requested = 0; |
| 228 return rv; | 253 return rv; |
| 229 } | 254 } |
| 230 | 255 |
| 231 static int PR_CALLBACK memio_Read(PRFileDesc *fd, uint8_t *buf, PRInt32 len) { | 256 static int PR_CALLBACK memio_Read(PRFileDesc *fd, uint8_t *buf, PRInt32 len) { |
| 232 /* pull bytes from buffer */ | 257 /* pull bytes from buffer */ |
| 233 return memio_Recv(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT); | 258 return memio_Recv(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT); |
| 234 } | 259 } |
| 235 | 260 |
| 236 static int PR_CALLBACK memio_Send(PRFileDesc *fd, | 261 static int PR_CALLBACK memio_Send(PRFileDesc *fd, |
| 237 const uint8_t *buf, | 262 const uint8_t *buf, |
| 238 PRInt32 len, | 263 PRInt32 len, |
| 239 PRIntn flags, | 264 PRIntn flags, |
| 240 PRIntervalTime timeout) { | 265 PRIntervalTime timeout) { |
| 241 struct PRFilePrivate *secret; | 266 struct PRFilePrivate *secret; |
| 242 struct memio_buffer *mb; | 267 struct memio_buffer *mb; |
| 243 int rv; | 268 int rv; |
| 244 | 269 |
| 245 secret = fd->secret; | 270 secret = fd->secret; |
| 246 mb = &secret->writebuf; | 271 mb = &secret->writebuf; |
| 247 PR_ASSERT(mb->bufsize); | 272 PR_ASSERT(mb->bufsize); |
| 248 | 273 |
| 274 /* Note that the read error state is not reported, because it cannot be |
| 275 * reported until all buffered data has been read. If there is an error |
| 276 * with the next layer, attempting to call Send again will report the |
| 277 * error appropriately. |
| 278 */ |
| 249 if (mb->last_err) { | 279 if (mb->last_err) { |
| 250 PR_SetError(mb->last_err, 0); | 280 PR_SetError(mb->last_err, 0); |
| 251 return -1; | 281 return -1; |
| 252 } | 282 } |
| 253 rv = memio_buffer_put(mb, buf, len); | 283 rv = memio_buffer_put(mb, buf, len); |
| 254 if (rv == 0) { | 284 if (rv == 0) { |
| 255 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | 285 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
| 256 return -1; | 286 return -1; |
| 257 } | 287 } |
| 258 return rv; | 288 return rv; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 | 368 |
| 339 static PRDescIdentity memio_identity = PR_INVALID_IO_LAYER; | 369 static PRDescIdentity memio_identity = PR_INVALID_IO_LAYER; |
| 340 | 370 |
| 341 static PRStatus memio_InitializeLayerName(void) { | 371 static PRStatus memio_InitializeLayerName(void) { |
| 342 memio_identity = PR_GetUniqueIdentity("memio"); | 372 memio_identity = PR_GetUniqueIdentity("memio"); |
| 343 return PR_SUCCESS; | 373 return PR_SUCCESS; |
| 344 } | 374 } |
| 345 | 375 |
| 346 /*--------------- public memio functions -----------------------*/ | 376 /*--------------- public memio functions -----------------------*/ |
| 347 | 377 |
| 348 PRFileDesc *memio_CreateIOLayer(int bufsize) { | 378 PRFileDesc *memio_CreateIOLayer(int readbufsize, int writebufsize) { |
| 349 PRFileDesc *fd; | 379 PRFileDesc *fd; |
| 350 struct PRFilePrivate *secret; | 380 struct PRFilePrivate *secret; |
| 351 static PRCallOnceType once; | 381 static PRCallOnceType once; |
| 352 | 382 |
| 353 PR_CallOnce(&once, memio_InitializeLayerName); | 383 PR_CallOnce(&once, memio_InitializeLayerName); |
| 354 | 384 |
| 355 fd = PR_CreateIOLayerStub(memio_identity, &memio_layer_methods); | 385 fd = PR_CreateIOLayerStub(memio_identity, &memio_layer_methods); |
| 356 secret = static_cast<PRFilePrivate*>(malloc(sizeof(struct PRFilePrivate))); | 386 secret = static_cast<PRFilePrivate*>(malloc(sizeof(struct PRFilePrivate))); |
| 357 memset(secret, 0, sizeof(*secret)); | 387 memset(secret, 0, sizeof(*secret)); |
| 358 | 388 |
| 359 memio_buffer_new(&secret->readbuf, bufsize); | 389 memio_buffer_new(&secret->readbuf, readbufsize); |
| 360 memio_buffer_new(&secret->writebuf, bufsize); | 390 memio_buffer_new(&secret->writebuf, writebufsize); |
| 361 fd->secret = secret; | 391 fd->secret = secret; |
| 362 return fd; | 392 return fd; |
| 363 } | 393 } |
| 364 | 394 |
| 365 void memio_SetPeerName(PRFileDesc* fd, const PRNetAddr* peername) { | 395 void memio_SetPeerName(PRFileDesc* fd, const PRNetAddr* peername) { |
| 366 PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity); | 396 PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity); |
| 367 struct PRFilePrivate *secret = memiofd->secret; | 397 struct PRFilePrivate *secret = memiofd->secret; |
| 368 secret->peername = *peername; | 398 secret->peername = *peername; |
| 369 } | 399 } |
| 370 | 400 |
| 371 memio_Private* memio_GetSecret(PRFileDesc* fd) { | 401 memio_Private* memio_GetSecret(PRFileDesc* fd) { |
| 372 PRFileDesc* memiofd = PR_GetIdentitiesLayer(fd, memio_identity); | 402 PRFileDesc* memiofd = PR_GetIdentitiesLayer(fd, memio_identity); |
| 373 return reinterpret_cast<memio_Private*>(memiofd->secret); | 403 struct PRFilePrivate *secret = memiofd->secret; |
| 404 return reinterpret_cast<memio_Private*>(secret); |
| 405 } |
| 406 |
| 407 int memio_GetReadRequest(memio_Private *secret) { |
| 408 return reinterpret_cast<PRFilePrivate*>(secret)->read_requested; |
| 374 } | 409 } |
| 375 | 410 |
| 376 int memio_GetReadParams(memio_Private* secret, uint8_t** buf) { | 411 int memio_GetReadParams(memio_Private* secret, uint8_t** buf) { |
| 377 struct memio_buffer* mb = | 412 struct memio_buffer* mb = |
| 378 &(reinterpret_cast<PRFilePrivate*>(secret)->readbuf); | 413 &(reinterpret_cast<PRFilePrivate*>(secret)->readbuf); |
| 379 PR_ASSERT(mb->bufsize); | 414 PR_ASSERT(mb->bufsize); |
| 380 | 415 |
| 381 *buf = &mb->buf[mb->tail]; | 416 *buf = &mb->buf[mb->tail]; |
| 382 return memio_buffer_unused_contiguous(mb); | 417 return memio_buffer_unused_contiguous(mb); |
| 383 } | 418 } |
| 384 | 419 |
| 420 int memio_GetReadableBufferSize(memio_Private *secret) { |
| 421 struct memio_buffer* mb = |
| 422 &(reinterpret_cast<PRFilePrivate*>(secret)->readbuf); |
| 423 PR_ASSERT(mb->bufsize); |
| 424 |
| 425 return memio_buffer_used_contiguous(mb); |
| 426 } |
| 427 |
| 385 void memio_PutReadResult(memio_Private *secret, int bytes_read) { | 428 void memio_PutReadResult(memio_Private *secret, int bytes_read) { |
| 386 struct memio_buffer* mb = | 429 struct memio_buffer* mb = |
| 387 &(reinterpret_cast<PRFilePrivate*>(secret)->readbuf); | 430 &(reinterpret_cast<PRFilePrivate*>(secret)->readbuf); |
| 388 PR_ASSERT(mb->bufsize); | 431 PR_ASSERT(mb->bufsize); |
| 389 | 432 |
| 390 if (bytes_read > 0) { | 433 if (bytes_read > 0) { |
| 391 mb->tail += bytes_read; | 434 mb->tail += bytes_read; |
| 392 if (mb->tail == mb->bufsize) | 435 if (mb->tail == mb->bufsize) |
| 393 mb->tail = 0; | 436 mb->tail = 0; |
| 394 } else if (bytes_read == 0) { | 437 } else if (bytes_read == 0) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 CHECKEQ(memio_buffer_unused_contiguous(&mb), 0); | 525 CHECKEQ(memio_buffer_unused_contiguous(&mb), 0); |
| 483 CHECKEQ(memio_buffer_used_contiguous(&mb), 1); | 526 CHECKEQ(memio_buffer_used_contiguous(&mb), 1); |
| 484 | 527 |
| 485 /* TODO: add more cases */ | 528 /* TODO: add more cases */ |
| 486 | 529 |
| 487 printf("Test passed\n"); | 530 printf("Test passed\n"); |
| 488 exit(0); | 531 exit(0); |
| 489 } | 532 } |
| 490 | 533 |
| 491 #endif | 534 #endif |
| OLD | NEW |