Introduce "BIO pairs", which (when finished) will relay data
[openssl.git] / crypto / bio / bss_bio.c
1 /* crypto/bio/bss_bio.c  -*- Mode: C; c-file-style: "eay" -*- */
2
3 /*  *** Not yet finished (or even tested). *** */
4
5 /* Special method for a BIO where the other endpoint is also a BIO
6  * of this kind, handled by the same thread.
7  * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces
8  * for which no specific BIO method is available. */
9
10 #include <assert.h>
11 #include <stdlib.h>
12
13 #include <openssl/bio.h>
14 #include <openssl/err.h>
15 #include <openssl/crypto.h>
16
17 static int bio_new(BIO *bio);
18 static int bio_free(BIO *bio);
19 static int bio_read(BIO *bio, char *buf, int size);
20 static int bio_write(BIO *bio, char *buf, int num);
21 static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr);
22 static int bio_puts(BIO *bio, char *str);
23
24 static int bio_make_pair(BIO *bio1, BIO *bio2);
25 static void bio_destroy_pair(BIO *bio);
26
27 static BIO_METHOD methods_biop =
28 {
29         BIO_TYPE_BIO,
30         "BIO pair",
31         bio_write,
32         bio_read,
33         bio_puts,
34         NULL /* no bio_gets */,
35         bio_ctrl,
36         bio_new,
37         bio_free
38 };
39
40 BIO_METHOD *BIO_s_bio(void)
41         {
42         return &methods_biop;
43         }
44
45 struct bio_bio_st
46 {
47         BIO *peer;     /* NULL if buf == NULL.
48                                         * If peer != NULL, then peer->ptr is also a bio_bio_st,
49                                         * and its "peer" member points back to us. */
50         
51         /* This is for what we write (i.e. reading uses peer's struct): */
52         int closed;    /* valid iff peer != NULL */
53         size_t len;    /* valid iff buf != NULL; 0 if peer == NULL */
54         size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
55         size_t size;
56         char *buf;     /* "size" elements (if != NULL) */
57 };
58
59 static int bio_new(BIO *bio)
60         {
61         struct bio_bio_st *b;
62         
63         b = Malloc(sizeof *b);
64         if (b == NULL)
65                 return 0;
66
67         b->peer = NULL;
68         b->size = 17*1024; /* enough for one TLS record (just a default) */
69         b->buf = NULL;
70
71         return 1;
72         }
73
74
75 static int bio_free(BIO *bio)
76         {
77         struct bio_bio_st *b;
78
79         if (bio == NULL)
80                 return 0;
81         b = bio->ptr;
82
83         assert(b != NULL);
84
85         if (b->peer)
86                 bio_destroy_pair(bio);
87         
88         if (b->buf != NULL)
89                 {
90                 Free(b->buf);
91                 }
92
93         Free(b);
94
95         return 1;
96         }
97
98
99
100 static int bio_read(BIO *bio, char *buf, int size)
101         {
102         /* XXX */
103         return -1;
104         }
105
106 static int bio_write(BIO *bio, char *buf, int num)
107         {
108         /* XXX */
109         return -1;
110         }
111         
112 static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr)
113         {
114         long ret;
115         struct bio_bio_st *b = bio->ptr;
116         
117         assert(b != NULL);
118
119         switch (cmd)
120                 {
121                 /* XXX Additional commands: */
122                 /* - Set buffer size */
123                 /* - make pair */
124                 /* - destroy pair */
125                 /* - get number of bytes that the next write will accept */
126                 /* - send "close" */
127
128         case BIO_CTRL_RESET:
129                 if (b->buf != NULL)
130                         {
131                         b->len = 0;
132                         b->offset = 0;
133                         }
134                 ret = 0;
135                 break;          
136
137         case BIO_CTRL_GET_CLOSE:
138                 ret = bio->shutdown;
139                 break;
140
141         case BIO_CTRL_SET_CLOSE:
142                 bio->shutdown = (int) num;
143                 ret = 1;
144                 break;
145
146         case BIO_CTRL_PENDING:
147                 if (b->peer != NULL)
148                         {
149                         struct bio_bio_st *peer_b =b->peer->ptr;
150                         
151                         ret = (long) peer_b->len;
152                         }
153                 else
154                         ret = 0;
155                 break;
156
157         case BIO_CTRL_WPENDING:
158                 if (b->buf != NULL)
159                         ret = (long) b->len;
160                 else
161                         ret = 0;
162                 break;
163
164         case BIO_CTRL_DUP:
165                 /* XXX */
166
167         case BIO_CTRL_FLUSH:
168                 ret = 1;
169                 break;
170
171         default:
172                 ret = 0;
173                 }
174         return ret;
175         }
176
177 static int bio_puts(BIO *bio, char *str)
178         {
179         return bio_write(bio, str, strlen(str));
180         }
181
182
183
184 static int bio_make_pair(BIO *bio1, BIO *bio2)
185         {
186         struct bio_bio_st *b1, *b2;
187
188         assert(bio1 != NULL);
189         assert(bio2 != NULL);
190
191         b1 = bio1->ptr;
192         b2 = bio2->ptr;
193         
194         if (b1->peer != NULL || b2->peer != NULL)
195                 {
196                 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
197                 return 0;
198                 }
199         
200         if (b1->buf != NULL)
201                 {
202                 b1->buf = Malloc(b1->size);
203                 if (b1->buf == NULL)
204                         {
205                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
206                         return 0;
207                         }
208                 b1->len = 0;
209                 b1->offset = 0;
210                 }
211         
212         if (b2->buf != NULL)
213                 {
214                 b2->buf = Malloc(b2->size);
215                 if (b2->buf == NULL)
216                         {
217                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
218                         return 0;
219                         }
220                 b2->len = 0;
221                 b2->offset = 0;
222                 }
223         
224         b1->peer = bio2;
225         b2->peer = bio1;
226
227         return 1;
228         }
229
230 static void bio_destroy_pair(BIO *bio)
231         {
232         struct bio_bio_st *b = bio->ptr;
233
234         if (b != NULL)
235                 {
236                 BIO *peer_bio = b->peer;
237
238                 if (peer_bio != NULL)
239                         {
240                         struct bio_bio_st *peer_b = peer_bio->ptr;
241
242                         assert(peer_b != NULL);
243                         assert(peer_b->peer == bio);
244
245                         peer_b->peer = NULL;
246                         peer_bio->init = 0;
247                         assert(peer_b->buf != NULL);
248                         peer_b->len = 0;
249                         peer_b->offset = 0;
250                         
251                         b->peer = NULL;
252                         bio->init = 0;
253                         assert(b->buf != NULL);
254                         b->len = 0;
255                         b->offset = 0;
256                         }
257                 }
258         }