1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2008 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Written in NSPR style to also be suitable for adding to the NSS demo suite 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* memio is a simple NSPR I/O layer that lets you decouple NSS from 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the real network. It's rather like openssl's memory bio, 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and is useful when your app absolutely, positively doesn't 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * want to let NSS do its own networking. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h> 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string.h> 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <prerror.h> 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <prinit.h> 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <prlog.h> 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "nss_memio.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- private memio types -----------------------*/ 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*---------------------------------------------------------------------- 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Simple private circular buffer class. Size cannot be changed once allocated. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott----------------------------------------------------------------------*/ 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct memio_buffer { 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int head; /* where to take next byte out of buf */ 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int tail; /* where to put next byte into buf */ 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bufsize; /* number of bytes allocated to buf */ 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* TODO(port): error handling is pessimistic right now. 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Once an error is set, the socket is considered broken 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (PR_WOULD_BLOCK_ERROR not included). 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRErrorCode last_err; 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *buf; 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* The 'secret' field of a PRFileDesc created by memio_CreateIOLayer points 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * to one of these. 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In the public header, we use struct memio_Private as a typesafe alias 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * for this. This causes a few ugly typecasts in the private file, but 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * seems safer. 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct PRFilePrivate { 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* read requests are satisfied from this buffer */ 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer readbuf; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* write requests are satisfied from this buffer */ 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer writebuf; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* SSL needs to know socket peer's name */ 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRNetAddr peername; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* if set, empty I/O returns EOF instead of EWOULDBLOCK */ 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int eof; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- private memio_buffer functions ---------------------*/ 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Forward declarations. */ 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Allocate a memio_buffer of given size. */ 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void memio_buffer_new(struct memio_buffer *mb, int size); 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Deallocate a memio_buffer allocated by memio_buffer_new. */ 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void memio_buffer_destroy(struct memio_buffer *mb); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* How many bytes can be read out of the buffer without wrapping */ 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_used_contiguous(const struct memio_buffer *mb); 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/* How many bytes exist after the wrap? */ 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic int memio_buffer_wrapped_bytes(const struct memio_buffer *mb); 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* How many bytes can be written into the buffer without wrapping */ 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_unused_contiguous(const struct memio_buffer *mb); 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Write n bytes into the buffer. Returns number of bytes written. */ 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_put(struct memio_buffer *mb, const char *buf, int n); 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Read n bytes from the buffer. Returns number of bytes read. */ 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_get(struct memio_buffer *mb, char *buf, int n); 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Allocate a memio_buffer of given size. */ 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void memio_buffer_new(struct memio_buffer *mb, int size) 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head = 0; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail = 0; 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->bufsize = size; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->buf = malloc(size); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Deallocate a memio_buffer allocated by memio_buffer_new. */ 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void memio_buffer_destroy(struct memio_buffer *mb) 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(mb->buf); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->buf = NULL; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head = 0; 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail = 0; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* How many bytes can be read out of the buffer without wrapping */ 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_used_contiguous(const struct memio_buffer *mb) 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (((mb->tail >= mb->head) ? mb->tail : mb->bufsize) - mb->head); 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick/* How many bytes exist after the wrap? */ 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic int memio_buffer_wrapped_bytes(const struct memio_buffer *mb) 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick{ 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return (mb->tail >= mb->head) ? 0 : mb->tail; 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* How many bytes can be written into the buffer without wrapping */ 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_unused_contiguous(const struct memio_buffer *mb) 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->head > mb->tail) return mb->head - mb->tail - 1; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return mb->bufsize - mb->tail - (mb->head == 0); 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Write n bytes into the buffer. Returns number of bytes written. */ 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_put(struct memio_buffer *mb, const char *buf, int n) 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int transferred = 0; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Handle part before wrap */ 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len = PR_MIN(n, memio_buffer_unused_contiguous(mb)); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (len > 0) { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Buffer not full */ 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(&mb->buf[mb->tail], buf, len); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail += len; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->tail == mb->bufsize) 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail = 0; 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n -= len; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf += len; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transferred += len; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Handle part after wrap */ 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len = PR_MIN(n, memio_buffer_unused_contiguous(mb)); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (len > 0) { 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Output buffer still not full, input buffer still not empty */ 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(&mb->buf[mb->tail], buf, len); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail += len; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->tail == mb->bufsize) 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail = 0; 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transferred += len; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transferred; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Read n bytes from the buffer. Returns number of bytes read. */ 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int memio_buffer_get(struct memio_buffer *mb, char *buf, int n) 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int transferred = 0; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Handle part before wrap */ 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len = PR_MIN(n, memio_buffer_used_contiguous(mb)); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (len) { 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(buf, &mb->buf[mb->head], len); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head += len; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->head == mb->bufsize) 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head = 0; 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott n -= len; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf += len; 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transferred += len; 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Handle part after wrap */ 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len = PR_MIN(n, memio_buffer_used_contiguous(mb)); 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (len) { 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(buf, &mb->buf[mb->head], len); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head += len; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->head == mb->bufsize) 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head = 0; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transferred += len; 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return transferred; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- private memio functions -----------------------*/ 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRStatus PR_CALLBACK memio_Close(PRFileDesc *fd) 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret = fd->secret; 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_buffer_destroy(&secret->readbuf); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_buffer_destroy(&secret->writebuf); 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(secret); 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd->dtor(fd); 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRStatus PR_CALLBACK memio_Shutdown(PRFileDesc *fd, PRIntn how) 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* TODO: pass shutdown status to app somehow */ 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* If there was a network error in the past taking bytes 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * out of the buffer, return it to the next call that 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * tries to read from an empty buffer. 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int PR_CALLBACK memio_Recv(PRFileDesc *fd, void *buf, PRInt32 len, 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRIntn flags, PRIntervalTime timeout) 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret; 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer *mb; 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags) { 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secret = fd->secret; 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb = &secret->readbuf; 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memio_buffer_get(mb, buf, len); 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == 0 && !secret->eof) { 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->last_err) 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(mb->last_err, 0); 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int PR_CALLBACK memio_Read(PRFileDesc *fd, void *buf, PRInt32 len) 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* pull bytes from buffer */ 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return memio_Recv(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT); 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int PR_CALLBACK memio_Send(PRFileDesc *fd, const void *buf, PRInt32 len, 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRIntn flags, PRIntervalTime timeout) 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret; 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer *mb; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secret = fd->secret; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb = &secret->writebuf; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->last_err) { 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(mb->last_err, 0); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memio_buffer_put(mb, buf, len); 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == 0) { 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int PR_CALLBACK memio_Write(PRFileDesc *fd, const void *buf, PRInt32 len) 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* append bytes to buffer */ 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return memio_Send(fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT); 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRStatus PR_CALLBACK memio_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* TODO: fail if memio_SetPeerName has not been called */ 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret = fd->secret; 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *addr = secret->peername; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRStatus memio_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Even in the original version for real tcp sockets, 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_SockOpt_Nonblocking is a special case that does not 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * translate to a getsockopt() call 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (PR_SockOpt_Nonblocking == data->option) { 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data->value.non_blocking = PR_TRUE; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_FAILURE; 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- private memio data -----------------------*/ 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Implement just the bare minimum number of methods needed to make ssl happy. 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Oddly, PR_Recv calls ssl_Recv calls ssl_SocketIsBlocking calls 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_GetSocketOption, so we have to provide an implementation of 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * PR_GetSocketOption that just says "I'm nonblocking". 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic struct PRIOMethods memio_layer_methods = { 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_DESC_LAYERED, 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Close, 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Read, 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Write, 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Shutdown, 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Recv, 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_Send, 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_GetPeerName, 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_GetSocketOption, 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRDescIdentity memio_identity = PR_INVALID_IO_LAYER; 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic PRStatus memio_InitializeLayerName(void) 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_identity = PR_GetUniqueIdentity("memio"); 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return PR_SUCCESS; 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- public memio functions -----------------------*/ 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPRFileDesc *memio_CreateIOLayer(int bufsize) 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRFileDesc *fd; 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static PRCallOnceType once; 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_CallOnce(&once, memio_InitializeLayerName); 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd = PR_CreateIOLayerStub(memio_identity, &memio_layer_methods); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secret = malloc(sizeof(struct PRFilePrivate)); 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(secret, 0, sizeof(*secret)); 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_buffer_new(&secret->readbuf, bufsize); 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_buffer_new(&secret->writebuf, bufsize); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd->secret = secret; 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return fd; 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid memio_SetPeerName(PRFileDesc *fd, const PRNetAddr *peername) 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct PRFilePrivate *secret = memiofd->secret; 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott secret->peername = *peername; 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottmemio_Private *memio_GetSecret(PRFileDesc *fd) 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRFileDesc *memiofd = PR_GetIdentitiesLayer(fd, memio_identity); 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PRFilePrivate *secret = memiofd->secret; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (memio_Private *)secret; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint memio_GetReadParams(memio_Private *secret, char **buf) 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *buf = &mb->buf[mb->tail]; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return memio_buffer_unused_contiguous(mb); 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid memio_PutReadResult(memio_Private *secret, int bytes_read) 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer* mb = &((PRFilePrivate *)secret)->readbuf; 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_read > 0) { 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail += bytes_read; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mb->tail == mb->bufsize) 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->tail = 0; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_read == 0) { 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Record EOF condition and report to caller when buffer runs dry */ 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ((PRFilePrivate *)secret)->eof = PR_TRUE; 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else /* if (bytes_read < 0) */ { 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->last_err = bytes_read; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid memio_GetWriteParams(memio_Private *secret, 4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char **buf1, unsigned int *len1, 4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char **buf2, unsigned int *len2) 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer* mb = &((PRFilePrivate *)secret)->writebuf; 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *buf1 = &mb->buf[mb->head]; 4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *len1 = memio_buffer_used_contiguous(mb); 4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *buf2 = mb->buf; 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *len2 = memio_buffer_wrapped_bytes(mb); 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid memio_PutWriteResult(memio_Private *secret, int bytes_written) 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer* mb = &((PRFilePrivate *)secret)->writebuf; 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_ASSERT(mb->bufsize); 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_written > 0) { 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->head += bytes_written; 4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (mb->head >= mb->bufsize) 4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mb->head -= mb->bufsize; 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_written < 0) { 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mb->last_err = bytes_written; 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*--------------- private memio_buffer self-test -----------------*/ 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* Even a trivial unit test is very helpful when doing circular buffers. */ 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*#define TRIVIAL_SELF_TEST*/ 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef TRIVIAL_SELF_TEST 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h> 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define TEST_BUFLEN 7 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define CHECKEQ(a, b) { \ 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((a) != (b)) { \ 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("%d != %d, Test failed line %d\n", a, b, __LINE__); \ 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exit(1); \ 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } \ 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint main() 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct memio_buffer mb; 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[100]; 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i; 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memio_buffer_new(&mb, TEST_BUFLEN); 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1); 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 0); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_put(&mb, "howdy", 5), 5); 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1-5); 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 5); 4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECKEQ(memio_buffer_wrapped_bytes(&mb), 0); 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_put(&mb, "!", 1), 1); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), 0); 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 6); 4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECKEQ(memio_buffer_wrapped_bytes(&mb), 0); 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_get(&mb, buf, 6), 6); 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memcmp(buf, "howdy!", 6), 0); 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), 1); 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 0); 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_put(&mb, "01234", 5), 5); 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 1); 4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECKEQ(memio_buffer_wrapped_bytes(&mb), 4); 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), TEST_BUFLEN-1-5); 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_put(&mb, "5", 1), 1); 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_unused_contiguous(&mb), 0); 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECKEQ(memio_buffer_used_contiguous(&mb), 1); 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* TODO: add more cases */ 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott printf("Test passed\n"); 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exit(0); 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 501