also support signing
[xonotic/d0_blind_id.git] / d0_iobuf.c
1 /*
2  * FILE:        d0_iobuf.c
3  * AUTHOR:      Rudolf Polzer - divVerent@xonotic.org
4  * 
5  * Copyright (c) 2010, Rudolf Polzer
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the copyright holder nor the names of contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  * 
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Format:commit %H$
33  * $Id$
34  */
35
36 #include "d0_iobuf.h"
37
38 #include <string.h>
39
40 struct d0_iobuf_s
41 {
42         const unsigned char *inbuf;
43         unsigned char *outbuf;
44         size_t inpos, outpos, inbuflen, outbuflen;
45         D0_BOOL ok;
46 };
47
48 d0_iobuf_t *d0_iobuf_open_read(const void *buf, size_t len)
49 {
50         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
51         b->inbuf = (const unsigned char *) buf;
52         b->outbuf = NULL;
53         b->inpos = b->outpos = 0;
54         b->inbuflen = len;
55         b->outbuflen = 0;
56         b->ok = 1;
57         return b;
58 }
59
60 d0_iobuf_t *d0_iobuf_open_write(void *buf, size_t len)
61 {
62         d0_iobuf_t *b = d0_malloc(sizeof(d0_iobuf_t));
63         b->inbuf = (const unsigned char *) buf;
64         b->outbuf = (unsigned char *) buf;
65         b->inpos = b->outpos = 0;
66         b->inbuflen = len;
67         b->outbuflen = len;
68         b->ok = 1;
69         return b;
70 }
71
72 D0_BOOL d0_iobuf_close(d0_iobuf_t *buf, size_t *len)
73 {
74         D0_BOOL r = buf->ok;
75         if(len)
76                 *len = buf->outpos;
77         d0_free(buf);
78         return r;
79 }
80
81 size_t d0_iobuf_write_raw(d0_iobuf_t *buf, const void *s, size_t n)
82 {
83         size_t nreal = n;
84         if(nreal > buf->outbuflen - buf->outpos)
85         {
86                 buf->ok = 0;
87                 nreal = buf->outbuflen - buf->outpos;
88         }
89         memcpy(buf->outbuf + buf->outpos, s, nreal);
90         buf->outpos += nreal;
91         return nreal;
92 }
93
94 size_t d0_iobuf_read_raw(d0_iobuf_t *buf, void *s, size_t n)
95 {
96         size_t nreal = n;
97         if(nreal > buf->inbuflen - buf->inpos)
98         {
99                 buf->ok = 0;
100                 nreal = buf->inbuflen - buf->inpos;
101         }
102         memcpy(s, buf->inbuf + buf->inpos, nreal);
103         buf->inpos += nreal;
104         return nreal;
105 }
106
107 D0_BOOL d0_iobuf_write_packet(d0_iobuf_t *buf, const void *s, size_t n)
108 {
109         unsigned char c;
110         size_t nn = n;
111         while(nn)
112         {
113                 c = nn & 0x7F;
114                 nn >>= 7;
115                 if(nn)
116                         c |= 0x80;
117                 if(d0_iobuf_write_raw(buf, &c, 1) != 1)
118                         return 0;
119         }
120         if(d0_iobuf_write_raw(buf, s, n) != n)
121                 return 0;
122         return 1;
123 }
124
125 D0_BOOL d0_iobuf_read_packet(d0_iobuf_t *buf, void *s, size_t *np)
126 {
127         unsigned char c;
128         size_t n = 0;
129         size_t nn = 1;
130         do
131         {
132                 if(d0_iobuf_read_raw(buf, &c, 1) != 1)
133                         return 0;
134                 n |= nn * (c & 0x7F);
135                 nn <<= 7;
136         }
137         while(c & 0x80);
138         if(n > *np)
139                 return 0;
140         if(d0_iobuf_read_raw(buf, s, n) != n)
141                 return 0;
142         *np = n;
143         return 1;
144 }
145
146 D0_BOOL d0_iobuf_conv_base64_in(d0_iobuf_t *buf)
147 {
148         // compand the in-buffer
149         return 0;
150 }
151
152 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
153 static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
154 {
155         unsigned char i0 = (bytes > 0) ? in[0] : 0;
156         unsigned char i1 = (bytes > 1) ? in[1] : 0;
157         unsigned char i2 = (bytes > 2) ? in[2] : 0;
158         unsigned char o0 = base64[i0 >> 2];
159         unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077];
160         unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077];
161         unsigned char o3 = base64[i2 & 077];
162         out[0] = (bytes > 0) ? o0 : '?';
163         out[1] = (bytes > 0) ? o1 : '?';
164         out[2] = (bytes > 1) ? o2 : '=';
165         out[3] = (bytes > 2) ? o3 : '=';
166 }
167
168 D0_BOOL d0_iobuf_conv_base64_out(d0_iobuf_t *buf)
169 {
170         size_t blocks, i;
171         // expand the out-buffer
172         blocks = ((buf->outpos + 2) / 3);
173         if(blocks*4 > buf->outbuflen)
174                 return 0;
175         for(i = blocks; i > 0; )
176         {
177                 --i;
178                 base64_3to4(buf->outbuf + 3*i, buf->outbuf + 4*i, buf->outpos - 3*i);
179         }
180         buf->outpos = blocks * 4;
181         return 1;
182 }