Commit 5fd336a0580916aeea6609784986aae40cde9662

Authored by Perry Werneck
1 parent 445c656a

DNS Resolve and connect now runs on background thread.

@@ -157,6 +157,9 @@ @@ -157,6 +157,9 @@
157 <Unit filename="src/lib3270/kybd.c"> 157 <Unit filename="src/lib3270/kybd.c">
158 <Option compilerVar="CC" /> 158 <Option compilerVar="CC" />
159 </Unit> 159 </Unit>
  160 + <Unit filename="src/lib3270/linux/connect.c">
  161 + <Option compilerVar="CC" />
  162 + </Unit>
160 <Unit filename="src/lib3270/linux/event_dispatcher.c"> 163 <Unit filename="src/lib3270/linux/event_dispatcher.c">
161 <Option compilerVar="CC" /> 164 <Option compilerVar="CC" />
162 </Unit> 165 </Unit>
@@ -245,6 +248,9 @@ @@ -245,6 +248,9 @@
245 <Unit filename="src/lib3270/version.c"> 248 <Unit filename="src/lib3270/version.c">
246 <Option compilerVar="CC" /> 249 <Option compilerVar="CC" />
247 </Unit> 250 </Unit>
  251 + <Unit filename="src/lib3270/windows/connect.c">
  252 + <Option compilerVar="CC" />
  253 + </Unit>
248 <Unit filename="src/lib3270/windows/event_dispatcher.c"> 254 <Unit filename="src/lib3270/windows/event_dispatcher.c">
249 <Option compilerVar="CC" /> 255 <Option compilerVar="CC" />
250 </Unit> 256 </Unit>
src/lib3270/connect.c
@@ -1,560 +0,0 @@ @@ -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 @@ @@ -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 @@ @@ -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 +