blob: 65ffae0da1b2720d3cf5538d9979667723073c26 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18#include "local.h"
19
20SSLBuffer::SSLBuffer(secure::client_t scontext) :
21TCPBuffer()
22{
23 context *ctx = (context *)scontext;
24 ssl = NULL;
25 bio = NULL;
26 server = false;
27
28 if(ctx && ctx->ctx && ctx->err() == secure::OK)
29 ssl = SSL_new(ctx->ctx);
30}
31
32SSLBuffer::SSLBuffer(const TCPServer *tcp, secure::server_t scontext, size_t size) :
33TCPBuffer(tcp, size)
34{
35 context *ctx = (context *)scontext;
36 ssl = NULL;
37 bio = NULL;
38 server = true;
39
40 if(ctx && ctx->ctx && ctx->err() == secure::OK)
41 ssl = SSL_new(ctx->ctx);
42
43 if(!is_open() || !ssl)
44 return;
45
46 SSL_set_fd((SSL *)ssl, getsocket());
47
48 if(SSL_accept((SSL *)ssl) > 0)
49 bio = SSL_get_wbio((SSL *)ssl);
50}
51
52SSLBuffer::~SSLBuffer()
53{
54 release();
55}
56
57void SSLBuffer::open(const char *host, const char *service, size_t size)
58{
59 if(server) {
60 ioerr = EBADF;
61 return;
62 }
63
64 close();
65 TCPBuffer::open(host, service, size);
66
67 if(!is_open() || !ssl)
68 return;
69
70 SSL_set_fd((SSL *)ssl, getsocket());
71
72 if(SSL_connect((SSL *)ssl) > 0)
73 bio = SSL_get_wbio((SSL *)ssl);
74}
75
76void SSLBuffer::close(void)
77{
78 if(server) {
79 ioerr = EBADF;
80 return;
81 }
82
83 if(bio) {
84 SSL_shutdown((SSL *)ssl);
85 bio = NULL;
86 }
87
88 TCPBuffer::close();
89}
90
91void SSLBuffer::release(void)
92{
93 server = false;
94 close();
95 if(ssl) {
96 SSL_free((SSL *)ssl);
97 ssl = NULL;
98 }
99}
100
101size_t SSLBuffer::_push(const char *address, size_t size)
102{
103 if(!bio)
104 return TCPBuffer::_push(address, size);
105
106 int result = SSL_write((SSL *)ssl, address, size);
107 if(result < 0) {
108 result = 0;
109 ioerr = EIO;
110 }
111 return (ssize_t)result;
112}
113
114bool SSLBuffer::_pending(void)
115{
116 if(so == INVALID_SOCKET)
117 return false;
118
119 if(input_pending())
120 return true;
121
122 if(ssl && SSL_pending((SSL *)ssl))
123 return true;
124
125 if(iowait && iowait != Timer::inf)
126 return Socket::wait(so, iowait);
127
128 return Socket::wait(so, 0);
129}
130
131size_t SSLBuffer::_pull(char *address, size_t size)
132{
133 if(!bio)
134 return TCPBuffer::_pull(address, size);
135
136 if(SSL_pending((SSL *)ssl) == 0 && iowait && iowait != Timer::inf && !Socket::wait(so, iowait))
137 return 0;
138
139 int result = SSL_read((SSL *)ssl, address, size);
140 if(result < 0) {
141 result = 0;
142 ioerr = EIO;
143 }
144 return (size_t) result;
145}
146
147bool SSLBuffer::_flush(void)
148{
149 int result;
150
151 if(TCPBuffer::_flush()) {
152 if(bio) {
153 result = BIO_flush((BIO *)bio);
154 if(result < 1) {
155 ioerr = EIO;
156 return false;
157 }
158 }
159 return true;
160 }
161
162 return false;
163}
164