Commit cf645ade7233158b0ebafdf8227519cd533664fc

Authored by Perry Werneck
1 parent 87ed2906
Exists in master and in 2 other branches develop, macos

Working on 'hang' when the ssl negotiation fails.

src/core/host.c
@@ -125,20 +125,27 @@ int host_disconnect(H3270 *hSession, int failed) { @@ -125,20 +125,27 @@ int host_disconnect(H3270 *hSession, int failed) {
125 125
126 trace("Disconnected (Failed: %d Reconnect: %d in_progress: %d)",failed,lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT),hSession->auto_reconnect_inprogress); 126 trace("Disconnected (Failed: %d Reconnect: %d in_progress: %d)",failed,lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT),hSession->auto_reconnect_inprogress);
127 127
128 - if(failed && lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT))  
129 - lib3270_activate_auto_reconnect(hSession,failed ? RECONNECT_ERR_MS : RECONNECT_MS);  
130 -  
131 - /*  
132 - * Remember a disconnect from ANSI mode, to keep screen tracing  
133 - * in sync.  
134 - */  
135 -#if defined(X3270_TRACE) /*[*/ 128 + //
  129 + // Remember a disconnect from ANSI mode, to keep screen tracing in sync.
  130 + //
136 if (IN_ANSI && lib3270_get_toggle(hSession,LIB3270_TOGGLE_SCREEN_TRACE)) 131 if (IN_ANSI && lib3270_get_toggle(hSession,LIB3270_TOGGLE_SCREEN_TRACE))
137 trace_ansi_disc(hSession); 132 trace_ansi_disc(hSession);
138 -#endif /*]*/  
139 133
140 lib3270_set_disconnected(hSession); 134 lib3270_set_disconnected(hSession);
141 135
  136 + if(hSession->connection.error) {
  137 +
  138 + // TODO: Add 'reconnect' option in the popup dialog for optional auto reconnect.
  139 + lib3270_popup(hSession,hSession->connection.error,!hSession->auto_reconnect_inprogress);
  140 +
  141 + lib3270_free(hSession->connection.error);
  142 + hSession->connection.error = NULL;
  143 +
  144 + }
  145 +
  146 + if(failed && hSession->connection.retry && lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT))
  147 + lib3270_activate_auto_reconnect(hSession,hSession->connection.retry);
  148 +
142 return 0; 149 return 0;
143 150
144 } 151 }
src/core/popup.c
@@ -38,6 +38,7 @@ @@ -38,6 +38,7 @@
38 #include <internals.h> 38 #include <internals.h>
39 #include <lib3270.h> 39 #include <lib3270.h>
40 #include <lib3270/log.h> 40 #include <lib3270/log.h>
  41 +#include <networking.h>
