Commit 5fd336a0580916aeea6609784986aae40cde9662

Authored by Perry Werneck
1 parent 445c656a

DNS Resolve and connect now runs on background thread.

lib3270.cbp
... ... @@ -157,6 +157,9 @@
157 157 <Unit filename="src/lib3270/kybd.c">
158 158 <Option compilerVar="CC" />
159 159 </Unit>
  160 + <Unit filename="src/lib3270/linux/connect.c">
  161 + <Option compilerVar="CC" />
  162 + </Unit>
160 163 <Unit filename="src/lib3270/linux/event_dispatcher.c">
161 164 <Option compilerVar="CC" />
162 165 </Unit>
... ... @@ -245,6 +248,9 @@
245 248 <Unit filename="src/lib3270/version.c">
246 249 <Option compilerVar="CC" />
247 250 </Unit>
  251 + <Unit filename="src/lib3270/windows/connect.c">
  252 + <Option compilerVar="CC" />
  253 + </Unit>
248 254 <Unit filename="src/lib3270/windows/event_dispatcher.c">
249 255 <Option compilerVar="CC" />
250 256 </Unit>
... ...
src/lib3270/connect.c
... ... @@ -1,560 +0,0 @@
1   -/*
2   - * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
3   - * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
4   - * aplicativos mainframe. Registro no INPI sob o nome G3270.
5   - *
6   - * Copyright (C) <2008> <Banco do Brasil S.A.>
7   - *
8   - * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
9   - * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
10   - * Free Software Foundation.
11   - *
12   - * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
13   - * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
14   - * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
15   - * obter mais detalhes.
16   - *
17   - * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
18   - * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
19   - * St, Fifth Floor, Boston, MA 02110-1301 USA
20   - *
21   - * Este programa está nomeado como connect.c e possui - linhas de código.
22   - *
23   - * Contatos:
24   - *
25   - * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
26   - * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
27   - *
28   - */
29   -
30   -#include <config.h>
31   -
32   -#if defined(_WIN32)
33   -
34   - // Compiling for WinXP or later: Expose getaddrinfo()/freeaddrinfo().
35   - #undef _WIN32_WINNT
36   - #define _WIN32_WINNT 0x0501
37   -
38   - #include <winsock2.h>
39   - #include <windows.h>
40   - #include <ws2tcpip.h>
41   -
42   -#endif
43   -
44   -#include "private.h"
45   -#include <errno.h>
46   -
47   -#if defined(_WIN32)
48   - #include <ws2tcpip.h>
49   -#else
50   - #include <sys/types.h>
51   - #include <sys/socket.h>
52   - #include <sys/ioctl.h>
53   - #include <netinet/in.h>
54   - #include <netdb.h>
55   - #include <unistd.h>
56   - #include <fcntl.h>
57   -#endif
58   -
59   -#ifdef HAVE_ICONV
60   - #include <iconv.h>
61   -#endif // HAVE_ICONV
62   -
63   -#if defined(_WIN32) /*[*/
64   - #define SOCK_CLOSE(s) closesocket(s->sock); s->sock = -1;
65   -#else /*][*/
66   - #define SOCK_CLOSE(s) close(s->sock); s->sock = -1;
67   -#endif /*]*/
68   -
69   -#include <stdlib.h>
70   -#include "statusc.h"
71   -#include "hostc.h"
72   -#include "trace_dsc.h"
73   -#include "utilc.h"
74   -#include "telnetc.h"
75   -#include "screen.h"
76   -#include <lib3270/internals.h>
77   -
78   -/*---[ Implement ]-------------------------------------------------------------------------------*/
79   -
80   -
81   -//static void net_connected(H3270 *hSession)
82   -static void net_connected(H3270 *hSession, int fd unused, LIB3270_IO_FLAG flag unused, void *dunno unused)
83   -{
84   - int err;
85   - socklen_t len = sizeof(err);
86   -
87   - if(hSession->xio.write) {
88   - trace("%s write=%p",__FUNCTION__,hSession->xio.write);
89   - lib3270_remove_poll(hSession, hSession->xio.write);
90   - hSession->xio.write = NULL;
91   - }
92   -
93   - if(getsockopt(hSession->sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0)
94   - {
95   - lib3270_disconnect(hSession);
96   - lib3270_popup_dialog( hSession,
97   - LIB3270_NOTIFY_ERROR,
98   - _( "Network error" ),
99   - _( "Unable to get connection state." ),
100   -#ifdef _WIN32
101   - "%s", lib3270_win32_strerror(WSAGetLastError())
102   -#else
103   - _( "%s" ), strerror(errno)
104   -#endif // _WIN32
105   - );
106   - return;
107   - }
108   - else if(err)
109   - {
110   - char buffer[4096];
111   - snprintf(buffer,4095,_( "Can't connect to %s" ), hSession->host.current );
112   -
113   - lib3270_disconnect(hSession);
114   - lib3270_popup_dialog( hSession,
115   - LIB3270_NOTIFY_ERROR,
116   - _( "Connection failed" ),
117   - buffer,
118   -#ifdef _WIN32
119   - _( "%s"), lib3270_win32_strerror(err)
120   -#else
121   - _( "%s" ), strerror(err)
122   -#endif // _WIN32
123   - );
124   - trace("%s",__FUNCTION__);
125   - return;
126   - }
127   -
128   - hSession->xio.except = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0);
129   - hSession->xio.read = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_READ,net_input,0);
130   -
131   -#if defined(HAVE_LIBSSL)
132   - if(hSession->ssl.con && hSession->ssl.state == LIB3270_SSL_UNDEFINED)
133   - {
134   - if(ssl_negotiate(hSession))
135   - return;
136   - }
137   -#endif
138   -
139   - lib3270_setup_session(hSession);
140   - lib3270_set_connected_initial(hSession);
141   -
142   -}
143   -
144   -
145   -#if defined(_WIN32)
146   -
147   - static void sockstart(H3270 *session)
148   - {
149   - static int initted = 0;
150   - WORD wVersionRequested;
151   - WSADATA wsaData;
152   -
153   - if (initted)
154   - return;
155   -
156   - initted = 1;
157   -
158   - wVersionRequested = MAKEWORD(2, 2);
159   -
160   - if (WSAStartup(wVersionRequested, &wsaData) != 0)
161   - {
162   - lib3270_popup_dialog( session,
163   - LIB3270_NOTIFY_CRITICAL,
164   - N_( "Network startup error" ),
165   - N_( "WSAStartup failed" ),
166   - "%s", lib3270_win32_strerror(GetLastError()) );
167   -
168   - _exit(1);
169   - }
170   -
171   - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
172   - {
173   - lib3270_popup_dialog( session,
174   - LIB3270_NOTIFY_CRITICAL,
175   - N_( "Network startup error" ),
176   - N_( "Bad winsock version" ),
177   - N_( "Can't use winsock version %d.%d" ), LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
178   - _exit(1);
179   - }
180   - }
181   -#endif // WIN32
182   -
183   - LIB3270_EXPORT int lib3270_connect_url(H3270 *hSession, const char *url, int wait)
184   - {
185   - CHECK_SESSION_HANDLE(hSession);
186   -
187   - if(url && *url)
188   - {
189   - lib3270_set_url(hSession,url);
190   - }
191   -
192   - return lib3270_connect(hSession, wait);
193   -
194   - }
195   -
196   - LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc, LIB3270_OPTION opt)
197   - {
198   - CHECK_SESSION_HANDLE(hSession);
199   -
200   - if(!hostname)
201   - return EINVAL;
202   -
203   - if(!srvc)
204   - srvc = "telnet";
205   -
206   - if(*hostname == '$')
207   - {
208   - const char *name = getenv(hostname+1);
209   - if(!name)
210   - {
211   - lib3270_popup_dialog( hSession,
212   - LIB3270_NOTIFY_ERROR,
213   - _( "Connection error" ),
214   - _( "Unable to find selected hostname." ),
215   - _( "Can't determine value for environment variable \"%s\" " ),
216   - hostname);
217   - lib3270_set_disconnected(hSession);
218   - return ENOENT;
219   - }
220   - hostname = name;
221   - }
222   -
223   - hSession->options = opt & ~LIB3270_OPTION_WAIT;
224   - Replace(hSession->host.current,strdup(hostname));
225   - Replace(hSession->host.srvc,strdup(srvc));
226   -
227   - Replace(hSession->host.full,
228   - lib3270_strdup_printf(
229   - "%s%s:%s",
230   - opt&LIB3270_OPTION_SSL ? "tn3270s://" : "tn3270://",
231   - hostname,
232   - srvc ));
233   -
234   - trace("current_host=\"%s\"",hSession->host.current);
235   -
236   - return lib3270_connect(hSession,opt & LIB3270_OPTION_WAIT);
237   -
238   - }
239   -
240   - int lib3270_connect(H3270 *hSession, int seconds)
241   - {
242   - int s;
243   - int optval;
244   - struct addrinfo hints;
245   - struct addrinfo * result = NULL;
246   - struct addrinfo * rp = NULL;
247   -
248   - CHECK_SESSION_HANDLE(hSession);
249   -
250   - lib3270_main_iterate(hSession,0);
251   -
252   - if(hSession->auto_reconnect_inprogress)
253   - return errno = EAGAIN;
254   -
255   - if(hSession->sock > 0)
256   - return errno = EBUSY;
257   -
258   -#if defined(_WIN32)
259   - sockstart(hSession);
260   -#endif
261   -
262   -#if defined(HAVE_LIBSSL)
263   - set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
264   -#endif // HAVE_LIBSSL
265   -
266   - snprintf(hSession->full_model_name,LIB3270_FULL_MODEL_NAME_LENGTH,"IBM-327%c-%d",hSession->m3279 ? '9' : '8', hSession->model_num);
267   -
268   - hSession->ever_3270 = False;
269   -
270   - memset(&hints, 0, sizeof(struct addrinfo));
271   - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
272   - hints.ai_socktype = SOCK_STREAM; /* Stream socket */
273   - hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
274   - hints.ai_protocol = 0; /* Any protocol */
275   - hints.ai_canonname = NULL;
276   - hints.ai_addr = NULL;
277   - hints.ai_next = NULL;
278   -
279   - hSession->cstate = LIB3270_RESOLVING;
280   - lib3270_st_changed(hSession, LIB3270_STATE_RESOLVING, True);
281   -
282   - s = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
283   -
284   - if(s != 0)
285   - {
286   - char buffer[4096];
287   -
288   - snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
289   -
290   -#if defined(WIN32) && defined(HAVE_ICONV)
291   - {
292   - char tmpbuffer[4096];
293   - const char * msg = gai_strerror(s);
294   - size_t in = strlen(msg);
295   - size_t out = 4096;
296   - char * ptr = tmpbuffer;
297   -
298   - iconv_t hConv = iconv_open(lib3270_win32_local_charset(),"UTF-8");
299   -
300   - trace("Antes: [%s]",msg);
301   - if(iconv(hConv,&msg,&in,&ptr,&out) != ((size_t) -1))
302   - msg = tmpbuffer;
303   - trace("Depois: [%s]",msg);
304   -
305   - iconv_close(hConv);
306   -
307   - lib3270_popup_dialog( hSession,
308   - LIB3270_NOTIFY_ERROR,
309   - _( "Connection error" ),
310   - buffer,
311   - "%s",
312   - msg);
313   - }
314   -
315   -#else
316   - lib3270_popup_dialog( hSession,
317   - LIB3270_NOTIFY_ERROR,
318   - _( "Connection error" ),
319   - buffer,
320   - "%s",
321   - gai_strerror(s));
322   -#endif // WIN32
323   -
324   -
325   - lib3270_set_disconnected(hSession);
326   - return errno = ENOENT;
327   - }
328   -
329   -
330   -#if !defined(_WIN32)
331   - /* don't share the socket with our children */
332   - (void) fcntl(hSession->sock, F_SETFD, 1);
333   -#endif
334   -
335   - hSession->ever_3270 = False;
336   - hSession->ssl.host = 0;
337   -
338   - if(hSession->options&LIB3270_OPTION_SSL)
339   - {
340   -#if defined(HAVE_LIBSSL)
341   - hSession->ssl.host = 1;
342   - ssl_init(hSession);
343   -#else
344   - lib3270_popup_dialog( hSession,
345   - LIB3270_NOTIFY_ERROR,
346   - _( "SSL error" ),
347   - _( "Unable to connect to secure hosts" ),
348   - _( "This version of %s was built without support for secure sockets layer (SSL)." ),
349   - PACKAGE_NAME);
350   -
351   - return errno = EINVAL;
352   -#endif // HAVE_LIBSSL
353   - }
354   -
355   - /* connect */
356   - status_connecting(hSession,1);
357   -
358   - for(rp = result; hSession->sock < 0 && rp != NULL; rp = rp->ai_next)
359   - {
360   - hSession->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
361   - if(hSession->sock < 0)
362   - continue;
363   -
364   - trace("sock=%d",hSession->sock);
365   -
366   -#ifdef WIN32
367   -
368   - WSASetLastError(0);
369   - u_long iMode=1;
370   - trace("sock=%d",hSession->sock);
371   -
372   - optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
373   - if (setsockopt(hSession->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
374   - {
375   - char buffer[4096];
376   - snprintf(buffer,4095,N_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
377   -
378   - lib3270_popup_dialog( hSession,
379   - LIB3270_NOTIFY_ERROR,
380   - _( "Connection error" ),
381   - buffer,
382   - "%s", lib3270_win32_strerror(WSAGetLastError()));
383   - SOCK_CLOSE(hSession);
384   - continue;
385   - }
386   - else
387   - {
388   - trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
389   - }
390   -
391   - if(ioctlsocket(hSession->sock,FIONBIO,&iMode))
392   - {
393   - lib3270_popup_dialog( hSession,
394   - LIB3270_NOTIFY_ERROR,
395   - _( "Connection error" ),
396   - _( "ioctlsocket(FIONBIO) failed." ),
397   - "%s", lib3270_win32_strerror(WSAGetLastError()));
398   - SOCK_CLOSE(hSession);
399   - continue;
400   - }
401   - else if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
402   - {
403   - int err = WSAGetLastError();
404   - if(err != WSAEWOULDBLOCK)
405   - {
406   - char buffer[4096];
407   - snprintf(buffer,4095,_( "Can't connect to %s"), lib3270_get_host(hSession));
408   -
409   - lib3270_popup_dialog( hSession,
410   - LIB3270_NOTIFY_ERROR,
411   - _( "Connection error" ),
412   - buffer,
413   - "%s", lib3270_win32_strerror(err));
414   - SOCK_CLOSE(hSession);
415   - continue;
416   -
417   - }
418   - }
419   -
420   - optval = 1;
421   - if (setsockopt(hSession->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
422   - {
423   - lib3270_popup_dialog( hSession,
424   - LIB3270_NOTIFY_ERROR,
425   - _( "Connection error" ),
426   - _( "setsockopt(SO_OOBINLINE) has failed" ),
427   - "%s", lib3270_win32_strerror(WSAGetLastError()));
428   - SOCK_CLOSE(hSession);
429   - continue;
430   - }
431   -
432   -#else
433   - fcntl(hSession->sock, F_SETFL,fcntl(hSession->sock,F_GETFL,0)|O_NONBLOCK);
434   -
435   - errno = 0;
436   - if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
437   - {
438   - if( errno != EINPROGRESS )
439   - {
440   - char buffer[4096];
441   - snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
442   -
443   - lib3270_popup_dialog( hSession,
444   - LIB3270_NOTIFY_ERROR,
445   - _( "Connection error" ),
446   - buffer,
447   - "%s",
448   - strerror(errno));
449   - SOCK_CLOSE(hSession);
450   - continue;
451   - }
452   - }
453   -
454   - optval = 1;
455   - if (setsockopt(hSession->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
456   - {
457   - lib3270_popup_dialog( hSession,
458   - LIB3270_NOTIFY_ERROR,
459   - _( "Connection error" ),
460   - _( "setsockopt(SO_OOBINLINE) has failed" ),
461   - "%s",
462   - strerror(errno));
463   - SOCK_CLOSE(hSession);
464   - continue;
465   - }
466   -
467   - optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
468   - if (setsockopt(hSession->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
469   - {
470   - char buffer[4096];
471   - snprintf(buffer,4095,N_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
472   -
473   - lib3270_popup_dialog( hSession,
474   - LIB3270_NOTIFY_ERROR,
475   - _( "Connection error" ),
476   - buffer,
477   - "%s",
478   - strerror(errno));
479   - SOCK_CLOSE(hSession);
480   - continue;
481   - }
482   - else
483   - {
484   - trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
485   - }
486   -
487   -#endif // WIN32
488   - }
489   -
490   - freeaddrinfo(result);
491   -
492   - // set options for inline out-of-band data and keepalives
493   -
494   - /*
495   -#if defined(OMTU)
496   - else if (setsockopt(hSession->sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,sizeof(mtu)) < 0)
497   - {
498   - popup_a_sockerr(hSession, N_( "setsockopt(%s)" ), "SO_SNDBUF");
499   - SOCK_CLOSE(hSession);
500   - }
501   -#endif
502   -
503   - */
504   -
505   - if(hSession->sock < 0)
506   - {
507   - lib3270_set_disconnected(hSession);
508   - return errno = ENOTCONN;
509   - }
510   -
511   - // Connecting, set callbacks, wait for connection
512   - hSession->cstate = LIB3270_PENDING;
513   - lib3270_st_changed(hSession, LIB3270_STATE_HALF_CONNECT, True);
514   -
515   - hSession->xio.write = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_WRITE,net_connected,0);
516   - // hSession->ns_write_id = AddOutput(hSession->sock, hSession, net_connected);
517   -
518   - trace("%s: Connection in progress",__FUNCTION__);
519   -
520   - if(seconds)
521   - {
522   - time_t end = time(0)+seconds;
523   -
524   - while(time(0) < end)
525   - {
526   - lib3270_main_iterate(hSession,1);
527   -
528   - switch(hSession->cstate)
529   - {
530   - case LIB3270_PENDING:
531   - case LIB3270_CONNECTED_INITIAL:
532   - case LIB3270_CONNECTED_ANSI:
533   - case LIB3270_CONNECTED_3270:
534   - case LIB3270_CONNECTED_INITIAL_E:
535   - case LIB3270_CONNECTED_NVT:
536   - case LIB3270_CONNECTED_SSCP:
537   - break;
538   -
539   - case LIB3270_NOT_CONNECTED:
540   - return errno = ENOTCONN;
541   -
542   - case LIB3270_CONNECTED_TN3270E:
543   - return 0;
544   -
545   - default:
546   - lib3270_write_log(hSession,"connect", "%s: State changed to unexpected state %d",__FUNCTION__,hSession->cstate);
547   - return -1;
548   - }
549   -
550   - }
551   -
552   - lib3270_disconnect(hSession);
553   - lib3270_write_log(hSession,"connect", "%s: %s",__FUNCTION__,strerror(ETIMEDOUT));
554   - return errno = ETIMEDOUT;
555   - }
556   -
557   - return 0;
558   -
559   - }
560   -
src/lib3270/linux/connect.c 0 → 100644
... ... @@ -0,0 +1,407 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 +#include <config.h>
  31 +#include "../private.h"
  32 +#include <errno.h>
  33 +
  34 +#include <sys/types.h>
  35 +#include <sys/socket.h>
  36 +#include <sys/ioctl.h>
  37 +#include <netinet/in.h>
  38 +#include <netdb.h>
  39 +#include <unistd.h>
  40 +#include <fcntl.h>
  41 +
  42 +// #ifdef HAVE_ICONV
  43 +// #include <iconv.h>
  44 +// #endif // HAVE_ICONV
  45 +
  46 +#define SOCK_CLOSE(s) close(s->sock); s->sock = -1;
  47 +
  48 +#include <stdlib.h>
  49 +
  50 +//#include "statusc.h"
  51 +#include "hostc.h"
  52 +#include "trace_dsc.h"
  53 +//#include "utilc.h"
  54 +#include "telnetc.h"
  55 +#include "screen.h"
  56 +
  57 +#include <lib3270/internals.h>
  58 +
  59 +/*---[ Implement ]-------------------------------------------------------------------------------*/
  60 +
  61 +
  62 +//static void net_connected(H3270 *hSession)
  63 +static void net_connected(H3270 *hSession, int fd unused, LIB3270_IO_FLAG flag unused, void *dunno unused)
  64 +{
  65 + int err;
  66 + socklen_t len = sizeof(err);
  67 +
  68 + if(hSession->xio.write) {
  69 + trace("%s write=%p",__FUNCTION__,hSession->xio.write);
  70 + lib3270_remove_poll(hSession, hSession->xio.write);
  71 + hSession->xio.write = NULL;
  72 + }
  73 +
  74 + if(getsockopt(hSession->sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0)
  75 + {
  76 + lib3270_disconnect(hSession);
  77 + lib3270_popup_dialog(
  78 + hSession,
  79 + LIB3270_NOTIFY_ERROR,
  80 + _( "Network error" ),
  81 + _( "Unable to get connection state." ),
  82 + _( "%s" ), strerror(errno)
  83 + );
  84 + return;
  85 + }
  86 + else if(err)
  87 + {
  88 + char buffer[4096];
  89 + snprintf(buffer,4095,_( "Can't connect to %s" ), hSession->host.current );
  90 +
  91 + lib3270_disconnect(hSession);
  92 + lib3270_popup_dialog(
  93 + hSession,
  94 + LIB3270_NOTIFY_ERROR,
  95 + _( "Connection failed" ),
  96 + buffer,
  97 + _( "%s" ), strerror(err)
  98 + );
  99 + return;
  100 + }
  101 +
  102 + hSession->xio.except = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0);
  103 + hSession->xio.read = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_READ,net_input,0);
  104 +
  105 +#if defined(HAVE_LIBSSL)
  106 + if(hSession->ssl.con && hSession->ssl.state == LIB3270_SSL_UNDEFINED)
  107 + {
  108 + if(ssl_negotiate(hSession))
  109 + return;
  110 + }
  111 +#endif
  112 +
  113 + lib3270_setup_session(hSession);
  114 + lib3270_set_connected_initial(hSession);
  115 +
  116 +}
  117 +
  118 + LIB3270_EXPORT int lib3270_connect_url(H3270 *hSession, const char *url, int wait)
  119 + {
  120 + CHECK_SESSION_HANDLE(hSession);
  121 +
  122 + if(url && *url)
  123 + {
  124 + lib3270_set_url(hSession,url);
  125 + }
  126 +
  127 + return lib3270_connect(hSession, wait);
  128 +
  129 + }
  130 +
  131 + LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc, LIB3270_OPTION opt)
  132 + {
  133 + CHECK_SESSION_HANDLE(hSession);
  134 +
  135 + if(!hostname)
  136 + return EINVAL;
  137 +
  138 + if(!srvc)
  139 + srvc = "telnet";
  140 +
  141 + if(*hostname == '$')
  142 + {
  143 + const char *name = getenv(hostname+1);
  144 + if(!name)
  145 + {
  146 + lib3270_popup_dialog( hSession,
  147 + LIB3270_NOTIFY_ERROR,
  148 + _( "Connection error" ),
  149 + _( "Unable to find selected hostname." ),
  150 + _( "Can't determine value for environment variable \"%s\" " ),
  151 + hostname);
  152 + lib3270_set_disconnected(hSession);
  153 + return ENOENT;
  154 + }
  155 + hostname = name;
  156 + }
  157 +
  158 + hSession->options = opt & ~LIB3270_OPTION_WAIT;
  159 + Replace(hSession->host.current,strdup(hostname));
  160 + Replace(hSession->host.srvc,strdup(srvc));
  161 +
  162 + Replace(hSession->host.full,
  163 + lib3270_strdup_printf(
  164 + "%s%s:%s",
  165 + opt&LIB3270_OPTION_SSL ? "tn3270s://" : "tn3270://",
  166 + hostname,
  167 + srvc ));
  168 +
  169 + trace("current_host=\"%s\"",hSession->host.current);
  170 +
  171 + return lib3270_connect(hSession,opt & LIB3270_OPTION_WAIT);
  172 +
  173 + }
  174 +
  175 + struct resolver
  176 + {
  177 + const char * message;
  178 + };
  179 +
  180 + static int background_connect(H3270 *hSession, void *host)
  181 + {
  182 + struct addrinfo hints;
  183 + struct addrinfo * result = NULL;
  184 + struct addrinfo * rp = NULL;
  185 +
  186 + memset(&hints,0,sizeof(hints));
  187 + hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
  188 + hints.ai_socktype = SOCK_STREAM; // Stream socket
  189 + hints.ai_flags = AI_PASSIVE; // For wildcard IP address
  190 + hints.ai_protocol = 0; // Any protocol
  191 +
  192 + int rc = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
  193 + if(rc != 0)
  194 + {
  195 + ((struct resolver *) host)->message = gai_strerror(rc);
  196 + return -1;
  197 + }
  198 +
  199 + status_connecting(hSession,1);
  200 +
  201 + for(rp = result; hSession->sock < 0 && rp != NULL; rp = rp->ai_next)
  202 + {
  203 + hSession->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  204 + if(hSession->sock < 0)
  205 + {
  206 + ((struct resolver *) host)->message = strerror(errno);
  207 + continue;
  208 + }
  209 +
  210 + // Connected!
  211 + if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
  212 + {
  213 + SOCK_CLOSE(hSession);
  214 + ((struct resolver *) host)->message = strerror(errno);
  215 + continue;
  216 + }
  217 +
  218 + }
  219 +
  220 + freeaddrinfo(result);
  221 +
  222 + return 0;
  223 +
  224 + }
  225 +
  226 + int lib3270_connect(H3270 *hSession, int seconds)
  227 + {
  228 + int optval;
  229 + struct resolver host;
  230 +
  231 + CHECK_SESSION_HANDLE(hSession);
  232 +
  233 + memset(&host,0,sizeof(host));
  234 +
  235 + lib3270_main_iterate(hSession,0);
  236 +
  237 + if(hSession->auto_reconnect_inprogress)
  238 + return errno = EAGAIN;
  239 +
  240 + if(hSession->sock > 0)
  241 + return errno = EBUSY;
  242 +
  243 +#if defined(HAVE_LIBSSL)
  244 + set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
  245 +#endif // HAVE_LIBSSL
  246 +
  247 + snprintf(hSession->full_model_name,LIB3270_FULL_MODEL_NAME_LENGTH,"IBM-327%c-%d",hSession->m3279 ? '9' : '8', hSession->model_num);
  248 +
  249 + hSession->ever_3270 = False;
  250 + hSession->cstate = LIB3270_RESOLVING;
  251 +
  252 + lib3270_st_changed(hSession, LIB3270_STATE_RESOLVING, True);
  253 +
  254 + // s = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
  255 + if(lib3270_run_task(hSession, background_connect, &host))
  256 + {
  257 + char buffer[4096];
  258 + snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
  259 +
  260 + lib3270_popup_dialog( hSession,
  261 + LIB3270_NOTIFY_ERROR,
  262 + _( "Connection error" ),
  263 + buffer,
  264 + "%s",
  265 + host.message);
  266 +
  267 + lib3270_set_disconnected(hSession);
  268 + return errno = ENOENT;
  269 + }
  270 +
  271 + /* don't share the socket with our children */
  272 + (void) fcntl(hSession->sock, F_SETFD, 1);
  273 +
  274 + hSession->ever_3270 = False;
  275 + hSession->ssl.host = 0;
  276 +
  277 + if(hSession->options&LIB3270_OPTION_SSL)
  278 + {
  279 +#if defined(HAVE_LIBSSL)
  280 + hSession->ssl.host = 1;
  281 + ssl_init(hSession);
  282 +#else
  283 + lib3270_popup_dialog( hSession,
  284 + LIB3270_NOTIFY_ERROR,
  285 + _( "SSL error" ),
  286 + _( "Unable to connect to secure hosts" ),
  287 + _( "This version of %s was built without support for secure sockets layer (SSL)." ),
  288 + PACKAGE_NAME);
  289 +
  290 + return errno = EINVAL;
  291 +#endif // HAVE_LIBSSL
  292 + }
  293 +
  294 + /* connect */
  295 + if(hSession->sock < 0)
  296 + {
  297 + lib3270_set_disconnected(hSession);
  298 +
  299 + char buffer[4096];
  300 + snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
  301 +
  302 + lib3270_popup_dialog(
  303 + hSession,
  304 + LIB3270_NOTIFY_ERROR,
  305 + _( "Connection error" ),
  306 + buffer,
  307 + "%s",
  308 + host.message
  309 + );
  310 +
  311 + return errno = ENOTCONN;
  312 + }
  313 +
  314 + // set options for inline out-of-band data and keepalives
  315 + optval = 1;
  316 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
  317 + {
  318 + lib3270_popup_dialog( hSession,
  319 + LIB3270_NOTIFY_ERROR,
  320 + _( "Connection error" ),
  321 + _( "setsockopt(SO_OOBINLINE) has failed" ),
  322 + "%s",
  323 + strerror(errno));
  324 + SOCK_CLOSE(hSession);
  325 + }
  326 +
  327 + optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
  328 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
  329 + {
  330 + char buffer[4096];
  331 + snprintf(buffer,4095,N_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
  332 +
  333 + lib3270_popup_dialog( hSession,
  334 + LIB3270_NOTIFY_ERROR,
  335 + _( "Connection error" ),
  336 + buffer,
  337 + "%s",
  338 + strerror(errno));
  339 + SOCK_CLOSE(hSession);
  340 + }
  341 + else
  342 + {
  343 + trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
  344 + }
  345 +
  346 +
  347 + /*
  348 +#if defined(OMTU)
  349 + else if (setsockopt(hSession->sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,sizeof(mtu)) < 0)
  350 + {
  351 + popup_a_sockerr(hSession, N_( "setsockopt(%s)" ), "SO_SNDBUF");
  352 + SOCK_CLOSE(hSession);
  353 + }
  354 +#endif
  355 +
  356 + */
  357 +
  358 + // Connecting, set callbacks, wait for connection
  359 + hSession->cstate = LIB3270_PENDING;
  360 + lib3270_st_changed(hSession, LIB3270_STATE_HALF_CONNECT, True);
  361 +
  362 + hSession->xio.write = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_WRITE,net_connected,0);
  363 + // hSession->ns_write_id = AddOutput(hSession->sock, hSession, net_connected);
  364 +
  365 + trace("%s: Connection in progress",__FUNCTION__);
  366 +
  367 + if(seconds)
  368 + {
  369 + time_t end = time(0)+seconds;
  370 +
  371 + while(time(0) < end)
  372 + {
  373 + lib3270_main_iterate(hSession,1);
  374 +
  375 + switch(hSession->cstate)
  376 + {
  377 + case LIB3270_PENDING:
  378 + case LIB3270_CONNECTED_INITIAL:
  379 + case LIB3270_CONNECTED_ANSI:
  380 + case LIB3270_CONNECTED_3270:
  381 + case LIB3270_CONNECTED_INITIAL_E:
  382 + case LIB3270_CONNECTED_NVT:
  383 + case LIB3270_CONNECTED_SSCP:
  384 + break;
  385 +
  386 + case LIB3270_NOT_CONNECTED:
  387 + return errno = ENOTCONN;
  388 +
  389 + case LIB3270_CONNECTED_TN3270E:
  390 + return 0;
  391 +
  392 + default:
  393 + lib3270_write_log(hSession,"connect", "%s: State changed to unexpected state %d",__FUNCTION__,hSession->cstate);
  394 + return -1;
  395 + }
  396 +
  397 + }
  398 +
  399 + lib3270_disconnect(hSession);
  400 + lib3270_write_log(hSession,"connect", "%s: %s",__FUNCTION__,strerror(ETIMEDOUT));
  401 + return errno = ETIMEDOUT;
  402 + }
  403 +
  404 + return 0;
  405 +
  406 + }
  407 +
... ...
src/lib3270/windows/connect.c 0 → 100644
... ... @@ -0,0 +1,560 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como connect.c e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 +#include <config.h>
  31 +
  32 +#if defined(_WIN32)
  33 +
  34 + // Compiling for WinXP or later: Expose getaddrinfo()/freeaddrinfo().
  35 + #undef _WIN32_WINNT
  36 + #define _WIN32_WINNT 0x0501
  37 +
  38 + #include <winsock2.h>
  39 + #include <windows.h>
  40 + #include <ws2tcpip.h>
  41 +
  42 +#endif
  43 +
  44 +#include "private.h"
  45 +#include <errno.h>
  46 +
  47 +#if defined(_WIN32)
  48 + #include <ws2tcpip.h>
  49 +#else
  50 + #include <sys/types.h>
  51 + #include <sys/socket.h>
  52 + #include <sys/ioctl.h>
  53 + #include <netinet/in.h>
  54 + #include <netdb.h>
  55 + #include <unistd.h>
  56 + #include <fcntl.h>
  57 +#endif
  58 +
  59 +#ifdef HAVE_ICONV
  60 + #include <iconv.h>
  61 +#endif // HAVE_ICONV
  62 +
  63 +#if defined(_WIN32) /*[*/
  64 + #define SOCK_CLOSE(s) closesocket(s->sock); s->sock = -1;
  65 +#else /*][*/
  66 + #define SOCK_CLOSE(s) close(s->sock); s->sock = -1;
  67 +#endif /*]*/
  68 +
  69 +#include <stdlib.h>
  70 +#include "statusc.h"
  71 +#include "hostc.h"
  72 +#include "trace_dsc.h"
  73 +#include "utilc.h"
  74 +#include "telnetc.h"
  75 +#include "screen.h"
  76 +#include <lib3270/internals.h>
  77 +
  78 +/*---[ Implement ]-------------------------------------------------------------------------------*/
  79 +
  80 +
  81 +//static void net_connected(H3270 *hSession)
  82 +static void net_connected(H3270 *hSession, int fd unused, LIB3270_IO_FLAG flag unused, void *dunno unused)
  83 +{
  84 + int err;
  85 + socklen_t len = sizeof(err);
  86 +
  87 + if(hSession->xio.write) {
  88 + trace("%s write=%p",__FUNCTION__,hSession->xio.write);
  89 + lib3270_remove_poll(hSession, hSession->xio.write);
  90 + hSession->xio.write = NULL;
  91 + }
  92 +
  93 + if(getsockopt(hSession->sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0)
  94 + {
  95 + lib3270_disconnect(hSession);
  96 + lib3270_popup_dialog( hSession,
  97 + LIB3270_NOTIFY_ERROR,
  98 + _( "Network error" ),
  99 + _( "Unable to get connection state." ),
  100 +#ifdef _WIN32
  101 + "%s", lib3270_win32_strerror(WSAGetLastError())
  102 +#else
  103 + _( "%s" ), strerror(errno)
  104 +#endif // _WIN32
  105 + );
  106 + return;
  107 + }
  108 + else if(err)
  109 + {
  110 + char buffer[4096];
  111 + snprintf(buffer,4095,_( "Can't connect to %s" ), hSession->host.current );
  112 +
  113 + lib3270_disconnect(hSession);
  114 + lib3270_popup_dialog( hSession,
  115 + LIB3270_NOTIFY_ERROR,
  116 + _( "Connection failed" ),
  117 + buffer,
  118 +#ifdef _WIN32
  119 + _( "%s"), lib3270_win32_strerror(err)
  120 +#else
  121 + _( "%s" ), strerror(err)
  122 +#endif // _WIN32
  123 + );
  124 + trace("%s",__FUNCTION__);
  125 + return;
  126 + }
  127 +
  128 + hSession->xio.except = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0);
  129 + hSession->xio.read = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_READ,net_input,0);
  130 +
  131 +#if defined(HAVE_LIBSSL)
  132 + if(hSession->ssl.con && hSession->ssl.state == LIB3270_SSL_UNDEFINED)
  133 + {
  134 + if(ssl_negotiate(hSession))
  135 + return;
  136 + }
  137 +#endif
  138 +
  139 + lib3270_setup_session(hSession);
  140 + lib3270_set_connected_initial(hSession);
  141 +
  142 +}
  143 +
  144 +
  145 +#if defined(_WIN32)
  146 +
  147 + static void sockstart(H3270 *session)
  148 + {
  149 + static int initted = 0;
  150 + WORD wVersionRequested;
  151 + WSADATA wsaData;
  152 +
  153 + if (initted)
  154 + return;
  155 +
  156 + initted = 1;
  157 +
  158 + wVersionRequested = MAKEWORD(2, 2);
  159 +
  160 + if (WSAStartup(wVersionRequested, &wsaData) != 0)
  161 + {
  162 + lib3270_popup_dialog( session,
  163 + LIB3270_NOTIFY_CRITICAL,
  164 + N_( "Network startup error" ),
  165 + N_( "WSAStartup failed" ),
  166 + "%s", lib3270_win32_strerror(GetLastError()) );
  167 +
  168 + _exit(1);
  169 + }
  170 +
  171 + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
  172 + {
  173 + lib3270_popup_dialog( session,
  174 + LIB3270_NOTIFY_CRITICAL,
  175 + N_( "Network startup error" ),
  176 + N_( "Bad winsock version" ),
  177 + N_( "Can't use winsock version %d.%d" ), LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
  178 + _exit(1);
  179 + }
  180 + }
  181 +#endif // WIN32
  182 +
  183 + LIB3270_EXPORT int lib3270_connect_url(H3270 *hSession, const char *url, int wait)
  184 + {
  185 + CHECK_SESSION_HANDLE(hSession);
  186 +
  187 + if(url && *url)
  188 + {
  189 + lib3270_set_url(hSession,url);
  190 + }
  191 +
  192 + return lib3270_connect(hSession, wait);
  193 +
  194 + }
  195 +
  196 + LIB3270_EXPORT int lib3270_connect_host(H3270 *hSession, const char *hostname, const char *srvc, LIB3270_OPTION opt)
  197 + {
  198 + CHECK_SESSION_HANDLE(hSession);
  199 +
  200 + if(!hostname)
  201 + return EINVAL;
  202 +
  203 + if(!srvc)
  204 + srvc = "telnet";
  205 +
  206 + if(*hostname == '$')
  207 + {
  208 + const char *name = getenv(hostname+1);
  209 + if(!name)
  210 + {
  211 + lib3270_popup_dialog( hSession,
  212 + LIB3270_NOTIFY_ERROR,
  213 + _( "Connection error" ),
  214 + _( "Unable to find selected hostname." ),
  215 + _( "Can't determine value for environment variable \"%s\" " ),
  216 + hostname);
  217 + lib3270_set_disconnected(hSession);
  218 + return ENOENT;
  219 + }
  220 + hostname = name;
  221 + }
  222 +
  223 + hSession->options = opt & ~LIB3270_OPTION_WAIT;
  224 + Replace(hSession->host.current,strdup(hostname));
  225 + Replace(hSession->host.srvc,strdup(srvc));
  226 +
  227 + Replace(hSession->host.full,
  228 + lib3270_strdup_printf(
  229 + "%s%s:%s",
  230 + opt&LIB3270_OPTION_SSL ? "tn3270s://" : "tn3270://",
  231 + hostname,
  232 + srvc ));
  233 +
  234 + trace("current_host=\"%s\"",hSession->host.current);
  235 +
  236 + return lib3270_connect(hSession,opt & LIB3270_OPTION_WAIT);
  237 +
  238 + }
  239 +
  240 + int lib3270_connect(H3270 *hSession, int seconds)
  241 + {
  242 + int s;
  243 + int optval;
  244 + struct addrinfo hints;
  245 + struct addrinfo * result = NULL;
  246 + struct addrinfo * rp = NULL;
  247 +
  248 + CHECK_SESSION_HANDLE(hSession);
  249 +
  250 + lib3270_main_iterate(hSession,0);
  251 +
  252 + if(hSession->auto_reconnect_inprogress)
  253 + return errno = EAGAIN;
  254 +
  255 + if(hSession->sock > 0)
  256 + return errno = EBUSY;
  257 +
  258 +#if defined(_WIN32)
  259 + sockstart(hSession);
  260 +#endif
  261 +
  262 +#if defined(HAVE_LIBSSL)
  263 + set_ssl_state(hSession,LIB3270_SSL_UNSECURE);
  264 +#endif // HAVE_LIBSSL
  265 +
  266 + snprintf(hSession->full_model_name,LIB3270_FULL_MODEL_NAME_LENGTH,"IBM-327%c-%d",hSession->m3279 ? '9' : '8', hSession->model_num);
  267 +
  268 + hSession->ever_3270 = False;
  269 +
  270 + memset(&hints, 0, sizeof(struct addrinfo));
  271 + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
  272 + hints.ai_socktype = SOCK_STREAM; /* Stream socket */
  273 + hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
  274 + hints.ai_protocol = 0; /* Any protocol */
  275 + hints.ai_canonname = NULL;
  276 + hints.ai_addr = NULL;
  277 + hints.ai_next = NULL;
  278 +
  279 + hSession->cstate = LIB3270_RESOLVING;
  280 + lib3270_st_changed(hSession, LIB3270_STATE_RESOLVING, True);
  281 +
  282 + s = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
  283 +
  284 + if(s != 0)
  285 + {
  286 + char buffer[4096];
  287 +
  288 + snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
  289 +
  290 +#if defined(WIN32) && defined(HAVE_ICONV)
  291 + {
  292 + char tmpbuffer[4096];
  293 + const char * msg = gai_strerror(s);
  294 + size_t in = strlen(msg);
  295 + size_t out = 4096;
  296 + char * ptr = tmpbuffer;
  297 +
  298 + iconv_t hConv = iconv_open(lib3270_win32_local_charset(),"UTF-8");
  299 +
  300 + trace("Antes: [%s]",msg);
  301 + if(iconv(hConv,&msg,&in,&ptr,&out) != ((size_t) -1))
  302 + msg = tmpbuffer;
  303 + trace("Depois: [%s]",msg);
  304 +
  305 + iconv_close(hConv);
  306 +
  307 + lib3270_popup_dialog( hSession,
  308 + LIB3270_NOTIFY_ERROR,
  309 + _( "Connection error" ),
  310 + buffer,
  311 + "%s",
  312 + msg);
  313 + }
  314 +
  315 +#else
  316 + lib3270_popup_dialog( hSession,
  317 + LIB3270_NOTIFY_ERROR,
  318 + _( "Connection error" ),
  319 + buffer,
  320 + "%s",
  321 + gai_strerror(s));
  322 +#endif // WIN32
  323 +
  324 +
  325 + lib3270_set_disconnected(hSession);
  326 + return errno = ENOENT;
  327 + }
  328 +
  329 +
  330 +#if !defined(_WIN32)
  331 + /* don't share the socket with our children */
  332 + (void) fcntl(hSession->sock, F_SETFD, 1);
  333 +#endif
  334 +
  335 + hSession->ever_3270 = False;
  336 + hSession->ssl.host = 0;
  337 +
  338 + if(hSession->options&LIB3270_OPTION_SSL)
  339 + {
  340 +#if defined(HAVE_LIBSSL)
  341 + hSession->ssl.host = 1;
  342 + ssl_init(hSession);
  343 +#else
  344 + lib3270_popup_dialog( hSession,
  345 + LIB3270_NOTIFY_ERROR,
  346 + _( "SSL error" ),
  347 + _( "Unable to connect to secure hosts" ),
  348 + _( "This version of %s was built without support for secure sockets layer (SSL)." ),
  349 + PACKAGE_NAME);
  350 +
  351 + return errno = EINVAL;
  352 +#endif // HAVE_LIBSSL
  353 + }
  354 +
  355 + /* connect */
  356 + status_connecting(hSession,1);
  357 +
  358 + for(rp = result; hSession->sock < 0 && rp != NULL; rp = rp->ai_next)
  359 + {
  360 + hSession->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  361 + if(hSession->sock < 0)
  362 + continue;
  363 +
  364 + trace("sock=%d",hSession->sock);
  365 +
  366 +#ifdef WIN32
  367 +
  368 + WSASetLastError(0);
  369 + u_long iMode=1;
  370 + trace("sock=%d",hSession->sock);
  371 +
  372 + optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
  373 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
  374 + {
  375 + char buffer[4096];
  376 + snprintf(buffer,4095,N_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
  377 +
  378 + lib3270_popup_dialog( hSession,
  379 + LIB3270_NOTIFY_ERROR,
  380 + _( "Connection error" ),
  381 + buffer,
  382 + "%s", lib3270_win32_strerror(WSAGetLastError()));
  383 + SOCK_CLOSE(hSession);
  384 + continue;
  385 + }
  386 + else
  387 + {
  388 + trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
  389 + }
  390 +
  391 + if(ioctlsocket(hSession->sock,FIONBIO,&iMode))
  392 + {
  393 + lib3270_popup_dialog( hSession,
  394 + LIB3270_NOTIFY_ERROR,
  395 + _( "Connection error" ),
  396 + _( "ioctlsocket(FIONBIO) failed." ),
  397 + "%s", lib3270_win32_strerror(WSAGetLastError()));
  398 + SOCK_CLOSE(hSession);
  399 + continue;
  400 + }
  401 + else if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
  402 + {
  403 + int err = WSAGetLastError();
  404 + if(err != WSAEWOULDBLOCK)
  405 + {
  406 + char buffer[4096];
  407 + snprintf(buffer,4095,_( "Can't connect to %s"), lib3270_get_host(hSession));
  408 +
  409 + lib3270_popup_dialog( hSession,
  410 + LIB3270_NOTIFY_ERROR,
  411 + _( "Connection error" ),
  412 + buffer,
  413 + "%s", lib3270_win32_strerror(err));
  414 + SOCK_CLOSE(hSession);
  415 + continue;
  416 +
  417 + }
  418 + }
  419 +
  420 + optval = 1;
  421 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
  422 + {
  423 + lib3270_popup_dialog( hSession,
  424 + LIB3270_NOTIFY_ERROR,
  425 + _( "Connection error" ),
  426 + _( "setsockopt(SO_OOBINLINE) has failed" ),
  427 + "%s", lib3270_win32_strerror(WSAGetLastError()));
  428 + SOCK_CLOSE(hSession);
  429 + continue;
  430 + }
  431 +
  432 +#else
  433 + fcntl(hSession->sock, F_SETFL,fcntl(hSession->sock,F_GETFL,0)|O_NONBLOCK);
  434 +
  435 + errno = 0;
  436 + if(connect(hSession->sock, rp->ai_addr, rp->ai_addrlen))
  437 + {
  438 + if( errno != EINPROGRESS )
  439 + {
  440 + char buffer[4096];
  441 + snprintf(buffer,4095,_( "Can't connect to %s:%s"), hSession->host.current, hSession->host.srvc);
  442 +
  443 + lib3270_popup_dialog( hSession,
  444 + LIB3270_NOTIFY_ERROR,
  445 + _( "Connection error" ),
  446 + buffer,
  447 + "%s",
  448 + strerror(errno));
  449 + SOCK_CLOSE(hSession);
  450 + continue;
  451 + }
  452 + }
  453 +
  454 + optval = 1;
  455 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
  456 + {
  457 + lib3270_popup_dialog( hSession,
  458 + LIB3270_NOTIFY_ERROR,
  459 + _( "Connection error" ),
  460 + _( "setsockopt(SO_OOBINLINE) has failed" ),
  461 + "%s",
  462 + strerror(errno));
  463 + SOCK_CLOSE(hSession);
  464 + continue;
  465 + }
  466 +
  467 + optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
  468 + if (setsockopt(hSession->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
  469 + {
  470 + char buffer[4096];
  471 + snprintf(buffer,4095,N_( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
  472 +
  473 + lib3270_popup_dialog( hSession,
  474 + LIB3270_NOTIFY_ERROR,
  475 + _( "Connection error" ),
  476 + buffer,
  477 + "%s",
  478 + strerror(errno));
  479 + SOCK_CLOSE(hSession);
  480 + continue;
  481 + }
  482 + else
  483 + {
  484 + trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
  485 + }
  486 +
  487 +#endif // WIN32
  488 + }
  489 +
  490 + freeaddrinfo(result);
  491 +
  492 + // set options for inline out-of-band data and keepalives
  493 +
  494 + /*
  495 +#if defined(OMTU)
  496 + else if (setsockopt(hSession->sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,sizeof(mtu)) < 0)
  497 + {
  498 + popup_a_sockerr(hSession, N_( "setsockopt(%s)" ), "SO_SNDBUF");
  499 + SOCK_CLOSE(hSession);
  500 + }
  501 +#endif
  502 +
  503 + */
  504 +
  505 + if(hSession->sock < 0)
  506 + {
  507 + lib3270_set_disconnected(hSession);
  508 + return errno = ENOTCONN;
  509 + }
  510 +
  511 + // Connecting, set callbacks, wait for connection
  512 + hSession->cstate = LIB3270_PENDING;
  513 + lib3270_st_changed(hSession, LIB3270_STATE_HALF_CONNECT, True);
  514 +
  515 + hSession->xio.write = lib3270_add_poll_fd(hSession,hSession->sock,LIB3270_IO_FLAG_WRITE,net_connected,0);
  516 + // hSession->ns_write_id = AddOutput(hSession->sock, hSession, net_connected);
  517 +
  518 + trace("%s: Connection in progress",__FUNCTION__);
  519 +
  520 + if(seconds)
  521 + {
  522 + time_t end = time(0)+seconds;
  523 +
  524 + while(time(0) < end)
  525 + {
  526 + lib3270_main_iterate(hSession,1);
  527 +
  528 + switch(hSession->cstate)
  529 + {
  530 + case LIB3270_PENDING:
  531 + case LIB3270_CONNECTED_INITIAL:
  532 + case LIB3270_CONNECTED_ANSI:
  533 + case LIB3270_CONNECTED_3270:
  534 + case LIB3270_CONNECTED_INITIAL_E:
  535 + case LIB3270_CONNECTED_NVT:
  536 + case LIB3270_CONNECTED_SSCP:
  537 + break;
  538 +
  539 + case LIB3270_NOT_CONNECTED:
  540 + return errno = ENOTCONN;
  541 +
  542 + case LIB3270_CONNECTED_TN3270E:
  543 + return 0;
  544 +
  545 + default:
  546 + lib3270_write_log(hSession,"connect", "%s: State changed to unexpected state %d",__FUNCTION__,hSession->cstate);
  547 + return -1;
  548 + }
  549 +
  550 + }
  551 +
  552 + lib3270_disconnect(hSession);
  553 + lib3270_write_log(hSession,"connect", "%s: %s",__FUNCTION__,strerror(ETIMEDOUT));
  554 + return errno = ETIMEDOUT;
  555 + }
  556 +
  557 + return 0;
  558 +
  559 + }
  560 +
... ...