"request" added.
[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
191
192 static int bio_make_pair(BIO *bio1, BIO *bio2)
193         {
194         struct bio_bio_st *b1, *b2;
195
196         assert(bio1 != NULL);
197         assert(bio2 != NULL);
198
199         b1 = bio1->ptr;
200         b2 = bio2->ptr;
201         
202         if (b1->peer != NULL || b2->peer != NULL)
203                 {
204                 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
205                 return 0;
206                 }
207         
208         if (b1->buf == NULL)
209                 {
210                 b1->buf = Malloc(b1->size);
211                 if (b1->buf == NULL)
212                         {
213                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
214                         return 0;
215                         }
216                 b1->len = 0;
217                 b1->offset = 0;
218                 }
219         
220         if (b2->buf == NULL)
221                 {
222                 b2->buf = Malloc(b2->size);
223                 if (b2->buf == NULL)
224                         {
225                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
226                         return 0;
227                         }
228                 b2->len = 0;
229                 b2->offset = 0;
230                 }
231         
232         b1->peer = bio2;
233         b1->closed = 0;
234         b1->request = 0;
235         b2->peer = bio1;
236         b2->closed = 0;
237         b2->request = 0;
238
239         bio1->init = 1;
240         bio2->init = 1;
241
242         return 1;
243         }
244
245 static void bio_destroy_pair(BIO *bio)
246         {
247         struct bio_bio_st *b = bio->ptr;
248
249         if (b != NULL)
250                 {
251                 BIO *peer_bio = b->peer;
252
253                 if (peer_bio != NULL)
254                         {
255                         struct bio_bio_st *peer_b = peer_bio->ptr;
256
257                         assert(peer_b != NULL);
258                         assert(peer_b->peer == bio);
259
260                         peer_b->peer = NULL;
261                         peer_bio->init = 0;
262                         assert(peer_b->buf != NULL);
263                         peer_b->len = 0;
264                         peer_b->offset = 0;
265                         
266                         b->peer = NULL;
267                         bio->init = 0;
268                         assert(b->buf != NULL);
269                         b->len = 0;
270                         b->offset = 0;
271                         }
272                 }
273         }