Survive pedanticism.
[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                         * peer != NULL iff init != 0 in the BIO. */
51         
52         /* This is for what we write (i.e. reading uses peer's struct): */
53         int closed;     /* valid iff peer != NULL */
54         size_t len;     /* valid iff buf != NULL; 0 if peer == NULL */
55         size_t offset;  /* valid iff buf != NULL; 0 if len == 0 */
56         size_t size;
57         char *buf;      /* "size" elements (if != NULL) */
58
59         size_t request; /* valid iff peer != NULL; 0 if len != 0;
60                          * otherwise set by peer to number of bytes
61                          * it (unsuccesfully) tried to read. */
62 };
63
64 static int bio_new(BIO *bio)
65         {
66         struct bio_bio_st *b;
67         
68         b = Malloc(sizeof *b);
69         if (b == NULL)
70                 return 0;
71
72         b->peer = NULL;
73         b->size = 17*1024; /* enough for one TLS record (just a default) */
74         b->buf = NULL;
75
76         return 1;
77         }
78
79
80 static int bio_free(BIO *bio)
81         {
82         struct bio_bio_st *b;
83
84         if (bio == NULL)
85                 return 0;
86         b = bio->ptr;
87
88         assert(b != NULL);
89
90         if (b->peer)
91                 bio_destroy_pair(bio);
92         
93         if (b->buf != NULL)
94                 {
95                 Free(b->buf);
96                 }
97
98         Free(b);
99
100         return 1;
101         }
102
103
104
105 static int bio_read(BIO *bio, char *buf, int size)
106         {
107         /* XXX */
108         return -1;
109         }
110
111 static int bio_write(BIO *bio, char *buf, int num)
112         {
113         /* XXX */
114         return -1;
115         }
116         
117 static long bio_ctrl(BIO *bio, int cmd, long num, char *ptr)
118         {
119         long ret;
120         struct bio_bio_st *b = bio->ptr;
121         
122         assert(b != NULL);
123
124         switch (cmd)
125                 {
126                 /* XXX Additional commands: */
127                 /* - Set buffer size */
128                 /* - make pair */
129                 /* - destroy pair */
130                 /* - get number of bytes that the next write will accept */
131                 /* - get number of bytes requested by peer */
132                 /* - send "close" */
133
134         case BIO_CTRL_RESET:
135                 if (b->buf != NULL)
136                         {
137                         b->len = 0;
138                         b->offset = 0;
139                         }
140                 ret = 0;
141                 break;          
142
143         case BIO_CTRL_GET_CLOSE:
144                 ret = bio->shutdown;
145                 break;
146
147         case BIO_CTRL_SET_CLOSE:
148                 bio->shutdown = (int) num;
149                 ret = 1;
150                 break;
151
152         case BIO_CTRL_PENDING:
153                 if (b->peer != NULL)
154                         {
155                         struct bio_bio_st *peer_b =b->peer->ptr;
156                         
157                         ret = (long) peer_b->len;
158                         }
159                 else
160                         ret = 0;
161                 break;
162
163         case BIO_CTRL_WPENDING:
164                 if (b->buf != NULL)
165                         ret = (long) b->len;
166                 else
167                         ret = 0;
168                 break;
169
170         case BIO_CTRL_DUP:
171                 /* XXX */
172                 ret = 1;
173                 break;
174
175         case BIO_CTRL_FLUSH:
176                 ret = 1;
177                 break;
178
179         default:
180                 ret = 0;
181                 }
182         return ret;
183         }
184
185 static int bio_puts(BIO *bio, char *str)
186         {
187         return bio_write(bio, str, strlen(str));
188         }
189
190 /* Until bio_make_pair is used, make a dummy function use it for -pedantic */
191 void dummy() { bio_make_pair(NULL,NULL); }
192
193 static int bio_make_pair(BIO *bio1, BIO *bio2)
194         {
195         struct bio_bio_st *b1, *b2;
196
197         assert(bio1 != NULL);
198         assert(bio2 != NULL);
199
200         b1 = bio1->ptr;
201         b2 = bio2->ptr;
202         
203         if (b1->peer != NULL || b2->peer != NULL)
204                 {
205                 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
206                 return 0;
207                 }
208         
209         if (b1->buf == NULL)
210                 {
211                 b1->buf = Malloc(b1->size);
212                 if (b1->buf == NULL)
213                         {
214                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
215                         return 0;
216                         }
217                 b1->len = 0;
218                 b1->offset = 0;
219                 }
220         
221         if (b2->buf == NULL)
222                 {
223                 b2->buf = Malloc(b2->size);
224                 if (b2->buf == NULL)
225                         {
226                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
227                         return 0;
228                         }
229                 b2->len = 0;
230                 b2->offset = 0;
231                 }
232         
233         b1->peer = bio2;
234         b1->closed = 0;
235         b1->request = 0;
236         b2->peer = bio1;
237         b2->closed = 0;
238         b2->request = 0;
239
240         bio1->init = 1;
241         bio2->init = 1;
242
243         return 1;
244         }
245
246 static void bio_destroy_pair(BIO *bio)
247         {
248         struct bio_bio_st *b = bio->ptr;
249
250         if (b != NULL)
251                 {
252                 BIO *peer_bio = b->peer;
253
254                 if (peer_bio != NULL)
255                         {
256                         struct bio_bio_st *peer_b = peer_bio->ptr;
257
258                         assert(peer_b != NULL);
259                         assert(peer_b->peer == bio);
260
261                         peer_b->peer = NULL;
262                         peer_bio->init = 0;
263                         assert(peer_b->buf != NULL);
264                         peer_b->len = 0;
265                         peer_b->offset = 0;
266                         
267                         b->peer = NULL;
268                         bio->init = 0;
269                         assert(b->buf != NULL);
270                         b->len = 0;
271                         b->offset = 0;
272                         }
273                 }
274         }