From ced7f3f3be5b7082fee977910c4775966d3368bc Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Thu, 12 Apr 2012 19:34:58 +0000 Subject: [PATCH] Em windows existem momentos em que ele trava durante a conexão, movi o connect() para um thread separada tentando evitar o problema --- XtGlue.c | 2 ++ api.h | 2 +- init.c | 5 +++++ proxy.c | 5 +---- resolver.c | 22 ++++++++++++++++------ resolverc.h | 2 +- screen.c | 8 -------- screen.h | 2 +- telnet.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------- 9 files changed, 124 insertions(+), 58 deletions(-) diff --git a/XtGlue.c b/XtGlue.c index 04b37a9..f7226c9 100644 --- a/XtGlue.c +++ b/XtGlue.c @@ -979,10 +979,12 @@ LIB3270_EXPORT int lib3270_call_thread(int(*callback)(H3270 *h, void *), H3270 * if(h->set_timer) h->set_timer(h,1); + lib3270_main_iterate(0); if(callbacks->callthread) rc = callbacks->callthread(callback,h,parm); else rc = callback(h,parm); + lib3270_main_iterate(0); if(h->set_timer) h->set_timer(h,0); diff --git a/api.h b/api.h index 43ee5a1..e03a15d 100644 --- a/api.h +++ b/api.h @@ -386,7 +386,7 @@ LOCAL_EXTERN SCRIPT_STATE status_script(SCRIPT_STATE state); #define Toggled(ix) lib3270_get_toggle(NULL,ix) - #define CallAndWait(c,h,p) lib3270_call_thread(c,h,p) +// #define CallAndWait(c,h,p) lib3270_call_thread(c,h,p) // #define RunPendingEvents(x) lib3270_main_iterate(x) // #define Wait(s) lib3270_wait(x) diff --git a/init.c b/init.c index 05ff9c8..b20b471 100644 --- a/init.c +++ b/init.c @@ -107,6 +107,10 @@ static void update_selection(H3270 *session, int start, int end) { } +static void *cursor(H3270 *session, LIB3270_CURSOR id) +{ +} + static void lib3270_session_init(H3270 *hSession, const char *model) { int ovc, ovr; @@ -131,6 +135,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model) hSession->resume = screen_disp; hSession->update_oia = update_oia; hSession->update_selection = update_selection; + hSession->cursor = cursor; hSession->sock = -1; hSession->model_num = -1; diff --git a/proxy.c b/proxy.c index b5263f6..c7b431d 100644 --- a/proxy.c +++ b/proxy.c @@ -688,10 +688,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) int rv; /* Resolve the hostname. */ - status_resolving(&h3270,1); - rv = resolve_host_and_port(host, CN, &rport, &ha.sa, &ha_len, - errmsg, sizeof(errmsg)); - status_resolving(&h3270,0); + rv = resolve_host_and_port(&h3270,host, CN, &rport, &ha.sa, &ha_len,errmsg, sizeof(errmsg)); if (rv == -2) use_name = 1; else if (rv < 0) { diff --git a/resolver.c b/resolver.c index 6fb75fd..c30c6ea 100644 --- a/resolver.c +++ b/resolver.c @@ -86,6 +86,8 @@ struct parms */ static int cresolve_host_and_port(H3270 *h, struct parms *p) { +#warning Should use configure to detect getaddrinfo and use it if available. + #ifdef AF_INET6 struct addrinfo hints, *res; @@ -126,6 +128,7 @@ static int cresolve_host_and_port(H3270 *h, struct parms *p) (void) memcpy(p->sa, res->ai_addr, res->ai_addrlen); *p->sa_len = res->ai_addrlen; + freeaddrinfo(res); #else /*][*/ @@ -179,16 +182,23 @@ static int cresolve_host_and_port(H3270 *h, struct parms *p) return 0; } -int resolve_host_and_port(const char *host, char *portname, unsigned short *pport,struct sockaddr *sa, socklen_t *sa_len, char *errmsg, int em_len) +int resolve_host_and_port(H3270 *hSession, const char *host, char *portname, unsigned short *pport,struct sockaddr *sa, socklen_t *sa_len, char *errmsg, int em_len) { - int rc; - struct parms p = { sizeof(struct parms), host, portname, pport, sa, sa_len, errmsg, em_len }; + int rc; + LIB3270_STATUS saved_status = hSession->oia_status; + struct parms p = { sizeof(struct parms), host, portname, pport, sa, sa_len, errmsg, em_len }; + + trace("Calling resolver for %s", p.host); + + status_changed(hSession,LIB3270_STATUS_RESOLVING); + hSession->cursor(hSession,CURSOR_MODE_LOCKED); - Trace("Calling resolver for %s", p.host); + rc = lib3270_call_thread((int (*)(H3270 *, void *)) cresolve_host_and_port,hSession,&p); - rc = CallAndWait((int (*)(H3270 *, void *)) cresolve_host_and_port,&h3270,&p); + hSession->cursor(hSession,CURSOR_MODE_NORMAL); + status_changed(hSession,saved_status); - Trace("Calling resolver for %s exits with %d", p.host, rc); + trace("Calling resolver for %s exits with %d", p.host, rc); return rc; diff --git a/resolverc.h b/resolverc.h index 2cf79e5..c5c00cd 100644 --- a/resolverc.h +++ b/resolverc.h @@ -17,6 +17,6 @@ * Hostname resolution. */ -LIB3270_INTERNAL int resolve_host_and_port(const char *host, char *portname, unsigned short *pport,struct sockaddr *sa, socklen_t *sa_len, char *errmsg, int em_size); +LIB3270_INTERNAL int resolve_host_and_port(H3270 *session, const char *host, char *portname, unsigned short *pport,struct sockaddr *sa, socklen_t *sa_len, char *errmsg, int em_size); diff --git a/screen.c b/screen.c index f839a1a..ba0991b 100644 --- a/screen.c +++ b/screen.c @@ -443,14 +443,6 @@ void status_oerr(H3270 *session, int error_type) } -void status_resolving(H3270 *session, Boolean on) -{ - if(session->cursor) - session->cursor(session, on ? CURSOR_MODE_LOCKED : CURSOR_MODE_NORMAL); - - status_changed(session, on ? LIB3270_STATUS_RESOLVING : LIB3270_STATUS_BLANK); -} - void status_connecting(H3270 *session, Boolean on) { if(session->cursor) diff --git a/screen.h b/screen.h index 7c2dafc..8717769 100644 --- a/screen.h +++ b/screen.h @@ -21,5 +21,5 @@ LIB3270_INTERNAL int *char_width, *char_height; // LIB3270_INTERNAL void screen_update(H3270 *session, int bstart, int bend); LIB3270_INTERNAL void status_connecting(H3270 *session, Boolean on); -LIB3270_INTERNAL void status_resolving(H3270 *session, Boolean on); +// LIB3270_INTERNAL void status_resolving(H3270 *session, Boolean on); diff --git a/telnet.c b/telnet.c index b06a741..f1dcf65 100644 --- a/telnet.c +++ b/telnet.c @@ -417,6 +417,40 @@ void popup_a_sockerr(H3270 *session, char *fmt, ...) } +#pragma pack(1) +struct connect_parm +{ + unsigned short sz; + int sockfd; + const struct sockaddr * addr; + socklen_t addrlen; + int err; +}; +#pragma pack() + +static int do_connect_sock(H3270 *h, struct connect_parm *p) +{ + + if(connect(p->sockfd, p->addr, p->addrlen) == -1) + p->err = socket_errno(); + else + p->err = 0; + + return 0; +} + +static int connect_sock(H3270 *hSession, int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + struct connect_parm p = { sizeof(struct connect_parm), sockfd, addr, addrlen, -1 }; + + trace("%s: Connect begin sock=%d",__FUNCTION__,p.sockfd); + lib3270_call_thread((int (*)(H3270 *, void *)) do_connect_sock,hSession,&p); + trace("%s: Connect ends, rc=%d",__FUNCTION__,p.err); + + return p.err; +} + + /** * Establish a telnet socket to the given host passed as an argument. * @@ -425,18 +459,18 @@ void popup_a_sockerr(H3270 *session, char *fmt, ...) * * @param session Handle to the session descriptor. * - * * @return The file descriptor of the connected socket. */ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Boolean *resolving, Boolean *pending) { - struct servent *sp; - struct hostent *hp; - char passthru_haddr[8]; - int passthru_len = 0; - unsigned short passthru_port = 0; - int on = 1; - char errmsg[1024]; + struct servent * sp; + struct hostent * hp; + char passthru_haddr[8]; + int passthru_len = 0; + unsigned short passthru_port = 0; + int on = 1; + char errmsg[1024]; + int rc; #if defined(OMTU) /*[*/ int mtu = OMTU; #endif /*]*/ @@ -522,85 +556,109 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo haddr.sin.sin_port = passthru_port; ha_len = sizeof(struct sockaddr_in); } else if (proxy_type > 0) { - status_resolving(session,1); - if (resolve_host_and_port(proxy_host, proxy_portname, + if (resolve_host_and_port(&h3270,proxy_host, proxy_portname, &proxy_port, &haddr.sa, &ha_len, errmsg, sizeof(errmsg)) < 0) { popup_an_error(session,errmsg); - status_resolving(session,0); return -1; - status_resolving(session,0); } } else { - status_resolving(session,1); - if (resolve_host_and_port(host, portname, + if (resolve_host_and_port(&h3270,host, portname, &session->current_port, &haddr.sa, &ha_len, errmsg, sizeof(errmsg)) < 0) { popup_an_error(session,errmsg); - status_resolving(session,0); return -1; - status_resolving(session,0); } } /* create the socket */ - if ((session->sock = socket(haddr.sa.sa_family, SOCK_STREAM, 0)) == -1) { + if ((session->sock = socket(haddr.sa.sa_family, SOCK_STREAM, 0)) == -1) + { popup_a_sockerr(session, N_( "socket" ) ); return -1; } /* set options for inline out-of-band data and keepalives */ - if (setsockopt(session->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&on, - sizeof(on)) < 0) { + if (setsockopt(session->sock, SOL_SOCKET, SO_OOBINLINE, (char *)&on,sizeof(on)) < 0) + { popup_a_sockerr(session, N_( "setsockopt(%s)" ), "SO_OOBINLINE"); close_fail; } - if (setsockopt(session->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, - sizeof(on)) < 0) { + + if (setsockopt(session->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + { popup_a_sockerr(session, N_( "setsockopt(%s)" ), "SO_KEEPALIVE"); close_fail; } -#if defined(OMTU) /*[*/ + +#if defined(OMTU) if (setsockopt(session->sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,sizeof(mtu)) < 0) { popup_a_sockerr(session, N_( "setsockopt(%s)" ), "SO_SNDBUF"); close_fail; } -#endif /*]*/ +#endif /* set the socket to be non-delaying */ -#if defined(_WIN32) /*[*/ +#if defined(_WIN32) if (non_blocking(False) < 0) -#else /*][*/ +#else if (non_blocking(True) < 0) -#endif /*]*/ +#endif close_fail; -#if !defined(_WIN32) /*[*/ +#if !defined(_WIN32) /* don't share the socket with our children */ (void) fcntl(session->sock, F_SETFD, 1); -#endif /*]*/ +#endif /* init ssl */ -#if defined(HAVE_LIBSSL) /*[*/ +#if defined(HAVE_LIBSSL) last_ssl_error = 0; if (session->ssl_host) ssl_init(); -#endif /*]*/ +#endif /* connect */ status_connecting(session,1); - if (connect(session->sock, &haddr.sa, ha_len) == -1) { + + switch(connect_sock(session, session->sock, &haddr.sa,ha_len)) + { + case 0: // Connected + trace_dsn("Connected.\n"); + if(non_blocking(False) < 0) + close_fail; + net_connected(session); + break; + + case SE_EWOULDBLOCK: // Connection in progress + case SE_EINPROGRESS: + *pending = True; + trace_dsn("Connection pending.\n"); +#if !defined(_WIN32) + output_id = AddOutput(session->sock, session, output_possible); +#endif + break; + + default: + popup_a_sockerr(session, N_( "Can't connect to %s:%d" ),session->hostname, session->current_port); + close_fail; + + } + +/* + if (connect(session->sock, &haddr.sa, ha_len) == -1) + { if (socket_errno() == SE_EWOULDBLOCK -#if defined(SE_EINPROGRESS) /*[*/ +#if defined(SE_EINPROGRESS) || socket_errno() == SE_EINPROGRESS -#endif /*]*/ +#endif ) { trace_dsn("Connection pending.\n"); *pending = True; -#if !defined(_WIN32) /*[*/ +#if !defined(_WIN32) output_id = AddOutput(session->sock, session, output_possible); -#endif /*]*/ +#endif } else { popup_a_sockerr(session, N_( "Can't connect to %s:%d" ),session->hostname, session->current_port); close_fail; @@ -610,6 +668,7 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo close_fail; net_connected(session); } + */ /* set up temporary termtype */ if (appres.termname == CN && session->std_ds_host) { @@ -821,10 +880,12 @@ connection_complete(void) */ static void output_possible(H3270 *session) { + trace("%s: %s",HALF_CONNECTED ? "Half connected" : "Connected"); if (HALF_CONNECTED) { connection_complete(); } + if (output_id) { RemoveInput(output_id); @@ -3163,8 +3224,7 @@ non_blocking(Boolean on) #if defined(HAVE_LIBSSL) /*[*/ /* Initialize the OpenSSL library. */ -static void -ssl_init(void) +static void ssl_init(void) { static Boolean ssl_initted = False; -- libgit2 0.21.2