source: sources/src/ioNetworkSslExchange.cc @ 1464:3f6711617be1

Revision 1464:3f6711617be1, 10.0 KB checked in by niam, 22 months ago (diff)

{issue #58[resolved]} support for non-c++ exceptions

Line 
1/***************************************************************************
2 *            ioNetworkSslExchange.cc
3 *
4 *  Tue Jun 10 2008
5 *  Copyright  2008  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#ifdef OPENSSL_EXT
33#include <poll.h>
34#include <openssl/ssl.h>
35#include <openssl/err.h>
36
37#include "ioSsl.inline"
38
39#include <libdodo/ioNetworkSslExchange.h>
40#include <libdodo/ioChannel.h>
41#include <libdodo/ioStreamChannel.h>
42#include <libdodo/ioNetworkSslExchangeEx.h>
43#include <libdodo/ioNetworkExchange.h>
44#include <libdodo/ioSsl.h>
45#include <libdodo/types.h>
46#include <libdodo/xexec.h>
47#include <libdodo/pcSyncStack.h>
48
49using namespace dodo::io::network::ssl;
50
51exchange::__init__::__init__() : network::exchange::__init__(),
52                                 handle(new io::ssl::__connection__)
53{
54}
55
56//-------------------------------------------------------------------
57
58exchange::__init__::__init__(__init__ &init) : network::exchange::__init__(init),
59                                               handle(new io::ssl::__connection__)
60{
61    handle->handle = init.handle->handle;
62
63    init.handle = NULL;
64}
65
66//-------------------------------------------------------------------
67
68exchange::__init__::~__init__()
69{
70    delete handle;
71}
72
73//-------------------------------------------------------------------
74
75exchange::exchange(exchange &e) : stream::channel(e.protection),
76                                  network::exchange(e.protection)
77{
78}
79
80//-------------------------------------------------------------------
81
82exchange::exchange(short protection) : stream::channel(protection),
83                                       handle(new io::ssl::__connection__)
84{
85#ifndef IO_WO_XEXEC
86    collectedData.setExecObject(xexec::OBJECT_IONETWORKSSLEXCHANGE);
87#endif
88}
89
90//-------------------------------------------------------------------
91
92exchange::exchange(__init__ &a_init,
93                   short    protection) : stream::channel(protection),
94                                          handle(new io::ssl::__connection__)
95{
96#ifndef IO_WO_XEXEC
97    collectedData.setExecObject(xexec::OBJECT_IONETWORKSSLEXCHANGE);
98#endif
99
100    init(a_init.socket, a_init.handle, a_init.blocked, a_init.blockInherited);
101
102    a_init.socket = -1;
103    a_init.handle->handle = NULL;
104}
105
106//-------------------------------------------------------------------
107
108exchange::~exchange()
109{
110    if (handle->handle != NULL) {
111        if (SSL_shutdown(handle->handle) == 0)
112            SSL_shutdown(handle->handle);
113
114        SSL_free(handle->handle);
115    }
116
117    delete handle;
118}
119
120//-------------------------------------------------------------------
121
122void
123exchange::_close(int                     socket,
124                 io::ssl::__connection__ *handle)
125{
126    int err = SSL_shutdown(handle->handle);
127    if (err < 0) {
128        unsigned long nerr = ERR_get_error();
129        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__CLOSE, exception::ERRNO_OPENSSL, nerr, ERR_error_string(nerr, NULL), __LINE__, __FILE__);
130    }
131    if (err == 0) {
132        err = SSL_shutdown(handle->handle);
133        if (err < 0) {
134            unsigned long nerr = ERR_get_error();
135            dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__CLOSE, exception::ERRNO_OPENSSL, nerr, ERR_error_string(nerr, NULL), __LINE__, __FILE__);
136        }
137    }
138
139    connection::_close(socket);
140}
141
142//-------------------------------------------------------------------
143
144void
145exchange::close()
146{
147    pc::sync::stack pg(keeper);
148
149#ifndef IO_WO_XEXEC
150    performPreExec(OPERATION_CLOSE);
151#endif
152
153    if (socket != -1) {
154        _close(socket, handle);
155
156        socket = -1;
157        handle->handle = NULL;
158    }
159
160#ifndef IO_WO_XEXEC
161    performPostExec(OPERATION_CLOSE);
162#endif
163}
164
165//-------------------------------------------------------------------
166
167void
168exchange::init(int                     dataocket,
169               io::ssl::__connection__ *a_handle,
170               bool                    a_blocked,
171               bool                    blockInherited)
172{
173    pc::sync::stack pg(keeper);
174
175    if (socket != -1) {
176        _close(socket, handle);
177
178        socket = -1;
179        handle->handle = NULL;
180    }
181
182    blocked = a_blocked;
183    socket = dataocket;
184    handle->handle = a_handle->handle;
185
186    setInBufferSize(inSocketBufferSize);
187    setOutBufferSize(outSocketBufferSize);
188
189    setInTimeout(inSocketTimeout);
190    setOutTimeout(outSocketTimeout);
191
192    setLingerOption(lingerOpts, lingerSeconds);
193
194    if (!blocked) {
195        if (blockInherited)
196            block(false);
197        else
198            block(true);
199    } else {
200        block(true);
201    }
202}
203
204//-------------------------------------------------------------------
205
206bool
207exchange::isAlive()
208{
209    pc::sync::stack pg(keeper);
210
211    if (socket == -1)
212        return false;
213
214    pollfd fd;
215    fd.fd = socket;
216    fd.events = POLLOUT;
217
218    if (poll(&fd, 1, -1) > 0)
219        if (isSetFlag(fd.revents, POLLOUT))
220            return true;
221
222    _close(socket, handle);
223
224    socket = -1;
225    handle->handle = NULL;
226
227    return false;
228}
229
230//-------------------------------------------------------------------
231
232unsigned long
233exchange::_write(const char * const data) const
234{
235    if (socket == -1)
236        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__WRITE, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKSSLEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
237
238    unsigned long blockSize = bs;
239    unsigned long bufferSize;
240
241    const char *s = data;
242
243    long n;
244
245    while (blockSize > 0) {
246        bufferSize = blockSize%outSocketBufferSize;
247        while (bufferSize > 0) {
248            if ((n = SSL_write(handle->handle, s, bufferSize)) <= 0) {
249                switch (SSL_get_error(handle->handle, n)) {
250                    case SSL_ERROR_WANT_READ:
251                    case SSL_ERROR_WANT_WRITE:
252                    case SSL_ERROR_WANT_X509_LOOKUP:
253
254                        continue;
255
256                    case SSL_ERROR_SYSCALL:
257
258                        if (errno == 0)
259                            continue;
260
261
262                    default:
263                    {
264                        unsigned long nerr = ERR_get_error();
265                        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__WRITE, exception::ERRNO_OPENSSL, nerr, ERR_error_string(nerr, NULL), __LINE__, __FILE__);
266                    }
267                }
268            }
269
270            s += n;
271            bufferSize -= n;
272            blockSize -= n;
273        }
274    }
275
276    return bs;
277}
278
279//-------------------------------------------------------------------
280
281unsigned long
282exchange::_read(char * const data) const
283{
284    if (socket == -1)
285        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__READ, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKSSLEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
286
287    unsigned long blockSize = bs;
288    unsigned long bufferSize;
289
290    char *s = data;
291
292    long n;
293
294    while (blockSize > 0) {
295        bufferSize = blockSize%inSocketBufferSize;
296        while (bufferSize > 0) {
297            if ((n = SSL_read(handle->handle, s, bufferSize)) <= 0) {
298                switch (SSL_get_error(handle->handle, n)) {
299                    case SSL_ERROR_WANT_READ:
300                    case SSL_ERROR_WANT_WRITE:
301                    case SSL_ERROR_WANT_X509_LOOKUP:
302
303                        continue;
304
305                    case SSL_ERROR_SYSCALL:
306
307                        if (errno == 0)
308                            continue;
309
310
311                    default:
312                    {
313                        unsigned long nerr = ERR_get_error();
314                        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__READ, exception::ERRNO_OPENSSL, nerr, ERR_error_string(nerr, NULL), __LINE__, __FILE__);
315                    }
316                }
317            }
318
319            s += n;
320            bufferSize -= n;
321            blockSize -= n;
322        }
323    }
324
325    return bs;
326}
327
328//-------------------------------------------------------------------
329
330unsigned long
331exchange::_readString(char * const s) const
332{
333    if (socket == -1)
334        dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__READSTRING, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKSSLEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
335
336    long n;
337
338    while (true) {
339        if ((n = SSL_read(handle->handle, s, bs)) <= 0) {
340            switch (SSL_get_error(handle->handle, n)) {
341                case SSL_ERROR_WANT_READ:
342                case SSL_ERROR_WANT_WRITE:
343                case SSL_ERROR_WANT_X509_LOOKUP:
344                case SSL_ERROR_ZERO_RETURN:
345
346                    continue;
347
348                case SSL_ERROR_SYSCALL:
349
350                    if (errno == 0)
351                        continue;
352
353
354                default:
355                {
356                    unsigned long nerr = ERR_get_error();
357                    dodo_throw exception::basic(exception::MODULE_IONETWORKSSLEXCHANGE, EXCHANGEEX__READSTRING, exception::ERRNO_OPENSSL, nerr, ERR_error_string(nerr, NULL), __LINE__, __FILE__);
358                }
359            }
360        }
361
362        break;
363    }
364
365    return (unsigned long)n;
366}
367
368//-------------------------------------------------------------------
369#endif
370
Note: See TracBrowser for help on using the repository browser.