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

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

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

Line 
1/***************************************************************************
2 *            ioNetworkExchange.cc
3 *
4 *  Thu Sep 20 2005
5 *  Copyright  2005  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#include <arpa/inet.h>
33#include <sys/socket.h>
34#include <poll.h>
35#include <errno.h>
36#include <string.h>
37#include <unistd.h>
38
39#include <libdodo/ioNetworkExchange.h>
40#include <libdodo/ioNetworkConnection.h>
41#include <libdodo/ioChannel.h>
42#include <libdodo/ioNetworkExchangeEx.h>
43#include <libdodo/types.h>
44#include <libdodo/pcSyncStack.h>
45
46using namespace dodo::io::network;
47
48exchange::__init__::__init__() : socket(-1)
49{
50}
51
52//-------------------------------------------------------------------
53
54exchange::__init__::__init__(__init__ &init) : socket(init.socket)
55{
56    init.socket = -1;
57}
58
59//-------------------------------------------------------------------
60
61exchange::__init__::~__init__()
62{
63}
64
65//-------------------------------------------------------------------
66
67exchange::exchange(exchange &fse) : stream::channel(fse.protection)
68{
69}
70
71//-------------------------------------------------------------------
72
73exchange::exchange(short protection) : stream::channel(protection)
74{
75#ifndef IO_WO_XEXEC
76    collectedData.setExecObject(xexec::OBJECT_IONETWORKEXCHANGE);
77#endif
78}
79
80//-------------------------------------------------------------------
81
82exchange::exchange(__init__ &a_init,
83                   short    protection) : stream::channel(protection)
84{
85#ifndef IO_WO_XEXEC
86    collectedData.setExecObject(xexec::OBJECT_IONETWORKEXCHANGE);
87#endif
88
89    init(a_init.socket, a_init.blocked, a_init.blockInherited);
90
91    a_init.socket = -1;
92}
93
94//-------------------------------------------------------------------
95
96exchange::~exchange()
97{
98    if (socket != -1) {
99        ::shutdown(socket, SHUT_RDWR);
100
101        ::close(socket);
102    }
103}
104
105//-------------------------------------------------------------------
106
107void
108exchange::close()
109{
110    pc::sync::stack pg(keeper);
111
112#ifndef IO_WO_XEXEC
113    performPreExec(OPERATION_CLOSE);
114#endif
115
116    if (socket != -1) {
117        _close(socket);
118
119        socket = -1;
120    }
121
122#ifndef IO_WO_XEXEC
123    performPostExec(OPERATION_CLOSE);
124#endif
125}
126
127//-------------------------------------------------------------------
128
129void
130exchange::init(int  dataocket,
131               bool a_blocked,
132               bool blockInherited)
133{
134    pc::sync::stack pg(keeper);
135
136    if (socket != -1) {
137        _close(socket);
138
139        socket = -1;
140    }
141
142    blocked = a_blocked;
143    socket = dataocket;
144
145    setInBufferSize(inSocketBufferSize);
146    setOutBufferSize(outSocketBufferSize);
147
148    setInTimeout(inSocketTimeout);
149    setOutTimeout(outSocketTimeout);
150
151    setLingerOption(lingerOpts, lingerSeconds);
152
153    if (!blocked) {
154        if (blockInherited)
155            block(false);
156        else
157            block(true);
158    } else
159        block(true);
160}
161
162//-------------------------------------------------------------------
163
164bool
165exchange::isAlive()
166{
167    pc::sync::stack pg(keeper);
168
169    if (socket == -1)
170        return false;
171
172    pollfd fd;
173    fd.fd = socket;
174    fd.events = POLLOUT;
175
176    if (poll(&fd, 1, -1) > 0)
177        if (isSetFlag(fd.revents, POLLOUT))
178            return true;
179
180    _close(socket);
181
182    socket = -1;
183
184    return false;
185}
186
187//-------------------------------------------------------------------
188
189unsigned long
190exchange::_write(const char * const data) const
191{
192    if (socket == -1)
193        dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__WRITE, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
194
195    unsigned long iter = bs / outSocketBufferSize;
196    unsigned long rest = bs % outSocketBufferSize;
197
198    const char *s = data;
199
200    long batch, n;
201
202    for (unsigned long i = 0; i < iter; ++i) {
203        batch = outSocketBufferSize;
204        while (batch > 0) {
205            while (true) {
206                if ((n = ::send(socket, s, batch, 0)) == -1) {
207                    if (errno == EINTR)
208                        continue;
209
210                    if (errno == EAGAIN)
211                        return s - data;
212
213                    dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__WRITE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
214                }
215
216                break;
217            }
218
219            batch -= n;
220            s += n;
221        }
222    }
223
224    if (rest > 0) {
225        batch = rest;
226        while (batch > 0) {
227            while (true) {
228                if ((n = ::send(socket, s, batch, 0)) == -1) {
229                    if (errno == EINTR)
230                        continue;
231
232                    if (errno == EAGAIN)
233                        return s - data;
234
235                    dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__WRITE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
236                }
237
238                break;
239            }
240
241            batch -= n;
242            s += n;
243        }
244    }
245
246    return bs;
247}
248
249//-------------------------------------------------------------------
250
251unsigned long
252exchange::_read(char * const data) const
253{
254    if (socket == -1)
255        dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__READ, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
256
257    unsigned long iter = bs / inSocketBufferSize;
258    unsigned long rest = bs % inSocketBufferSize;
259
260    char *s = data;
261    char *_s = s;
262
263    long batch, n;
264
265    for (unsigned long i = 0; i < iter; ++i) {
266        batch = inSocketBufferSize;
267        while (batch > 0) {
268            while (true) {
269                if ((n = ::recv(socket, s, batch, 0)) == -1) {
270                    if (errno == EINTR)
271                        continue;
272
273                    if (errno == EAGAIN)
274                        return s - _s;
275
276                    dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__READ, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
277                }
278
279                break;
280            }
281
282            if (n == 0)
283                return s - _s;
284
285            batch -= n;
286            s += n;
287        }
288    }
289
290    if (rest > 0) {
291        batch = rest;
292        while (batch > 0) {
293            while (true) {
294                if ((n = ::recv(socket, s, batch, 0)) == -1) {
295                    if (errno == EINTR)
296                        continue;
297
298                    if (errno == EAGAIN)
299                        return s - _s;
300
301                    dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__READ, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
302                }
303
304                break;
305            }
306
307            if (n == 0)
308                return s - _s;
309
310            batch -= n;
311            s += n;
312        }
313    }
314
315    return bs;
316}
317
318//-------------------------------------------------------------------
319
320unsigned long
321exchange::_writeString(const char * const s) const
322{
323    unsigned long _bs = bs;
324    unsigned long written;
325
326    dodo_try {
327        bs = strnlen(s, bs) + 1;
328
329        written = _write(s);
330
331        bs = _bs;
332    } dodo_catch (exception::basic *e UNUSED) {
333        bs = _bs;
334
335        dodo_rethrow;
336    }
337
338    return written;
339}
340
341//-------------------------------------------------------------------
342
343unsigned long
344exchange::_readString(char * const s) const
345{
346    if (socket == -1)
347        dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__READSTRING, exception::ERRNO_LIBDODO, EXCHANGEEX_NOCONNECTION, IONETWORKEXCHANGEEX_NOCONNECTION_STR, __LINE__, __FILE__);
348
349    long n = 0;
350
351    while (true) {
352        if ((n = ::recv(socket, s, bs, 0)) == -1) {
353            if (errno == EINTR)
354                continue;
355
356            if (errno == EAGAIN)
357                return 0;
358
359            dodo_throw exception::basic(exception::MODULE_IONETWORKEXCHANGE, EXCHANGEEX__READSTRING, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
360        }
361
362        break;
363    }
364
365    return n;
366}
367
368//-------------------------------------------------------------------
369
370void
371exchange::flush() const
372{
373}
374
375//-------------------------------------------------------------------
376
377int
378exchange::inDescriptor() const
379{
380    pc::sync::stack pg(keeper);
381
382    return socket;
383}
384
385//-------------------------------------------------------------------
386
387int
388exchange::outDescriptor() const
389{
390    pc::sync::stack pg(keeper);
391
392    return socket;
393}
394
395//-------------------------------------------------------------------
396
Note: See TracBrowser for help on using the repository browser.