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

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

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

Line 
1/***************************************************************************
2 *            ioNetworkClient.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 <sys/types.h>
33#include <sys/stat.h>
34#include <netinet/in.h>
35#include <arpa/inet.h>
36#include <netdb.h>
37#include <sys/un.h>
38#include <sys/socket.h>
39#include <net/if.h>
40#include <sys/ioctl.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <unistd.h>
44
45#include <libdodo/ioNetworkClient.h>
46#include <libdodo/ioNetworkClientEx.h>
47#include <libdodo/types.h>
48#include <libdodo/ioNetworkConnection.h>
49#include <libdodo/ioNetworkExchange.h>
50#include <libdodo/xexec.h>
51
52using namespace dodo::io::network;
53
54#ifndef IO_WO_XEXEC
55client::__collected_data__::__collected_data__(xexec *executor,
56                                               short execObject) : xexec::__collected_data__(executor, execObject)
57{
58}
59#endif
60
61//-------------------------------------------------------------------
62
63#ifndef IO_WO_XEXEC
64client::client(client &c) : xexec(c),
65                            collectedData(this, xexec::OBJECT_IONETWORKCLIENT)
66#else
67client::client(client &)
68#endif
69{
70}
71
72//-------------------------------------------------------------------
73
74client::client(short a_family,
75               short a_type) : blockInherited(false),
76                               family(a_family),
77                               type(a_type)
78#ifndef IO_WO_XEXEC
79                               ,
80                               collectedData(this, xexec::OBJECT_IONETWORKCLIENT)
81#endif
82{
83}
84
85//-------------------------------------------------------------------
86
87client::~client()
88{
89    if (socket != -1) {
90        ::shutdown(socket, SHUT_RDWR);
91
92        ::close(socket);
93    }
94}
95
96//-------------------------------------------------------------------
97
98void
99client::restoreOptions()
100{
101    setInBufferSize(inSocketBufferSize);
102    setOutBufferSize(outSocketBufferSize);
103
104    setInTimeout(inSocketTimeout);
105    setOutTimeout(outSocketTimeout);
106
107    setLingerOption(lingerOpts, lingerSeconds);
108
109    block(blocked);
110}
111
112//-------------------------------------------------------------------
113
114void
115client::makeSocket()
116{
117    if (socket != -1) {
118        ::shutdown(socket, SHUT_RDWR);
119
120        if (::close(socket) == -1)
121            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_MAKESOCKET, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
122
123        socket = -1;
124    }
125
126    int real_domain(PF_INET), real_type(SOCK_STREAM);
127
128    switch (family) {
129        case PROTOCOL_FAMILY_IPV4:
130
131            real_domain = PF_INET;
132
133            break;
134
135        case PROTOCOL_FAMILY_IPV6:
136
137            real_domain = PF_INET6;
138
139            break;
140
141        case PROTOCOL_FAMILY_UNIX_SOCKET:
142
143            real_domain = PF_UNIX;
144
145            break;
146
147        default:
148
149            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_MAKESOCKET, exception::ERRNO_LIBDODO, CLIENTEX_WRONGPARAMETER, IONETWORKCLIENTEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
150    }
151
152    switch (type) {
153        case TRANSFER_STREAM:
154
155            real_type = SOCK_STREAM;
156
157            break;
158
159        case TRANSFER_DATAGRAM:
160
161            real_type = SOCK_DGRAM;
162
163            break;
164
165        default:
166
167            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_MAKESOCKET, exception::ERRNO_LIBDODO, CLIENTEX_WRONGPARAMETER, IONETWORKCLIENTEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
168    }
169
170    socket = ::socket(real_domain, real_type, 0);
171    if (socket == -1)
172        dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_MAKESOCKET, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
173
174    restoreOptions();
175}
176
177//-------------------------------------------------------------------
178
179void
180client::connect(const dodo::string &host,
181                int              port,
182                exchange         &exchange)
183{
184#ifndef IO_WO_XEXEC
185    performPreExec(OPERATION_CONNECT);
186#endif
187
188    makeSocket();
189
190    if (family == PROTOCOL_FAMILY_IPV6) {
191        struct sockaddr_in6 sa;
192        sa.sin6_family = AF_INET6;
193        sa.sin6_port = htons(port);
194        sa.sin6_flowinfo = 0;
195        sa.sin6_scope_id = 0;
196        inet_pton(AF_INET6, host.data(), &sa.sin6_addr);
197
198        if (::connect(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
199            if (::close(socket) == -1)
200                dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
201
202            socket = -1;
203
204            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
205        }
206    } else {
207        struct sockaddr_in sa;
208        sa.sin_family = AF_INET;
209        sa.sin_port = htons(port);
210        inet_aton(host.data(), &sa.sin_addr);
211
212        if (::connect(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
213            if (::close(socket) == -1)
214                dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
215
216            socket = -1;
217
218            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
219        }
220    }
221
222    exchange.init(socket, blocked, blockInherited);
223
224    socket = -1;
225
226#ifndef IO_WO_XEXEC
227    performPostExec(OPERATION_CONNECT);
228#endif
229}
230
231//-------------------------------------------------------------------
232
233void
234client::connectFrom(const dodo::string &local,
235                    const dodo::string &host,
236                    int              port,
237                    exchange         &exchange)
238{
239#ifndef IO_WO_XEXEC
240    performPreExec(OPERATION_CONNECTFROM);
241#endif
242
243    makeSocket();
244
245    int sockFlag(1);
246    if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &sockFlag, sizeof(int)) == -1)
247        dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
248
249    addFlag(socketOpts, 1 << OPTION_REUSE_ADDRESS);
250
251    if (family == PROTOCOL_FAMILY_IPV6) {
252        struct sockaddr_in6 sa;
253        sa.sin6_family = AF_INET6;
254        sa.sin6_flowinfo = 0;
255        sa.sin6_scope_id = 0;
256        sa.sin6_port = htons(0);
257        inet_pton(AF_INET6, local.data(), &sa.sin6_addr);
258
259        if (::bind(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1)
260            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
261
262        sa.sin6_port = htons(port);
263        inet_pton(AF_INET6, host.data(), &sa.sin6_addr);
264
265        if (::connect(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
266            if (::close(socket) == -1)
267                dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
268
269            socket = -1;
270
271            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
272        }
273    } else {
274        struct sockaddr_in sa;
275        sa.sin_family = AF_INET;
276        sa.sin_port = htons(0);
277        inet_aton(local.data(), &sa.sin_addr);
278
279        if (::bind(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1)
280            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
281
282        sa.sin_port = htons(port);
283        inet_aton(host.data(), &sa.sin_addr);
284
285        if (::connect(socket, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
286            if (::close(socket) == -1)
287                dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
288
289            socket = -1;
290
291            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECTFROM, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
292        }
293    }
294
295    exchange.init(socket, blocked, blockInherited);
296
297    socket = -1;
298
299#ifndef IO_WO_XEXEC
300    performPostExec(OPERATION_CONNECTFROM);
301#endif
302}
303
304//-------------------------------------------------------------------
305
306void
307client::connect(const dodo::string &path,
308                exchange         &exchange)
309{
310#ifndef IO_WO_XEXEC
311    performPreExec(OPERATION_CONNECT);
312#endif
313
314    makeSocket();
315
316    struct sockaddr_un sa;
317
318    unsigned long size = path.size();
319
320    if (size >= 108)
321        dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_LIBDODO, CLIENTEX_LONGPATH, IONETWORKCLIENTEX_LONGPATH_STR, __LINE__, __FILE__);
322
323    strncpy(sa.sun_path, path.data(), size);
324    sa.sun_family = AF_UNIX;
325
326    if (::connect(socket, (struct sockaddr *)&sa, path.size() + sizeof(sa.sun_family)) == -1) {
327        if (::close(socket) == -1)
328            dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
329
330        socket = -1;
331
332        dodo_throw exception::basic(exception::MODULE_IONETWORKCLIENT, CLIENTEX_CONNECT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
333    }
334
335    exchange.init(socket, blocked, blockInherited);
336
337    socket = -1;
338
339#ifndef IO_WO_XEXEC
340    performPostExec(OPERATION_CONNECT);
341#endif
342}
343
344//-------------------------------------------------------------------
345
Note: See TracBrowser for help on using the repository browser.