41 42
42 /*--[ Implement ]------------------------------------------------------------------------------------*/ 43 /*--[ Implement ]------------------------------------------------------------------------------------*/
43 44
@@ -191,3 +192,33 @@ LIB3270_EXPORT void lib3270_set_popup_handler(H3270 *hSession, int (*handler)(H3 @@ -191,3 +192,33 @@ LIB3270_EXPORT void lib3270_set_popup_handler(H3270 *hSession, int (*handler)(H3
191 192
192 193
193 } 194 }
  195 +
  196 +void lib3270_set_network_error(H3270 *hSession, const char *summary, const char *fmt, ...) {
  197 +
  198 + // Release last error.
  199 + if(hSession->connection.error) {
  200 + lib3270_free(hSession->connection.error);
  201 + hSession->connection.error = NULL;
  202 + }
  203 +
  204 + // Format body.
  205 + va_list args;
  206 + va_start(args, fmt);
  207 + lib3270_autoptr(char) body = lib3270_vsprintf(fmt, args);
  208 + va_end(args);
  209 +
  210 + hSession->connection.error = lib3270_malloc(sizeof(LIB3270_POPUP) + strlen(summary) + strlen(body) + 3);
  211 +
  212 + // Set type.
  213 + hSession->connection.error->type = LIB3270_NOTIFY_ERROR;
  214 +
  215 + // Copy summary
  216 + hSession->connection.error->summary = (char *) (hSession->connection.error + 1);
  217 + strcpy((char *) hSession->connection.error->summary,summary);
  218 +
  219 + // Copy body.
  220 + hSession->connection.error->body = hSession->connection.error->summary + strlen(hSession->connection.error->summary) + 1;
  221 + strcpy((char *) hSession->connection.error->body,body);
  222 +
  223 +}
  224 +
src/core/properties/unsigned.c
@@ -61,6 +61,14 @@ static unsigned int lib3270_get_host_type_number(const H3270 *hSession) { @@ -61,6 +61,14 @@ static unsigned int lib3270_get_host_type_number(const H3270 *hSession) {
61 return (unsigned int) hSession->host_type; 61 return (unsigned int) hSession->host_type;
62 } 62 }
63 63
  64 +LIB3270_EXPORT unsigned int lib3270_get_auto_reconnect(const H3270 *hSession) {
  65 + return hSession->connection.retry;
  66 +}
  67 +
  68 +LIB3270_EXPORT int lib3270_set_auto_reconnect(H3270 *hSession, unsigned int timer) {
  69 + hSession->connection.retry = timer;
  70 +}
  71 +
64 const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) { 72 const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) {
65 73
66 static const LIB3270_UINT_PROPERTY properties[] = { 74 static const LIB3270_UINT_PROPERTY properties[] = {
@@ -132,6 +140,14 @@ const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) { @@ -132,6 +140,14 @@ const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) {
132 }, 140 },
133 141
134 { 142 {
  143 + .name = "auto_reconnect", // Property name.
  144 + .default_value = 5000, // Default value for the property.
  145 + .description = N_( "Time for auto-reconnect" ), // Property description.
  146 + .get = lib3270_get_auto_reconnect, // Get value.
  147 + .set = lib3270_set_auto_reconnect // Set value.
  148 + },
  149 +
  150 + {
135 .name = "unlock_delay", // Property name. 151 .name = "unlock_delay", // Property name.
136 .group = LIB3270_ACTION_GROUP_OFFLINE, // Property group. 152 .group = LIB3270_ACTION_GROUP_OFFLINE, // Property group.
137 #ifdef UNLOCK_MS 153 #ifdef UNLOCK_MS
src/core/session.c
@@ -287,6 +287,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char @@ -287,6 +287,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char
287 hSession->model_num = -1; 287 hSession->model_num = -1;
288 hSession->connection.state = LIB3270_NOT_CONNECTED; 288 hSession->connection.state = LIB3270_NOT_CONNECTED;
289 hSession->connection.timeout = 10000; 289 hSession->connection.timeout = 10000;
  290 + hSession->connection.retry = 5000;
290 hSession->oia.status = LIB3270_MESSAGE_DISCONNECTED; 291 hSession->oia.status = LIB3270_MESSAGE_DISCONNECTED;
291 hSession->kybdlock = KL_NOT_CONNECTED; 292 hSession->kybdlock = KL_NOT_CONNECTED;
292 hSession->aid = AID_NO; 293 hSession->aid = AID_NO;
@@ -485,7 +486,8 @@ LIB3270_EXPORT char lib3270_get_session_id(H3270 *hSession) { @@ -485,7 +486,8 @@ LIB3270_EXPORT char lib3270_get_session_id(H3270 *hSession) {
485 } 486 }
486 487
487 struct lib3270_session_callbacks * lib3270_get_session_callbacks(H3270 *hSession, const char *revision, unsigned short sz) { 488 struct lib3270_session_callbacks * lib3270_get_session_callbacks(H3270 *hSession, const char *revision, unsigned short sz) {
488 -#define REQUIRED_REVISION "20201117" 489 +
  490 + #define REQUIRED_REVISION "20210619"
489 491
490 if(revision && strcasecmp(revision,REQUIRED_REVISION) < 0) { 492 if(revision && strcasecmp(revision,REQUIRED_REVISION) < 0) {
491 errno = EINVAL; 493 errno = EINVAL;
src/core/toggles/getset.c
@@ -68,13 +68,6 @@ static void toggle_notify(H3270 *session, struct lib3270_toggle *t, LIB3270_TOGG @@ -68,13 +68,6 @@ static void toggle_notify(H3270 *session, struct lib3270_toggle *t, LIB3270_TOGG
68 ((struct lib3270_toggle_callback *) node)->func(session, ix, t->value, node->userdata); 68 ((struct lib3270_toggle_callback *) node)->func(session, ix, t->value, node->userdata);
69 } 69 }
70 70
71 - /*  
72 - for(st = session->listeners.toggle.callbacks[ix]; st != (struct lib3270_toggle_callback *) NULL; st = (struct lib3270_toggle_callback *) st->next)  
73 - {  
74 - st->func(session, ix, t->value, st->data);  
75 - }  
76 - */  
77 -  
78 } 71 }
79 72
80 /** 73 /**
src/include/internals.h
@@ -114,8 +114,8 @@ @@ -114,8 +114,8 @@
114 #undef X3270_MENUS 114 #undef X3270_MENUS
115 #endif /*]*/ 115 #endif /*]*/
116 116
117 -#define RECONNECT_MS 2000 /**< @brief 2 sec before reconnecting to host. */  
118 -#define RECONNECT_ERR_MS 5000 /**< @brief 5 sec before reconnecting to host when failed */ 117 +//#define RECONNECT_MS 2000 /**< @brief 2 sec before reconnecting to host. */
  118 +//#define RECONNECT_ERR_MS 5000 /**< @brief 5 sec before reconnecting to host when failed */
119 119
120 /** 120 /**
121 * @brief types of internal actions 121 * @brief types of internal actions
@@ -310,6 +310,8 @@ struct _h3270 { @@ -310,6 +310,8 @@ struct _h3270 {
310 struct { 310 struct {
311 LIB3270_CSTATE state; ///< @brief Connection state. 311 LIB3270_CSTATE state; ///< @brief Connection state.
312 unsigned int timeout; ///< @brief Connection timeout (1000 = 1s) 312 unsigned int timeout; ///< @brief Connection timeout (1000 = 1s)
  313 + unsigned int retry; ///< @brief Time to retry when connection ends with error.
  314 + LIB3270_POPUP * error; ///< @brief Last connection error.
313 } connection; 315 } connection;
314 316
315 // flags 317 // flags
src/include/lib3270/properties.h
@@ -282,6 +282,20 @@ LIB3270_EXPORT const char * lib3270_service_get_name(const H3270 *h); @@ -282,6 +282,20 @@ LIB3270_EXPORT const char * lib3270_service_get_name(const H3270 *h);
282 */ 282 */
283 LIB3270_EXPORT unsigned int lib3270_get_task_count(const H3270 *h); 283 LIB3270_EXPORT unsigned int lib3270_get_task_count(const H3270 *h);
284 284
  285 +/**
  286 + * @brief Set timer for auto-reconnect when connection fails.
  287 + *
  288 + * @param hSession Session handle.
  289 + */
  290 +LIB3270_EXPORT int lib3270_set_auto_reconnect(H3270 *hSession, unsigned int timer);
  291 +
  292 +/**
  293 + * @brief Get timer for auto-reconnect when connection fails.
  294 + *
  295 + * @param hSession Session handle.
  296 + */
  297 +LIB3270_EXPORT unsigned int lib3270_get_auto_reconnect(const H3270 *hSession);
  298 +
285 #ifdef __cplusplus 299 #ifdef __cplusplus
286 } 300 }
287 #endif 301 #endif
src/include/lib3270/toggle.h
@@ -54,7 +54,6 @@ typedef enum _lib3270_toggle_id { @@ -54,7 +54,6 @@ typedef enum _lib3270_toggle_id {
54 LIB3270_TOGGLE_RECTANGLE_SELECT, 54 LIB3270_TOGGLE_RECTANGLE_SELECT,
55 LIB3270_TOGGLE_CROSSHAIR, 55 LIB3270_TOGGLE_CROSSHAIR,
56 LIB3270_TOGGLE_FULL_SCREEN, 56 LIB3270_TOGGLE_FULL_SCREEN,
57 - LIB3270_TOGGLE_RECONNECT,  
58 LIB3270_TOGGLE_INSERT, 57 LIB3270_TOGGLE_INSERT,
59 LIB3270_TOGGLE_SMART_PASTE, 58 LIB3270_TOGGLE_SMART_PASTE,
60 LIB3270_TOGGLE_BOLD, 59 LIB3270_TOGGLE_BOLD,
@@ -69,6 +68,8 @@ typedef enum _lib3270_toggle_id { @@ -69,6 +68,8 @@ typedef enum _lib3270_toggle_id {
69 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */ 68 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */
70 LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */ 69 LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */
71 70
  71 + LIB3270_TOGGLE_RECONNECT, /**< @brief Auto reconnect */
  72 +
72 LIB3270_TOGGLE_COUNT 73 LIB3270_TOGGLE_COUNT
73 74
74 } LIB3270_TOGGLE_ID; 75 } LIB3270_TOGGLE_ID;
src/include/networking.h
@@ -188,6 +188,12 @@ typedef struct lib3270_net_module { @@ -188,6 +188,12 @@ typedef struct lib3270_net_module {
188 LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession); 188 LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession);
189 189
190 /** 190 /**
  191 + * @brief Set network error message.
  192 + *
  193 + */
  194 +LIB3270_INTERNAL void lib3270_set_network_error(H3270 *hSession,const char *summary, const char *fmt, ...);
  195 +
  196 +/**
191 * @brief Connect to host, returns a connected socket. 197 * @brief Connect to host, returns a connected socket.
192 * 198 *
193 * @param hSession Disconnected TN3270 session. 199 * @param hSession Disconnected TN3270 session.
src/network_modules/openssl/main.c
@@ -94,14 +94,13 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) @@ -94,14 +94,13 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length)
94 94
95 trace_ssl(hSession,"%s","The secure connection has been closed cleanly"); 95 trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
96 96
97 - lib3270_popup_dialog(  
98 - hSession,  
99 - LIB3270_NOTIFY_ERROR,  
100 - NULL, 97 + lib3270_set_network_error(
  98 + hSession,
101 _("Disconnected from host."), 99 _("Disconnected from host."),
102 "%s", 100 "%s",
103 _("The secure connection has been closed cleanly.") 101 _("The secure connection has been closed cleanly.")
104 ); 102 );
  103 +
105 return 0; 104 return 0;
106 105
107 case SSL_ERROR_WANT_READ: 106 case SSL_ERROR_WANT_READ:
@@ -118,14 +117,12 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) @@ -118,14 +117,12 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length)
118 (void) ERR_error_string(ssl_error, err_buf); 117 (void) ERR_error_string(ssl_error, err_buf);
119 trace_dsn(hSession,"RCVD SSL_write error %d (%s)\n", ssl_error, err_buf); 118 trace_dsn(hSession,"RCVD SSL_write error %d (%s)\n", ssl_error, err_buf);
120 119
121 - lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf);  
122 -  
123 - LIB3270_POPUP popup = {  
124 - .summary = _("Error writing to host"),  
125 - .body = body  
126 - };  
127 -  
128 - lib3270_popup(hSession,&popup,0); 120 + lib3270_set_network_error(
  121 + hSession,
  122 + _("Error writing to host."),
  123 + _("The SSL error message was %s"),
  124 + err_buf
  125 + );
129 126
130 return -1; 127 return -1;
131 128
@@ -145,10 +142,8 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) { @@ -145,10 +142,8 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
145 142
146 trace_ssl(hSession,"%s","The secure connection has been closed cleanly"); 143 trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
147 144
148 - lib3270_popup_dialog(  
149 - hSession,  
150 - LIB3270_NOTIFY_ERROR,  
151 - NULL, 145 + lib3270_set_network_error(
  146 + hSession,
152 _("Disconnected from host."), 147 _("Disconnected from host."),
153 "%s", 148 "%s",
154 _("The secure connection has been closed cleanly.") 149 _("The secure connection has been closed cleanly.")
@@ -169,14 +164,12 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) { @@ -169,14 +164,12 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
169 (void) ERR_error_string(ssl_error, err_buf); 164 (void) ERR_error_string(ssl_error, err_buf);
170 trace_dsn(hSession,"RCVD SSL_read error %d (%s)\n", ssl_error, err_buf); 165 trace_dsn(hSession,"RCVD SSL_read error %d (%s)\n", ssl_error, err_buf);
171 166
172 - lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf);  
173 -  
174 - LIB3270_POPUP popup = {  
175 - .summary = _("Error reading from host"),  
176 - .body = body  
177 - };  
178 -  
179 - lib3270_popup(hSession,&popup,0); 167 + lib3270_set_network_error(
  168 + hSession,
  169 + _("Error reading from host"),
  170 + _("The SSL error message was %s"),
  171 + err_buf
  172 + );
180 173
181 return -1; 174 return -1;
182 } 175 }
src/network_modules/tools.c
@@ -59,15 +59,14 @@ int lib3270_socket_recv_failed(H3270 *hSession) { @@ -59,15 +59,14 @@ int lib3270_socket_recv_failed(H3270 *hSession) {
59 59
60 int rc = -wsaError; 60 int rc = -wsaError;
61 61
62 - LIB3270_POPUP popup = {  
63 - .name = "RecvFailed",  
64 - .type = LIB3270_NOTIFY_ERROR,  
65 - .summary = _("Error receiving data from host"),  
66 - };  
67 -  
68 // TODO: Translate WSA Error, update message body. 62 // TODO: Translate WSA Error, update message body.
69 63
70 - lib3270_popup(hSession,&popup,0); 64 + lib3270_set_network_error(
  65 + hSession,
  66 + _("Error receiving data from host"),
  67 + _("The windows error code was %u"),
  68 + (unsigned int) wsaError
  69 + );
71 70
72 #else 71 #else
73 72
@@ -78,20 +77,13 @@ int lib3270_socket_recv_failed(H3270 *hSession) { @@ -78,20 +77,13 @@ int lib3270_socket_recv_failed(H3270 *hSession) {
78 // Network error, notify user 77 // Network error, notify user
79 int rc = -errno; 78 int rc = -errno;
80 79
81 - lib3270_autoptr(char) body = lib3270_strdup_printf(  
82 - _("The system error code was %d (%s)"),  
83 - errno,  
84 - strerror(errno)  
85 - );  
86 -  
87 - LIB3270_POPUP popup = {  
88 - .name = "RecvFailed",  
89 - .type = LIB3270_NOTIFY_ERROR,  
90 - .summary = _("Error receiving data from host"),  
91 - .body = body  
92 - };  
93 -  
94 - lib3270_popup(hSession,&popup,0); 80 + lib3270_set_network_error(
  81 + hSession,
  82 + _("Error receiving data from host"),
  83 + _("The system error code was %d (%s)"),
  84 + errno,
  85 + strerror(errno)
  86 + );
95 87
96 #endif // _WIN32 88 #endif // _WIN32
97 89
@@ -105,14 +97,11 @@ int lib3270_socket_send_failed(H3270 *hSession) { @@ -105,14 +97,11 @@ int lib3270_socket_send_failed(H3270 *hSession) {
105 97
106 int rc = WSAGetLastError(); 98 int rc = WSAGetLastError();
107 99
108 - lib3270_popup_dialog(  
109 - hSession,  
110 - LIB3270_NOTIFY_ERROR,  
111 - NULL, 100 + lib3270_set_network_error(
  101 + hSession,
112 _("Erro sending data to host"), 102 _("Erro sending data to host"),
113 - _( "The system error was %s (%d)" ),  
114 - lib3270_win32_strerror(rc),  
115 - rc 103 + _("The windows error code was %u"),
  104 + (unsigned int) wsaError
116 ); 105 );
117 106
118 #else 107 #else
@@ -121,24 +110,20 @@ int lib3270_socket_send_failed(H3270 *hSession) { @@ -121,24 +110,20 @@ int lib3270_socket_send_failed(H3270 *hSession) {
121 110
122 switch(rc) { 111 switch(rc) {
123 case EPIPE: 112 case EPIPE:
124 - lib3270_popup_dialog(  
125 - hSession,  
126 - LIB3270_NOTIFY_ERROR,  
127 - NULL, 113 + lib3270_set_network_error(
  114 + hSession,
128 _("Broken pipe"), 115 _("Broken pipe"),
129 - _("The system error code was %d"),  
130 - rc 116 + _("The system error code was %d"),
  117 + rc
131 ); 118 );
132 break; 119 break;
133 120
134 case ECONNRESET: 121 case ECONNRESET:
135 - lib3270_popup_dialog(  
136 - hSession,  
137 - LIB3270_NOTIFY_ERROR,  
138 - NULL, 122 + lib3270_set_network_error(
  123 + hSession,
139 _("Connection reset by peer"), 124 _("Connection reset by peer"),
140 - _("The system error code was %d"),  
141 - rc 125 + _("The system error code was %d"),
  126 + rc
142 ); 127 );
143 break; 128 break;
144 129
@@ -146,10 +131,8 @@ int lib3270_socket_send_failed(H3270 *hSession) { @@ -146,10 +131,8 @@ int lib3270_socket_send_failed(H3270 *hSession) {
146 return 0; 131 return 0;
147 132
148 default: 133 default:
149 - lib3270_popup_dialog(  
150 - hSession,  
151 - LIB3270_NOTIFY_ERROR,  
152 - NULL, 134 + lib3270_set_network_error(
  135 + hSession,
153 _("Unexpected error writing to network socket"), 136 _("Unexpected error writing to network socket"),
154 _("The system error code was %d (%s)"), 137 _("The system error code was %d (%s)"),
155 rc, strerror(rc) 138 rc, strerror(rc)
@@ -157,7 +140,6 @@ int lib3270_socket_send_failed(H3270 *hSession) { @@ -157,7 +140,6 @@ int lib3270_socket_send_failed(H3270 *hSession) {
157 140
158 } 141 }
159 142
160 -  
161 #endif // _WIN32 143 #endif // _WIN32
162 144
163 return -1; 145 return -1;