bss_rtcp.c revision 59191
1204076Spjd/* crypto/bio/bss_rtcp.c */
2204076Spjd/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3204076Spjd * All rights reserved.
4204076Spjd *
5204076Spjd * This package is an SSL implementation written
6204076Spjd * by Eric Young (eay@cryptsoft.com).
7204076Spjd * The implementation was written so as to conform with Netscapes SSL.
8204076Spjd *
9204076Spjd * This library is free for commercial and non-commercial use as long as
10204076Spjd * the following conditions are aheared to.  The following conditions
11204076Spjd * apply to all code found in this distribution, be it the RC4, RSA,
12204076Spjd * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13204076Spjd * included with this distribution is covered by the same copyright terms
14204076Spjd * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15204076Spjd *
16204076Spjd * Copyright remains Eric Young's, and as such any Copyright notices in
17204076Spjd * the code are not to be removed.
18204076Spjd * If this package is used in a product, Eric Young should be given attribution
19204076Spjd * as the author of the parts of the library used.
20204076Spjd * This can be in the form of a textual message at program startup or
21204076Spjd * in documentation (online or textual) provided with the package.
22204076Spjd *
23204076Spjd * Redistribution and use in source and binary forms, with or without
24204076Spjd * modification, are permitted provided that the following conditions
25204076Spjd * are met:
26204076Spjd * 1. Redistributions of source code must retain the copyright
27204076Spjd *    notice, this list of conditions and the following disclaimer.
28204076Spjd * 2. Redistributions in binary form must reproduce the above copyright
29204076Spjd *    notice, this list of conditions and the following disclaimer in the
30204076Spjd *    documentation and/or other materials provided with the distribution.
31204076Spjd * 3. All advertising materials mentioning features or use of this software
32204076Spjd *    must display the following acknowledgement:
33204076Spjd *    "This product includes cryptographic software written by
34204076Spjd *     Eric Young (eay@cryptsoft.com)"
35204076Spjd *    The word 'cryptographic' can be left out if the rouines from the library
36204076Spjd *    being used are not cryptographic related :-).
37204076Spjd * 4. If you include any Windows specific code (or a derivative thereof) from
38204076Spjd *    the apps directory (application code) you must include an acknowledgement:
39204076Spjd *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40204076Spjd *
41204076Spjd * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43229509Strociny * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44204076Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45229509Strociny * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46229509Strociny * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47229509Strociny * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48229509Strociny * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49229509Strociny * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50229509Strociny * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51229509Strociny * SUCH DAMAGE.
52204076Spjd *
53204076Spjd * The licence and distribution terms for any publically available version or
54204076Spjd * derivative of this code cannot be changed.  i.e. this code cannot simply be
55219864Spjd * copied and put under another distribution licence
56204076Spjd * [including the GNU Public Licence.]
57204076Spjd */
58204076Spjd
59204076Spjd/* Written by David L. Jones <jonesd@kcgl1.eng.ohio-state.edu>
60204076Spjd * Date:   22-JUL-1996
61204076Spjd * Revised: 25-SEP-1997		Update for 0.8.1, BIO_CTRL_SET -> BIO_C_SET_FD
62204076Spjd */
63204076Spjd/* VMS */
64204076Spjd#include <stdio.h>
65204076Spjd#include <stdlib.h>
66204076Spjd#include <string.h>
67204076Spjd#include <errno.h>
68204076Spjd#include "cryptlib.h"
69204076Spjd#include <openssl/bio.h>
70204076Spjd
71204076Spjd#include <iodef.h>		/* VMS IO$_ definitions */
72204076Spjd#include <starlet.h>
73204076Spjd
74204076Spjdtypedef unsigned short io_channel;
75204076Spjd/*************************************************************************/
76204076Spjdstruct io_status { short status, count; long flags; };
77204076Spjd
78204076Spjdstruct rpc_msg {		/* Should have member alignment inhibited */
79204076Spjd   char channel;		/* 'A'-app data. 'R'-remote client 'G'-global */
80204076Spjd   char function;		/* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */
81204076Spjd   unsigned short int length;	/* Amount of data returned or max to return */
82204076Spjd   char data[4092];		/* variable data */
83204076Spjd};
84204076Spjd#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092)
85204076Spjd
86204076Spjdstruct rpc_ctx {
87204076Spjd    int filled, pos;
88204076Spjd    struct rpc_msg msg;
89204076Spjd};
90204076Spjd
91204076Spjdstatic int rtcp_write(BIO *h,char *buf,int num);
92204076Spjdstatic int rtcp_read(BIO *h,char *buf,int size);
93204076Spjdstatic int rtcp_puts(BIO *h,char *str);
94204076Spjdstatic int rtcp_gets(BIO *h,char *str,int size);
95204076Spjdstatic long rtcp_ctrl(BIO *h,int cmd,long arg1,char *arg2);
96204076Spjdstatic int rtcp_new(BIO *h);
97204076Spjdstatic int rtcp_free(BIO *data);
98204076Spjd
99204076Spjdstatic BIO_METHOD rtcp_method=
100204076Spjd	{
101204076Spjd	BIO_TYPE_FD,
102229509Strociny	"RTCP",
103204076Spjd	rtcp_write,
104229509Strociny	rtcp_read,
105204076Spjd	rtcp_puts,
106204076Spjd	rtcp_gets,
107204076Spjd	rtcp_ctrl,
108204076Spjd	rtcp_new,
109204076Spjd	rtcp_free,
110204076Spjd	NULL,
111204076Spjd	};
112204076Spjd
113229509StrocinyBIO_METHOD *BIO_s_rtcp(void)
114204076Spjd	{
115229509Strociny	return(&rtcp_method);
116204076Spjd	}
117204076Spjd/*****************************************************************************/
118204076Spjd/* Decnet I/O routines.
119204076Spjd */
120204076Spjd
121204076Spjd#ifdef __DECC
122204076Spjd#pragma message save
123204076Spjd#pragma message disable DOLLARID
124204076Spjd#endif
125204076Spjd
126204076Spjdstatic int get ( io_channel chan, char *buffer, int maxlen, int *length )
127204076Spjd{
128204076Spjd    int status;
129204076Spjd    struct io_status iosb;
130204076Spjd    status = sys$qiow ( 0, chan, IO$_READVBLK, &iosb, 0, 0,
131229509Strociny	buffer, maxlen, 0, 0, 0, 0 );
132204076Spjd    if ( (status&1) == 1 ) status = iosb.status;
133204076Spjd    if ( (status&1) == 1 ) *length = iosb.count;
134204076Spjd    return status;
135204076Spjd}
136204076Spjd
137204076Spjdstatic int put ( io_channel chan, char *buffer, int length )
138204076Spjd{
139204076Spjd    int status;
140204076Spjd    struct io_status iosb;
141204076Spjd    status = sys$qiow ( 0, chan, IO$_WRITEVBLK, &iosb, 0, 0,
142204076Spjd	buffer, length, 0, 0, 0, 0 );
143204076Spjd    if ( (status&1) == 1 ) status = iosb.status;
144204076Spjd    return status;
145204076Spjd}
146204076Spjd
147204076Spjd#ifdef __DECC
148229509Strociny#pragma message restore
149229509Strociny#endif
150229509Strociny
151229509Strociny/***************************************************************************/
152229509Strociny
153229509Strocinystatic int rtcp_new(BIO *bi)
154229509Strociny{
155204076Spjd    struct rpc_ctx *ctx;
156204076Spjd	bi->init=1;
157204076Spjd	bi->num=0;
158204076Spjd	bi->flags = 0;
159204076Spjd	bi->ptr=Malloc(sizeof(struct rpc_ctx));
160204076Spjd	ctx = (struct rpc_ctx *) bi->ptr;
161204076Spjd	ctx->filled = 0;
162204076Spjd	ctx->pos = 0;
163204076Spjd	return(1);
164204076Spjd}
165204076Spjd
166204076Spjdstatic int rtcp_free(BIO *a)
167204076Spjd{
168204076Spjd	if (a == NULL) return(0);
169204076Spjd	if ( a->ptr ) Free ( a->ptr );
170204076Spjd	a->ptr = NULL;
171204076Spjd	return(1);
172204076Spjd}
173204076Spjd
174204076Spjdstatic int rtcp_read(BIO *b, char *out, int outl)
175204076Spjd{
176204076Spjd    int status, length;
177204076Spjd    struct rpc_ctx *ctx;
178204076Spjd    /*
179204076Spjd     * read data, return existing.
180204076Spjd     */
181204076Spjd    ctx = (struct rpc_ctx *) b->ptr;
182204076Spjd    if ( ctx->pos < ctx->filled ) {
183204076Spjd	length = ctx->filled - ctx->pos;
184204076Spjd	if ( length > outl ) length = outl;
185204076Spjd	memmove ( out, &ctx->msg.data[ctx->pos], length );
186204076Spjd	ctx->pos += length;
187204076Spjd	return length;
188204076Spjd    }
189204076Spjd    /*
190204076Spjd     * Requst more data from R channel.
191204076Spjd     */
192204076Spjd    ctx->msg.channel = 'R';
193204076Spjd    ctx->msg.function = 'G';
194204076Spjd    ctx->msg.length = sizeof(ctx->msg.data);
195204076Spjd    status = put ( b->num, (char *) &ctx->msg, RPC_HDR_SIZE );
196204076Spjd    if ( (status&1) == 0 ) {
197204076Spjd	return -1;
198204076Spjd    }
199204076Spjd    /*
200204076Spjd     * Read.
201204076Spjd     */
202204076Spjd    ctx->pos = ctx->filled = 0;
203204076Spjd    status = get ( b->num, (char *) &ctx->msg, sizeof(ctx->msg), &length );
204204076Spjd    if ( (status&1) == 0 ) length = -1;
205204076Spjd    if ( ctx->msg.channel != 'R' || ctx->msg.function != 'C' ) {
206204076Spjd	length = -1;
207204076Spjd    }
208204076Spjd    ctx->filled = length - RPC_HDR_SIZE;
209204076Spjd
210204076Spjd    if ( ctx->pos < ctx->filled ) {
211204076Spjd	length = ctx->filled - ctx->pos;
212204076Spjd	if ( length > outl ) length = outl;
213204076Spjd	memmove ( out, ctx->msg.data, length );
214223654Strociny	ctx->pos += length;
215204076Spjd	return length;
216204076Spjd    }
217204076Spjd
218204076Spjd    return length;
219204076Spjd}
220204076Spjd
221204076Spjdstatic int rtcp_write(BIO *b, char *in, int inl)
222231017Strociny{
223204076Spjd    int status, i, segment, length;
224204076Spjd    struct rpc_ctx *ctx;
225204076Spjd    /*
226223654Strociny     * Output data, send in chunks no larger that sizeof(ctx->msg.data).
227204076Spjd     */
228204076Spjd    ctx = (struct rpc_ctx *) b->ptr;
229204076Spjd    for ( i = 0; i < inl; i += segment ) {
230204076Spjd	segment = inl - i;
231204076Spjd	if ( segment > sizeof(ctx->msg.data) ) segment = sizeof(ctx->msg.data);
232204076Spjd	ctx->msg.channel = 'R';
233204076Spjd	ctx->msg.function = 'P';
234229509Strociny	ctx->msg.length = segment;
235204076Spjd	memmove ( ctx->msg.data, &in[i], segment );
236204076Spjd	status = put ( b->num, (char *) &ctx->msg, segment + RPC_HDR_SIZE );
237229509Strociny	if ((status&1) == 0 ) { i = -1; break; }
238204076Spjd
239204076Spjd	status = get ( b->num, (char *) &ctx->msg, sizeof(ctx->msg), &length );
240204076Spjd	if ( ((status&1) == 0) || (length < RPC_HDR_SIZE) ) { i = -1; break; }
241204076Spjd	if ( (ctx->msg.channel != 'R') || (ctx->msg.function != 'C') ) {
242204076Spjd	   printf("unexpected response when confirming put %c %c\n",
243204076Spjd		ctx->msg.channel, ctx->msg.function );
244204076Spjd
245204076Spjd	}
246204076Spjd    }
247223654Strociny    return(i);
248223654Strociny}
249204076Spjd
250204076Spjdstatic long rtcp_ctrl(BIO *b, int cmd, long num, char *ptr)
251204076Spjd	{
252204076Spjd	long ret=1;
253204076Spjd
254204076Spjd	switch (cmd)
255204076Spjd		{
256204076Spjd	case BIO_CTRL_RESET:
257204076Spjd	case BIO_CTRL_EOF:
258204076Spjd		ret = 1;
259204076Spjd		break;
260204076Spjd	case BIO_C_SET_FD:
261204076Spjd		b->num = num;
262204076Spjd		ret = 1;
263204076Spjd	 	break;
264204076Spjd	case BIO_CTRL_SET_CLOSE:
265204076Spjd	case BIO_CTRL_FLUSH:
266204076Spjd	case BIO_CTRL_DUP:
267204076Spjd		ret=1;
268204076Spjd		break;
269204076Spjd	case BIO_CTRL_GET_CLOSE:
270229509Strociny	case BIO_CTRL_INFO:
271204076Spjd	case BIO_CTRL_GET:
272204076Spjd	case BIO_CTRL_PENDING:
273204076Spjd	case BIO_CTRL_WPENDING:
274204076Spjd	default:
275204076Spjd		ret=0;
276204076Spjd		break;
277204076Spjd		}
278204076Spjd	return(ret);
279204076Spjd	}
280229509Strociny
281204076Spjdstatic int rtcp_gets(BIO *bp, char *buf, int size)
282204076Spjd	{
283204076Spjd	return(0);
284204076Spjd	}
285204076Spjd
286204076Spjdstatic int rtcp_puts(BIO *bp, char *str)
287204076Spjd{
288204076Spjd    int length;
289204076Spjd    if (str == NULL) return(0);
290204076Spjd    length = strlen ( str );
291204076Spjd    if ( length == 0 ) return (0);
292204076Spjd    return rtcp_write ( bp,str, length );
293204076Spjd}
294204076Spjd
295204076Spjd