bss_rtcp.c revision 306195
1/* crypto/bio/bss_rtcp.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59/*- 60 * Written by David L. Jones <jonesd@kcgl1.eng.ohio-state.edu> 61 * Date: 22-JUL-1996 62 * Revised: 25-SEP-1997 Update for 0.8.1, BIO_CTRL_SET -> BIO_C_SET_FD 63 */ 64/* VMS */ 65#include <stdio.h> 66#include <stdlib.h> 67#include <string.h> 68#include <errno.h> 69#include "cryptlib.h" 70#include <openssl/bio.h> 71 72#include <iodef.h> /* VMS IO$_ definitions */ 73#include <starlet.h> 74 75typedef unsigned short io_channel; 76/*************************************************************************/ 77struct io_status { 78 short status, count; 79 long flags; 80}; 81 82/* Should have member alignment inhibited */ 83struct rpc_msg { 84 /* 'A'-app data. 'R'-remote client 'G'-global */ 85 char channel; 86 /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 87 char function; 88 /* Amount of data returned or max to return */ 89 unsigned short int length; 90 /* variable data */ 91 char data[4092]; 92}; 93#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 94 95struct rpc_ctx { 96 int filled, pos; 97 struct rpc_msg msg; 98}; 99 100static int rtcp_write(BIO *h, const char *buf, int num); 101static int rtcp_read(BIO *h, char *buf, int size); 102static int rtcp_puts(BIO *h, const char *str); 103static int rtcp_gets(BIO *h, char *str, int size); 104static long rtcp_ctrl(BIO *h, int cmd, long arg1, void *arg2); 105static int rtcp_new(BIO *h); 106static int rtcp_free(BIO *data); 107 108static BIO_METHOD rtcp_method = { 109 BIO_TYPE_FD, 110 "RTCP", 111 rtcp_write, 112 rtcp_read, 113 rtcp_puts, 114 rtcp_gets, 115 rtcp_ctrl, 116 rtcp_new, 117 rtcp_free, 118 NULL, 119}; 120 121BIO_METHOD *BIO_s_rtcp(void) 122{ 123 return (&rtcp_method); 124} 125 126/*****************************************************************************/ 127/* 128 * Decnet I/O routines. 129 */ 130 131#ifdef __DECC 132# pragma message save 133# pragma message disable DOLLARID 134#endif 135 136static int get(io_channel chan, char *buffer, int maxlen, int *length) 137{ 138 int status; 139 struct io_status iosb; 140 status = sys$qiow(0, chan, IO$_READVBLK, &iosb, 0, 0, 141 buffer, maxlen, 0, 0, 0, 0); 142 if ((status & 1) == 1) 143 status = iosb.status; 144 if ((status & 1) == 1) 145 *length = iosb.count; 146 return status; 147} 148 149static int put(io_channel chan, char *buffer, int length) 150{ 151 int status; 152 struct io_status iosb; 153 status = sys$qiow(0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 154 buffer, length, 0, 0, 0, 0); 155 if ((status & 1) == 1) 156 status = iosb.status; 157 return status; 158} 159 160#ifdef __DECC 161# pragma message restore 162#endif 163 164/***************************************************************************/ 165 166static int rtcp_new(BIO *bi) 167{ 168 struct rpc_ctx *ctx; 169 bi->init = 1; 170 bi->num = 0; 171 bi->flags = 0; 172 bi->ptr = OPENSSL_malloc(sizeof(struct rpc_ctx)); 173 if (bi->ptr == NULL) 174 return (0); 175 ctx = (struct rpc_ctx *)bi->ptr; 176 ctx->filled = 0; 177 ctx->pos = 0; 178 return (1); 179} 180 181static int rtcp_free(BIO *a) 182{ 183 if (a == NULL) 184 return (0); 185 if (a->ptr) 186 OPENSSL_free(a->ptr); 187 a->ptr = NULL; 188 return (1); 189} 190 191static int rtcp_read(BIO *b, char *out, int outl) 192{ 193 int status, length; 194 struct rpc_ctx *ctx; 195 /* 196 * read data, return existing. 197 */ 198 ctx = (struct rpc_ctx *)b->ptr; 199 if (ctx->pos < ctx->filled) { 200 length = ctx->filled - ctx->pos; 201 if (length > outl) 202 length = outl; 203 memmove(out, &ctx->msg.data[ctx->pos], length); 204 ctx->pos += length; 205 return length; 206 } 207 /* 208 * Requst more data from R channel. 209 */ 210 ctx->msg.channel = 'R'; 211 ctx->msg.function = 'G'; 212 ctx->msg.length = sizeof(ctx->msg.data); 213 status = put(b->num, (char *)&ctx->msg, RPC_HDR_SIZE); 214 if ((status & 1) == 0) { 215 return -1; 216 } 217 /* 218 * Read. 219 */ 220 ctx->pos = ctx->filled = 0; 221 status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length); 222 if ((status & 1) == 0) 223 length = -1; 224 if (ctx->msg.channel != 'R' || ctx->msg.function != 'C') { 225 length = -1; 226 } 227 ctx->filled = length - RPC_HDR_SIZE; 228 229 if (ctx->pos < ctx->filled) { 230 length = ctx->filled - ctx->pos; 231 if (length > outl) 232 length = outl; 233 memmove(out, ctx->msg.data, length); 234 ctx->pos += length; 235 return length; 236 } 237 238 return length; 239} 240 241static int rtcp_write(BIO *b, const char *in, int inl) 242{ 243 int status, i, segment, length; 244 struct rpc_ctx *ctx; 245 /* 246 * Output data, send in chunks no larger that sizeof(ctx->msg.data). 247 */ 248 ctx = (struct rpc_ctx *)b->ptr; 249 for (i = 0; i < inl; i += segment) { 250 segment = inl - i; 251 if (segment > sizeof(ctx->msg.data)) 252 segment = sizeof(ctx->msg.data); 253 ctx->msg.channel = 'R'; 254 ctx->msg.function = 'P'; 255 ctx->msg.length = segment; 256 memmove(ctx->msg.data, &in[i], segment); 257 status = put(b->num, (char *)&ctx->msg, segment + RPC_HDR_SIZE); 258 if ((status & 1) == 0) { 259 i = -1; 260 break; 261 } 262 263 status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length); 264 if (((status & 1) == 0) || (length < RPC_HDR_SIZE)) { 265 i = -1; 266 break; 267 } 268 if ((ctx->msg.channel != 'R') || (ctx->msg.function != 'C')) { 269 printf("unexpected response when confirming put %c %c\n", 270 ctx->msg.channel, ctx->msg.function); 271 272 } 273 } 274 return (i); 275} 276 277static long rtcp_ctrl(BIO *b, int cmd, long num, void *ptr) 278{ 279 long ret = 1; 280 281 switch (cmd) { 282 case BIO_CTRL_RESET: 283 case BIO_CTRL_EOF: 284 ret = 1; 285 break; 286 case BIO_C_SET_FD: 287 b->num = num; 288 ret = 1; 289 break; 290 case BIO_CTRL_SET_CLOSE: 291 case BIO_CTRL_FLUSH: 292 case BIO_CTRL_DUP: 293 ret = 1; 294 break; 295 case BIO_CTRL_GET_CLOSE: 296 case BIO_CTRL_INFO: 297 case BIO_CTRL_GET: 298 case BIO_CTRL_PENDING: 299 case BIO_CTRL_WPENDING: 300 default: 301 ret = 0; 302 break; 303 } 304 return (ret); 305} 306 307static int rtcp_gets(BIO *bp, char *buf, int size) 308{ 309 return (0); 310} 311 312static int rtcp_puts(BIO *bp, const char *str) 313{ 314 int length; 315 if (str == NULL) 316 return (0); 317 length = strlen(str); 318 if (length == 0) 319 return (0); 320 return rtcp_write(bp, str, length); 321} 322