diff --git a/src/core/host.c b/src/core/host.c index 95849b3..123f5ed 100644 --- a/src/core/host.c +++ b/src/core/host.c @@ -125,20 +125,27 @@ int host_disconnect(H3270 *hSession, int failed) { trace("Disconnected (Failed: %d Reconnect: %d in_progress: %d)",failed,lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT),hSession->auto_reconnect_inprogress); - if(failed && lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT)) - lib3270_activate_auto_reconnect(hSession,failed ? RECONNECT_ERR_MS : RECONNECT_MS); - - /* - * Remember a disconnect from ANSI mode, to keep screen tracing - * in sync. - */ -#if defined(X3270_TRACE) /*[*/ + // + // Remember a disconnect from ANSI mode, to keep screen tracing in sync. + // if (IN_ANSI && lib3270_get_toggle(hSession,LIB3270_TOGGLE_SCREEN_TRACE)) trace_ansi_disc(hSession); -#endif /*]*/ lib3270_set_disconnected(hSession); + if(hSession->connection.error) { + + // TODO: Add 'reconnect' option in the popup dialog for optional auto reconnect. + lib3270_popup(hSession,hSession->connection.error,!hSession->auto_reconnect_inprogress); + + lib3270_free(hSession->connection.error); + hSession->connection.error = NULL; + + } + + if(failed && hSession->connection.retry && lib3270_get_toggle(hSession,LIB3270_TOGGLE_RECONNECT)) + lib3270_activate_auto_reconnect(hSession,hSession->connection.retry); + return 0; } diff --git a/src/core/popup.c b/src/core/popup.c index cbe92ff..3300e29 100644 --- a/src/core/popup.c +++ b/src/core/popup.c @@ -38,6 +38,7 @@ #include #include #include +#include /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -191,3 +192,33 @@ LIB3270_EXPORT void lib3270_set_popup_handler(H3270 *hSession, int (*handler)(H3 } + +void lib3270_set_network_error(H3270 *hSession, const char *summary, const char *fmt, ...) { + + // Release last error. + if(hSession->connection.error) { + lib3270_free(hSession->connection.error); + hSession->connection.error = NULL; + } + + // Format body. + va_list args; + va_start(args, fmt); + lib3270_autoptr(char) body = lib3270_vsprintf(fmt, args); + va_end(args); + + hSession->connection.error = lib3270_malloc(sizeof(LIB3270_POPUP) + strlen(summary) + strlen(body) + 3); + + // Set type. + hSession->connection.error->type = LIB3270_NOTIFY_ERROR; + + // Copy summary + hSession->connection.error->summary = (char *) (hSession->connection.error + 1); + strcpy((char *) hSession->connection.error->summary,summary); + + // Copy body. + hSession->connection.error->body = hSession->connection.error->summary + strlen(hSession->connection.error->summary) + 1; + strcpy((char *) hSession->connection.error->body,body); + +} + diff --git a/src/core/properties/unsigned.c b/src/core/properties/unsigned.c index 9688e81..bad8d94 100644 --- a/src/core/properties/unsigned.c +++ b/src/core/properties/unsigned.c @@ -61,6 +61,14 @@ static unsigned int lib3270_get_host_type_number(const H3270 *hSession) { return (unsigned int) hSession->host_type; } +LIB3270_EXPORT unsigned int lib3270_get_auto_reconnect(const H3270 *hSession) { + return hSession->connection.retry; +} + +LIB3270_EXPORT int lib3270_set_auto_reconnect(H3270 *hSession, unsigned int timer) { + hSession->connection.retry = timer; +} + const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) { static const LIB3270_UINT_PROPERTY properties[] = { @@ -132,6 +140,14 @@ const LIB3270_UINT_PROPERTY * lib3270_get_unsigned_properties_list(void) { }, { + .name = "auto_reconnect", // Property name. + .default_value = 5000, // Default value for the property. + .description = N_( "Time for auto-reconnect" ), // Property description. + .get = lib3270_get_auto_reconnect, // Get value. + .set = lib3270_set_auto_reconnect // Set value. + }, + + { .name = "unlock_delay", // Property name. .group = LIB3270_ACTION_GROUP_OFFLINE, // Property group. #ifdef UNLOCK_MS diff --git a/src/core/session.c b/src/core/session.c index 2c3a1be..117d883 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -287,6 +287,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char hSession->model_num = -1; hSession->connection.state = LIB3270_NOT_CONNECTED; hSession->connection.timeout = 10000; + hSession->connection.retry = 5000; hSession->oia.status = LIB3270_MESSAGE_DISCONNECTED; hSession->kybdlock = KL_NOT_CONNECTED; hSession->aid = AID_NO; @@ -485,7 +486,8 @@ LIB3270_EXPORT char lib3270_get_session_id(H3270 *hSession) { } struct lib3270_session_callbacks * lib3270_get_session_callbacks(H3270 *hSession, const char *revision, unsigned short sz) { -#define REQUIRED_REVISION "20201117" + + #define REQUIRED_REVISION "20210619" if(revision && strcasecmp(revision,REQUIRED_REVISION) < 0) { errno = EINVAL; diff --git a/src/core/toggles/getset.c b/src/core/toggles/getset.c index 0cb8a31..d623da0 100644 --- a/src/core/toggles/getset.c +++ b/src/core/toggles/getset.c @@ -68,13 +68,6 @@ static void toggle_notify(H3270 *session, struct lib3270_toggle *t, LIB3270_TOGG ((struct lib3270_toggle_callback *) node)->func(session, ix, t->value, node->userdata); } - /* - for(st = session->listeners.toggle.callbacks[ix]; st != (struct lib3270_toggle_callback *) NULL; st = (struct lib3270_toggle_callback *) st->next) - { - st->func(session, ix, t->value, st->data); - } - */ - } /** diff --git a/src/include/internals.h b/src/include/internals.h index c5f56d1..c7cfb22 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -114,8 +114,8 @@ #undef X3270_MENUS #endif /*]*/ -#define RECONNECT_MS 2000 /**< @brief 2 sec before reconnecting to host. */ -#define RECONNECT_ERR_MS 5000 /**< @brief 5 sec before reconnecting to host when failed */ +//#define RECONNECT_MS 2000 /**< @brief 2 sec before reconnecting to host. */ +//#define RECONNECT_ERR_MS 5000 /**< @brief 5 sec before reconnecting to host when failed */ /** * @brief types of internal actions @@ -310,6 +310,8 @@ struct _h3270 { struct { LIB3270_CSTATE state; ///< @brief Connection state. unsigned int timeout; ///< @brief Connection timeout (1000 = 1s) + unsigned int retry; ///< @brief Time to retry when connection ends with error. + LIB3270_POPUP * error; ///< @brief Last connection error. } connection; // flags diff --git a/src/include/lib3270/properties.h b/src/include/lib3270/properties.h index 3eccf5e..55777a4 100644 --- a/src/include/lib3270/properties.h +++ b/src/include/lib3270/properties.h @@ -282,6 +282,20 @@ LIB3270_EXPORT const char * lib3270_service_get_name(const H3270 *h); */ LIB3270_EXPORT unsigned int lib3270_get_task_count(const H3270 *h); +/** + * @brief Set timer for auto-reconnect when connection fails. + * + * @param hSession Session handle. + */ +LIB3270_EXPORT int lib3270_set_auto_reconnect(H3270 *hSession, unsigned int timer); + +/** + * @brief Get timer for auto-reconnect when connection fails. + * + * @param hSession Session handle. + */ +LIB3270_EXPORT unsigned int lib3270_get_auto_reconnect(const H3270 *hSession); + #ifdef __cplusplus } #endif diff --git a/src/include/lib3270/toggle.h b/src/include/lib3270/toggle.h index d374005..ab9f361 100644 --- a/src/include/lib3270/toggle.h +++ b/src/include/lib3270/toggle.h @@ -54,7 +54,6 @@ typedef enum _lib3270_toggle_id { LIB3270_TOGGLE_RECTANGLE_SELECT, LIB3270_TOGGLE_CROSSHAIR, LIB3270_TOGGLE_FULL_SCREEN, - LIB3270_TOGGLE_RECONNECT, LIB3270_TOGGLE_INSERT, LIB3270_TOGGLE_SMART_PASTE, LIB3270_TOGGLE_BOLD, @@ -69,6 +68,8 @@ typedef enum _lib3270_toggle_id { LIB3270_TOGGLE_NETWORK_TRACE, /**< @brief Enable network in/out trace */ LIB3270_TOGGLE_SSL_TRACE, /**< @brief Enable security traces */ + LIB3270_TOGGLE_RECONNECT, /**< @brief Auto reconnect */ + LIB3270_TOGGLE_COUNT } LIB3270_TOGGLE_ID; diff --git a/src/include/networking.h b/src/include/networking.h index 23efcee..e9e4830 100644 --- a/src/include/networking.h +++ b/src/include/networking.h @@ -188,6 +188,12 @@ typedef struct lib3270_net_module { LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession); /** + * @brief Set network error message. + * + */ +LIB3270_INTERNAL void lib3270_set_network_error(H3270 *hSession,const char *summary, const char *fmt, ...); + +/** * @brief Connect to host, returns a connected socket. * * @param hSession Disconnected TN3270 session. diff --git a/src/network_modules/openssl/main.c b/src/network_modules/openssl/main.c index bc90f5f..814c568 100644 --- a/src/network_modules/openssl/main.c +++ b/src/network_modules/openssl/main.c @@ -94,14 +94,13 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) trace_ssl(hSession,"%s","The secure connection has been closed cleanly"); - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Disconnected from host."), "%s", _("The secure connection has been closed cleanly.") ); + return 0; case SSL_ERROR_WANT_READ: @@ -118,14 +117,12 @@ ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) (void) ERR_error_string(ssl_error, err_buf); trace_dsn(hSession,"RCVD SSL_write error %d (%s)\n", ssl_error, err_buf); - lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf); - - LIB3270_POPUP popup = { - .summary = _("Error writing to host"), - .body = body - }; - - lib3270_popup(hSession,&popup,0); + lib3270_set_network_error( + hSession, + _("Error writing to host."), + _("The SSL error message was %s"), + err_buf + ); return -1; @@ -145,10 +142,8 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) { trace_ssl(hSession,"%s","The secure connection has been closed cleanly"); - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Disconnected from host."), "%s", _("The secure connection has been closed cleanly.") @@ -169,14 +164,12 @@ static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) { (void) ERR_error_string(ssl_error, err_buf); trace_dsn(hSession,"RCVD SSL_read error %d (%s)\n", ssl_error, err_buf); - lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf); - - LIB3270_POPUP popup = { - .summary = _("Error reading from host"), - .body = body - }; - - lib3270_popup(hSession,&popup,0); + lib3270_set_network_error( + hSession, + _("Error reading from host"), + _("The SSL error message was %s"), + err_buf + ); return -1; } diff --git a/src/network_modules/tools.c b/src/network_modules/tools.c index 459ec9f..5891cdf 100644 --- a/src/network_modules/tools.c +++ b/src/network_modules/tools.c @@ -59,15 +59,14 @@ int lib3270_socket_recv_failed(H3270 *hSession) { int rc = -wsaError; - LIB3270_POPUP popup = { - .name = "RecvFailed", - .type = LIB3270_NOTIFY_ERROR, - .summary = _("Error receiving data from host"), - }; - // TODO: Translate WSA Error, update message body. - lib3270_popup(hSession,&popup,0); + lib3270_set_network_error( + hSession, + _("Error receiving data from host"), + _("The windows error code was %u"), + (unsigned int) wsaError + ); #else @@ -78,20 +77,13 @@ int lib3270_socket_recv_failed(H3270 *hSession) { // Network error, notify user int rc = -errno; - lib3270_autoptr(char) body = lib3270_strdup_printf( - _("The system error code was %d (%s)"), - errno, - strerror(errno) - ); - - LIB3270_POPUP popup = { - .name = "RecvFailed", - .type = LIB3270_NOTIFY_ERROR, - .summary = _("Error receiving data from host"), - .body = body - }; - - lib3270_popup(hSession,&popup,0); + lib3270_set_network_error( + hSession, + _("Error receiving data from host"), + _("The system error code was %d (%s)"), + errno, + strerror(errno) + ); #endif // _WIN32 @@ -105,14 +97,11 @@ int lib3270_socket_send_failed(H3270 *hSession) { int rc = WSAGetLastError(); - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Erro sending data to host"), - _( "The system error was %s (%d)" ), - lib3270_win32_strerror(rc), - rc + _("The windows error code was %u"), + (unsigned int) wsaError ); #else @@ -121,24 +110,20 @@ int lib3270_socket_send_failed(H3270 *hSession) { switch(rc) { case EPIPE: - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Broken pipe"), - _("The system error code was %d"), - rc + _("The system error code was %d"), + rc ); break; case ECONNRESET: - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Connection reset by peer"), - _("The system error code was %d"), - rc + _("The system error code was %d"), + rc ); break; @@ -146,10 +131,8 @@ int lib3270_socket_send_failed(H3270 *hSession) { return 0; default: - lib3270_popup_dialog( - hSession, - LIB3270_NOTIFY_ERROR, - NULL, + lib3270_set_network_error( + hSession, _("Unexpected error writing to network socket"), _("The system error code was %d (%s)"), rc, strerror(rc) @@ -157,7 +140,6 @@ int lib3270_socket_send_failed(H3270 *hSession) { } - #endif // _WIN32 return -1; -- libgit2 0.21.2