Commit cf645ade7233158b0ebafdf8227519cd533664fc
1 parent
87ed2906
Exists in
master
and in
2 other branches
Working on 'hang' when the ssl negotiation fails.
Showing
11 changed files
with
136 additions
and
89 deletions
Show diff stats
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; | ... | ... |