OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
buffer.c
Go to the documentation of this file.
1 #include "tunala.h"
2 
3 #ifndef NO_BUFFER
4 
5 void buffer_init(buffer_t *buf)
6 {
7  buf->used = 0;
8  buf->total_in = buf->total_out = 0;
9 }
10 
12 {
13  /* Our data is static - nothing needs "release", just reset it */
14  buf->used = 0;
15 }
16 
17 /* Code these simple ones in compact form */
18 unsigned int buffer_used(buffer_t *buf) {
19  return buf->used; }
20 unsigned int buffer_unused(buffer_t *buf) {
21  return (MAX_DATA_SIZE - buf->used); }
22 int buffer_full(buffer_t *buf) {
23  return (buf->used == MAX_DATA_SIZE ? 1 : 0); }
25  return (buf->used < MAX_DATA_SIZE ? 1 : 0); }
27  return (buf->used == 0 ? 1 : 0); }
29  return (buf->used > 0 ? 1 : 0); }
30 unsigned long buffer_total_in(buffer_t *buf) {
31  return buf->total_in; }
32 unsigned long buffer_total_out(buffer_t *buf) {
33  return buf->total_out; }
34 
35 /* These 3 static (internal) functions don't adjust the "total" variables as
36  * it's not sure when they're called how it should be interpreted. Only the
37  * higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
38  * values. */
39 #if 0 /* To avoid "unused" warnings */
40 static unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
41  unsigned int size)
42 {
43  unsigned int added = MAX_DATA_SIZE - buf->used;
44  if(added > size)
45  added = size;
46  if(added == 0)
47  return 0;
48  memcpy(buf->data + buf->used, ptr, added);
49  buf->used += added;
50  buf->total_in += added;
51  return added;
52 }
53 
54 static unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap)
55 {
56  unsigned int moved, tomove = from->used;
57  if((int)tomove > cap)
58  tomove = cap;
59  if(tomove == 0)
60  return 0;
61  moved = buffer_adddata(to, from->data, tomove);
62  if(moved == 0)
63  return 0;
64  buffer_takedata(from, NULL, moved);
65  return moved;
66 }
67 #endif
68 
69 static unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
70  unsigned int size)
71 {
72  unsigned int taken = buf->used;
73  if(taken > size)
74  taken = size;
75  if(taken == 0)
76  return 0;
77  if(ptr)
78  memcpy(ptr, buf->data, taken);
79  buf->used -= taken;
80  /* Do we have to scroll? */
81  if(buf->used > 0)
82  memmove(buf->data, buf->data + taken, buf->used);
83  return taken;
84 }
85 
86 #ifndef NO_IP
87 
88 int buffer_from_fd(buffer_t *buf, int fd)
89 {
90  int toread = buffer_unused(buf);
91  if(toread == 0)
92  /* Shouldn't be called in this case! */
93  abort();
94  toread = read(fd, buf->data + buf->used, toread);
95  if(toread > 0) {
96  buf->used += toread;
97  buf->total_in += toread;
98  }
99  return toread;
100 }
101 
102 int buffer_to_fd(buffer_t *buf, int fd)
103 {
104  int towrite = buffer_used(buf);
105  if(towrite == 0)
106  /* Shouldn't be called in this case! */
107  abort();
108  towrite = write(fd, buf->data, towrite);
109  if(towrite > 0) {
110  buffer_takedata(buf, NULL, towrite);
111  buf->total_out += towrite;
112  }
113  return towrite;
114 }
115 
116 #endif /* !defined(NO_IP) */
117 
118 #ifndef NO_OPENSSL
119 
120 static void int_ssl_check(SSL *s, int ret)
121 {
122  int e = SSL_get_error(s, ret);
123  switch(e) {
124  /* These seem to be harmless and already "dealt with" by our
125  * non-blocking environment. NB: "ZERO_RETURN" is the clean
126  * "error" indicating a successfully closed SSL tunnel. We let
127  * this happen because our IO loop should not appear to have
128  * broken on this condition - and outside the IO loop, the
129  * "shutdown" state is checked. */
130  case SSL_ERROR_NONE:
131  case SSL_ERROR_WANT_READ:
135  return;
136  /* These seem to be indications of a genuine error that should
137  * result in the SSL tunnel being regarded as "dead". */
138  case SSL_ERROR_SYSCALL:
139  case SSL_ERROR_SSL:
140  SSL_set_app_data(s, (char *)1);
141  return;
142  default:
143  break;
144  }
145  /* For any other errors that (a) exist, and (b) crop up - we need to
146  * interpret what to do with them - so "politely inform" the caller that
147  * the code needs updating here. */
148  abort();
149 }
150 
151 void buffer_from_SSL(buffer_t *buf, SSL *ssl)
152 {
153  int ret;
154  if(!ssl || buffer_full(buf))
155  return;
156  ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
157  if(ret > 0) {
158  buf->used += ret;
159  buf->total_in += ret;
160  }
161  if(ret < 0)
162  int_ssl_check(ssl, ret);
163 }
164 
165 void buffer_to_SSL(buffer_t *buf, SSL *ssl)
166 {
167  int ret;
168  if(!ssl || buffer_empty(buf))
169  return;
170  ret = SSL_write(ssl, buf->data, buf->used);
171  if(ret > 0) {
172  buffer_takedata(buf, NULL, ret);
173  buf->total_out += ret;
174  }
175  if(ret < 0)
176  int_ssl_check(ssl, ret);
177 }
178 
179 void buffer_from_BIO(buffer_t *buf, BIO *bio)
180 {
181  int ret;
182  if(!bio || buffer_full(buf))
183  return;
184  ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
185  if(ret > 0) {
186  buf->used += ret;
187  buf->total_in += ret;
188  }
189 }
190 
191 void buffer_to_BIO(buffer_t *buf, BIO *bio)
192 {
193  int ret;
194  if(!bio || buffer_empty(buf))
195  return;
196  ret = BIO_write(bio, buf->data, buf->used);
197  if(ret > 0) {
198  buffer_takedata(buf, NULL, ret);
199  buf->total_out += ret;
200  }
201 }
202 
203 #endif /* !defined(NO_OPENSSL) */
204 
205 #endif /* !defined(NO_BUFFER) */