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