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 125  
126 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 131 if (IN_ANSI && lib3270_get_toggle(hSession,LIB3270_TOGGLE_SCREEN_TRACE))
137 132 trace_ansi_disc(hSession);
138   -#endif /*]*/
139 133  
140 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 149 return 0;
143 150  
144 151 }
... ...
src/core/popup.c
... ... @@ -38,6 +38,7 @@
38 38 #include <internals.h>
39 39 #include <lib3270.h>
40 40 #include <lib3270/log.h>
  41 +#include <networking.h>
41 42  
42 43 /*--[ Implement ]------------------------------------------------------------------------------------*/
43 44  
... ... @@ -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 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 72 const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) {
65 73  
66 74 static const LIB3270_UINT_PROPERTY properties[] = {
... ... @@ -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 151 .name = "unlock_delay", // Property name.
136 152 .group = LIB3270_ACTION_GROUP_OFFLINE, // Property group.
137 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 287 hSession->model_num = -1;
288 288 hSession->connection.state = LIB3270_NOT_CONNECTED;
289 289 hSession->connection.timeout = 10000;
  290 + hSession->connection.retry = 5000;
290 291 hSession->oia.status = LIB3270_MESSAGE_DISCONNECTED;
291 292 hSession->kybdlock = KL_NOT_CONNECTED;
292 293 hSession->aid = AID_NO;
... ... @@ -485,7 +486,8 @@ LIB3270_EXPORT char lib3270_get_session_id(H3270 *hSession) {
485 486 }
486 487  
487 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 492 if(revision && strcasecmp(revision,REQUIRED_REVISION) < 0) {
491 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 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 114 #undef X3270_MENUS
115 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 121 * @brief types of internal actions
... ... @@ -310,6 +310,8 @@ struct _h3270 {
310 310 struct {
311 311 LIB3270_CSTATE state; ///< @brief Connection state.
312 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 315 } connection;
314 316  
315 317 // flags
... ...
src/include/lib3270/properties.h
... ... @@ -282,6 +282,20 @@ LIB3270_EXPORT const char * lib3270_service_get_name(const H3270 *h);
282 282 */
283 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 299 #ifdef __cplusplus
286 300 }
287 301 #endif
... ...
src/include/lib3270/toggle.h
... ... @@ -54,7 +54,6 @@ typedef enum _lib3270_toggle_id {
54 54 LIB3270_TOGGLE_RECTANGLE_SELECT,
55 55 LIB3270_TOGGLE_CROSSHAIR,
56 56 LIB3270_TOGGLE_FULL_SCREEN,
57   - LIB3270_TOGGLE_RECONNECT,
58 57 LIB3270_TOGGLE_INSERT,
59 58 LIB3270_TOGGLE_SMART_PASTE,
60 59 LIB3270_TOGGLE_BOLD,
... ... @@ -69,6 +68,8 @@ typedef enum _lib3270_toggle_id {
69 68 LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */
70 69 LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */
71 70  
  71 + LIB3270_TOGGLE_RECONNECT, /**< @brief Auto reconnect */
  72 +
72 73 LIB3270_TOGGLE_COUNT
73 74  
74 75 } LIB3270_TOGGLE_ID;
... ...
src/include/networking.h
... ... @@ -188,6 +188,12 @@ typedef struct lib3270_net_module {
188 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 197 * @brief Connect to host, returns a connected socket.
192 198 *
193 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 94  
95 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 99 _("Disconnected from host."),
102 100 "%s",
103 101 _("The secure connection has been closed cleanly.")
104 102 );
  103 +
105 104 return 0;
106 105  
107 106 case SSL_ERROR_WANT_READ:
... ... @@ -118,14 +117,12 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length)
118 117 (void) ERR_error_string(ssl_error, err_buf);
119 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 127 return -1;
131 128  
... ... @@ -145,10 +142,8 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
145 142  
146 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 147 _("Disconnected from host."),
153 148 "%s",
154 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 164 (void) ERR_error_string(ssl_error, err_buf);
170 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 174 return -1;
182 175 }
... ...
src/network_modules/tools.c
... ... @@ -59,15 +59,14 @@ int lib3270_socket_recv_failed(H3270 *hSession) {
59 59  
60 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 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 71 #else
73 72  
... ... @@ -78,20 +77,13 @@ int lib3270_socket_recv_failed(H3270 *hSession) {
78 77 // Network error, notify user
79 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 88 #endif // _WIN32
97 89  
... ... @@ -105,14 +97,11 @@ int lib3270_socket_send_failed(H3270 *hSession) {
105 97  
106 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 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 107 #else
... ... @@ -121,24 +110,20 @@ int lib3270_socket_send_failed(H3270 *hSession) {
121 110  
122 111 switch(rc) {
123 112 case EPIPE:
124   - lib3270_popup_dialog(
125   - hSession,
126   - LIB3270_NOTIFY_ERROR,
127   - NULL,
  113 + lib3270_set_network_error(
  114 + hSession,
128 115 _("Broken pipe"),
129   - _("The system error code was %d"),
130   - rc
  116 + _("The system error code was %d"),
  117 + rc
131 118 );
132 119 break;
133 120  
134 121 case ECONNRESET:
135   - lib3270_popup_dialog(
136   - hSession,
137   - LIB3270_NOTIFY_ERROR,
138   - NULL,
  122 + lib3270_set_network_error(
  123 + hSession,
139 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 128 break;
144 129  
... ... @@ -146,10 +131,8 @@ int lib3270_socket_send_failed(H3270 *hSession) {
146 131 return 0;
147 132  
148 133 default:
149   - lib3270_popup_dialog(
150   - hSession,
151   - LIB3270_NOTIFY_ERROR,
152   - NULL,
  134 + lib3270_set_network_error(
  135 + hSession,
153 136 _("Unexpected error writing to network socket"),
154 137 _("The system error code was %d (%s)"),
155 138 rc, strerror(rc)
... ... @@ -157,7 +140,6 @@ int lib3270_socket_send_failed(H3270 *hSession) {
157 140  
158 141 }
159 142  
160   -
161 143 #endif // _WIN32
162 144  
163 145 return -1;
... ...