diff --git a/lib3270.cbp b/lib3270.cbp
index 5f00494..bde1d60 100644
--- a/lib3270.cbp
+++ b/lib3270.cbp
@@ -337,7 +337,7 @@
-
+
diff --git a/src/core/host.c b/src/core/host.c
index f3935c4..136656b 100644
--- a/src/core/host.c
+++ b/src/core/host.c
@@ -388,13 +388,14 @@ LIB3270_EXPORT int lib3270_set_url(H3270 *h, const char *n)
{ 0, "telnet://", "telnet" }
};
+ int f;
*/
+
lib3270_autoptr(char) str = strdup(n);
char * hostname = lib3270_set_network_module_from_url(h,str);
const char * srvc;
char * ptr;
char * query = "";
- int f;
trace("%s(%s)",__FUNCTION__,str);
diff --git a/src/include/networking.h b/src/include/networking.h
index 3143f7e..a4a47c9 100644
--- a/src/include/networking.h
+++ b/src/include/networking.h
@@ -177,7 +177,7 @@
* @retval -EAGAIN Try again.
*
*/
- LIB3270_INTERNAL int lib3270_network_recv_failed(H3270 *hSession);
+ LIB3270_INTERNAL int lib3270_socket_recv_failed(H3270 *hSession);
/**
* @brief Translate system socket send error codes, show popup if needed.
@@ -187,7 +187,9 @@
* @return Translated error code.
*
*/
- LIB3270_INTERNAL int lib3270_network_send_failed(H3270 *hSession);
+ LIB3270_INTERNAL int lib3270_socket_send_failed(H3270 *hSession);
+
+ LIB3270_INTERNAL int lib3270_socket_set_non_blocking(H3270 *hSession, int sock, const unsigned char on);
/**
* @breif Select the network context from URL.
@@ -195,7 +197,8 @@
* @return Pointer to the hostname or NULL if failed (sets errno).
*
*/
- LIB3270_INTERNAL const char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url);
+ LIB3270_INTERNAL char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url);
+
/**
* @brief Select the default (unsecure) network context.
@@ -205,6 +208,10 @@
*/
LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession);
+#ifdef HAVE_LIBSSL
+ LIB3270_INTERNAL void lib3270_set_libssl_network_module(H3270 *hSession);
+#endif // HAVE_LIBSSL
+
LIB3270_INTERNAL int lib3270_activate_ssl_network_module(H3270 *hSession, int sock);
#endif // LIB3270_NETWORKING_H_INCLUDED
diff --git a/src/network_modules/default/main.c b/src/network_modules/default/main.c
index fff9e91..c2fcae8 100644
--- a/src/network_modules/default/main.c
+++ b/src/network_modules/default/main.c
@@ -33,7 +33,6 @@
*/
#include "private.h"
- #include
static void unsecure_network_finalize(H3270 *hSession) {
@@ -70,7 +69,7 @@
if(bytes >= 0)
return bytes;
- return lib3270_network_send_failed(hSession);
+ return lib3270_socket_send_failed(hSession);
}
@@ -82,7 +81,7 @@
return bytes;
}
- return lib3270_network_recv_failed(hSession);
+ return lib3270_socket_recv_failed(hSession);
}
@@ -95,62 +94,7 @@ static void * unsecure_network_add_poll(H3270 *hSession, LIB3270_IO_FLAG flag, v
}
static int unsecure_network_non_blocking(H3270 *hSession, const unsigned char on) {
-
- if(hSession->network.context->sock < 0)
- return 0;
-
-#ifdef WIN32
-
- WSASetLastError(0);
- u_long iMode= on ? 1 : 0;
-
- if(ioctlsocket(hSession->network.context->sock,FIONBIO,&iMode))
- {
- lib3270_popup_dialog( hSession,
- LIB3270_NOTIFY_ERROR,
- _( "Connection error" ),
- _( "ioctlsocket(FIONBIO) failed." ),
- "%s", lib3270_win32_strerror(GetLastError()));
- return -1;
- }
-
-#else
-
- int f;
-
- if ((f = fcntl(hSession->network.context->sock, F_GETFL, 0)) == -1)
- {
- lib3270_popup_dialog( hSession,
- LIB3270_NOTIFY_ERROR,
- _( "Socket error" ),
- _( "fcntl() error when getting socket state." ),
- _( "%s" ), strerror(errno)
- );
-
- return -1;
- }
-
- if (on)
- f |= O_NDELAY;
- else
- f &= ~O_NDELAY;
-
- if (fcntl(hSession->network.context->sock, F_SETFL, f) < 0)
- {
- lib3270_popup_dialog( hSession,
- LIB3270_NOTIFY_ERROR,
- _( "Socket error" ),
- on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
- _( "%s" ), strerror(errno)
- );
- return -1;
- }
-
-#endif
-
- debug("Socket %d is now %s",hSession->network.context->sock,(on ? "Non Blocking" : "Blocking"));
-
- return 0;
+ return lib3270_socket_set_non_blocking(hSession, hSession->network.context->sock, on);
}
static int unsecure_network_is_connected(const H3270 *hSession) {
diff --git a/src/network_modules/openssl/main.c b/src/network_modules/openssl/main.c
index 0e990d3..ce0a506 100644
--- a/src/network_modules/openssl/main.c
+++ b/src/network_modules/openssl/main.c
@@ -79,45 +79,102 @@ static int openssl_network_disconnect(H3270 *hSession) {
ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) {
-/*
- if(hSession->network.context->sock < 0) {
- return -(errno = ENOTCONN);
+ int rc = SSL_write(hSession->network.context->con, (const char *) buffer, length);
+ if(rc > 0)
+ return rc;
+
+ // https://www.openssl.org/docs/man1.0.2/man3/SSL_get_error.html
+ int ssl_error = SSL_get_error(hSession->network.context->con, rc);
+ switch(ssl_error) {
+ case SSL_ERROR_ZERO_RETURN:
+
+ trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
+
+ lib3270_popup_dialog(
+ hSession,
+ LIB3270_NOTIFY_ERROR,
+ NULL,
+ _("Disconnected from host"),
+ "%s",
+ _("The secure connection has been closed cleanly.")
+ );
+ return 0;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return -EWOULDBLOCK; // Force a new loop.
+
+ case SSL_ERROR_SYSCALL:
+ return lib3270_socket_send_failed(hSession);
+
}
- ssize_t bytes = SSL_write(hSession->network.context->con, (const char *) buffer, length);
+ // Build error message.
+ char err_buf[120];
+ (void) ERR_error_string(ssl_error, err_buf);
+ trace_dsn(hSession,"RCVD SSL_write error %d (%s)\n", ssl_error, err_buf);
- debug("%s bytes=%d",__FUNCTION__,(int) bytes);
+ lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf);
- if(bytes >= 0)
- return bytes;
+ LIB3270_POPUP popup = {
+ .summary = _("Error writing to host"),
+ .body = body
+ };
- // SSL Write has failed, using SSL_get_error to identify what has happened.
- int error = SSL_get_error(hSession->network.context->con,(int) bytes);
+ lib3270_popup(hSession,&popup,0);
- if(error == SSL_ERROR_SYSCALL) {
+ return -1;
- #error Use errno!
+}
- return -1;
+static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
+
+ int rc = SSL_read(hSession->network.context->con, (char *) buf, len);
+ if(rc > 0) {
+ return rc;
}
- // Not a system error, inspects the result.
+ // https://www.openssl.org/docs/man1.0.2/man3/SSL_get_error.html
+ int ssl_error = SSL_get_error(hSession->network.context->con, rc);
+ switch(ssl_error) {
+ case SSL_ERROR_ZERO_RETURN:
+ trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
+ lib3270_popup_dialog(
+ hSession,
+ LIB3270_NOTIFY_ERROR,
+ NULL,
+ _("Disconnected from host"),
+ "%s",
+ _("The secure connection has been closed cleanly.")
+ );
+ return 0;
- lib3270_popup(hSession,&popup,0);
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return -EWOULDBLOCK; // Force a new loop.
- return -1;
-*/
+ case SSL_ERROR_SYSCALL:
+ return lib3270_socket_recv_failed(hSession);
-}
+ }
-static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
+ // Build error message.
+ char err_buf[120];
+ (void) ERR_error_string(ssl_error, err_buf);
+ trace_dsn(hSession,"RCVD SSL_read error %d (%s)\n", ssl_error, err_buf);
-// return SSL_read(hSession->network.context->con, (char *) buf, len);
+ 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);
+ return -1;
}
static int openssl_network_getsockname(const H3270 *hSession, struct sockaddr *addr, socklen_t *addrlen) {
@@ -125,22 +182,23 @@ static int openssl_network_getsockname(const H3270 *hSession, struct sockaddr *a
}
static void * openssl_network_add_poll(H3270 *hSession, LIB3270_IO_FLAG flag, void(*call)(H3270 *, int, LIB3270_IO_FLAG, void *), void *userdata) {
-
+ return lib3270_add_poll_fd(hSession,hSession->network.context->sock,flag,call,userdata);
}
static int openssl_network_non_blocking(H3270 *hSession, const unsigned char on) {
-
+ return lib3270_socket_set_non_blocking(hSession, hSession->network.context->sock, on);
}
-static int openssl_network_is_connected(H3270 *hSession) {
-
+static int openssl_network_is_connected(const H3270 *hSession) {
+ return hSession->network.context->sock > 0;
}
static int openssl_network_setsockopt(H3270 *hSession, int level, int optname, const void *optval, size_t optlen) {
-
+ return setsockopt(hSession->network.context->sock, level, optname, optval, optlen);
}
static int openssl_network_getsockopt(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen) {
+ return getsockopt(hSession->network.context->sock, level, optname, optval, optlen);
}
static int openssl_network_init(H3270 *hSession) {
@@ -151,8 +209,6 @@ static int openssl_network_init(H3270 *hSession) {
if(!ctx_context)
return -1;
- LIB3270_NET_CONTEXT * context = hSession->network.context;
-
return 0;
}
@@ -202,11 +258,13 @@ static int openssl_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state
hSession->ssl.host = 1;
context->sock = lib3270_network_connect(hSession, state);
+ debug("%s: sock=%d",__FUNCTION__,context->sock);
+
return (context->sock < 0 ? -1 : 0);
}
-void lib3270_set_openssl_network_module(H3270 *hSession) {
+void lib3270_set_libssl_network_module(H3270 *hSession) {
static const LIB3270_NET_MODULE module = {
.name = "tn3270s",
@@ -244,7 +302,7 @@ void lib3270_set_openssl_network_module(H3270 *hSession) {
int lib3270_activate_ssl_network_module(H3270 *hSession, int sock) {
- lib3270_set_openssl_network_module(hSession);
+ lib3270_set_libssl_network_module(hSession);
int rc = openssl_network_init(hSession);
@@ -261,3 +319,5 @@ void lib3270_openssl_crl_free(LIB3270_NET_CONTEXT *context) {
}
}
+
+
diff --git a/src/network_modules/select.c b/src/network_modules/select.c
index f54ba85..539a3af 100644
--- a/src/network_modules/select.c
+++ b/src/network_modules/select.c
@@ -18,7 +18,7 @@
* programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
* St, Fifth Floor, Boston, MA 02110-1301 USA
*
- * Este programa está nomeado como unsecure.c e possui - linhas de código.
+ * Este programa está nomeado como - e possui - linhas de código.
*
* Contatos:
*
@@ -41,14 +41,24 @@
/*--[ Implement ]------------------------------------------------------------------------------------*/
- const char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url) {
+ char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url) {
static const struct {
const char *scheme; ///< @brief URL scheme for module.
void (*activate)(H3270 *hSession); ///< @brief Selection method.
} modules[] = {
- { "tn3270://", lib3270_set_default_network_module },
+ { "tn3270://", lib3270_set_default_network_module },
+
+#ifdef HAVE_LIBSSL
+
+ { "tn3270s://", lib3270_set_libssl_network_module },
+
+ // Compatibility schemes.
+ { "L://", lib3270_set_libssl_network_module },
+ { "L:", lib3270_set_libssl_network_module },
+
+#endif // HAVE_LIBSSL
};
diff --git a/src/network_modules/tools.c b/src/network_modules/tools.c
new file mode 100644
index 0000000..e30ecf9
--- /dev/null
+++ b/src/network_modules/tools.c
@@ -0,0 +1,214 @@
+/*
+ * "Software PW3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
+ * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
+ * aplicativos mainframe. Registro no INPI sob o nome G3270.
+ *
+ * Copyright (C) <2008>
+ *
+ * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
+ * os termos da GPL v.2 - Licença Pública Geral ', conforme publicado pela
+ * Free Software Foundation.
+ *
+ * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
+ * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
+ * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
+ * obter mais detalhes.
+ *
+ * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
+ * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
+ * St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Este programa está nomeado como unsecure.c e possui - linhas de código.
+ *
+ * Contatos:
+ *
+ * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
+ * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça)
+ *
+ */
+
+ /**
+ * @brief Common methods for send/recv errors.
+ *
+ */
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+/*--[ Implement ]------------------------------------------------------------------------------------*/
+
+ int lib3270_socket_recv_failed(H3270 *hSession) {
+
+#ifdef _WIN32
+
+ int wsaError = WSAGetLastError();
+
+ // EWOULDBLOCK & EAGAIN should return directly.
+ if(wsaError == WSAEWOULDBLOCK)
+ return -EWOULDBLOCK;
+
+ if(wsaError == WSAEINPROGRESS)
+ return -EAGAIN;
+
+ 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);
+
+#else
+
+ // EWOULDBLOCK & EAGAIN should return directly.
+ if(errno == EWOULDBLOCK || errno == EAGAIN)
+ return -errno;
+
+ // 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);
+
+#endif // _WIN32
+
+ return rc;
+
+ }
+
+ int lib3270_socket_send_failed(H3270 *hSession) {
+
+ #ifdef _WIN32
+
+ int rc = WSAGetLastError();
+
+ #error Have work to do.
+
+ #else
+
+ int rc = errno;
+
+ switch(rc) {
+ case EPIPE:
+ lib3270_popup_dialog(
+ hSession,
+ LIB3270_NOTIFY_ERROR,
+ NULL,
+ _("Broken pipe"),
+ _("The system error code was %d"),
+ rc
+ );
+ break;
+
+ case ECONNRESET:
+ lib3270_popup_dialog(
+ hSession,
+ LIB3270_NOTIFY_ERROR,
+ NULL,
+ _("Connection reset by peer"),
+ _("The system error code was %d"),
+ rc
+ );
+ break;
+
+ case EINTR:
+ return 0;
+
+ default:
+ lib3270_popup_dialog(
+ hSession,
+ LIB3270_NOTIFY_ERROR,
+ NULL,
+ _("Unexpected error writing to network socket"),
+ _("The system error code was %d (%s)"),
+ rc, strerror(rc)
+ );
+
+ }
+
+
+ #endif // _WIN32
+
+ return -1;
+
+ }
+
+int lib3270_socket_set_non_blocking(H3270 *hSession, int sock, const unsigned char on) {
+
+ if(sock < 0)
+ return 0;
+
+#ifdef WIN32
+
+ WSASetLastError(0);
+ u_long iMode= on ? 1 : 0;
+
+ if(ioctlsocket(sock,FIONBIO,&iMode))
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Connection error" ),
+ _( "ioctlsocket(FIONBIO) failed." ),
+ "%s", lib3270_win32_strerror(GetLastError()));
+ return -1;
+ }
+
+#else
+
+ int f;
+
+ if ((f = fcntl(sock, F_GETFL, 0)) == -1)
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Socket error" ),
+ _( "fcntl() error when getting socket state." ),
+ _( "%s" ), strerror(errno)
+ );
+
+ return -1;
+ }
+
+ if (on)
+ f |= O_NDELAY;
+ else
+ f &= ~O_NDELAY;
+
+ if (fcntl(sock, F_SETFL, f) < 0)
+ {
+ lib3270_popup_dialog( hSession,
+ LIB3270_NOTIFY_ERROR,
+ _( "Socket error" ),
+ on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
+ _( "%s" ), strerror(errno)
+ );
+ return -1;
+ }
+
+#endif
+
+ debug("Socket %d is now %s",sock,(on ? "Non Blocking" : "Blocking"));
+
+ return 0;
+
+}
diff --git a/src/network_modules/translate.c b/src/network_modules/translate.c
deleted file mode 100644
index 995ffa7..0000000
--- a/src/network_modules/translate.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * "Software PW3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
- * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
- * aplicativos mainframe. Registro no INPI sob o nome G3270.
- *
- * Copyright (C) <2008>
- *
- * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
- * os termos da GPL v.2 - Licença Pública Geral ', conforme publicado pela
- * Free Software Foundation.
- *
- * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
- * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
- * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
- * obter mais detalhes.
- *
- * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
- * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
- * St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Este programa está nomeado como unsecure.c e possui - linhas de código.
- *
- * Contatos:
- *
- * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
- * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça)
- *
- */
-
- /**
- * @brief Common methods for send/recv errors.
- *
- */
-
- #include
- #include
- #include
- #include
- #include
-
-/*--[ Implement ]------------------------------------------------------------------------------------*/
-
- int lib3270_network_recv_failed(H3270 *hSession) {
-
-#ifdef _WIN32
-
- int wsaError = WSAGetLastError();
-
- // EWOULDBLOCK & EAGAIN should return directly.
- if(wsaError == WSAEWOULDBLOCK)
- return -EWOULDBLOCK;
-
- if(wsaError == WSAEINPROGRESS)
- return -EAGAIN;
-
- 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);
-
-#else
-
- // EWOULDBLOCK & EAGAIN should return directly.
- if(errno == EWOULDBLOCK || errno == EAGAIN)
- return -errno;
-
- // 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);
-
-#endif // _WIN32
-
- return rc;
-
- }
-
- int lib3270_network_send_failed(H3270 *hSession) {
-
- #ifdef _WIN32
-
- int rc = WSAGetLastError();
-
- #error Have work to do.
-
- #else
-
- int rc = errno;
-
- switch(rc) {
- case EPIPE:
- lib3270_popup_dialog(
- hSession,
- LIB3270_NOTIFY_ERROR,
- NULL,
- _("Broken pipe"),
- _("The system error code was %d"),
- rc
- );
- break;
-
- case ECONNRESET:
- lib3270_popup_dialog(
- hSession,
- LIB3270_NOTIFY_ERROR,
- NULL,
- _("Connection reset by peer"),
- _("The system error code was %d"),
- rc
- );
- break;
-
- case EINTR:
- return 0;
-
- default:
- lib3270_popup_dialog(
- hSession,
- LIB3270_NOTIFY_ERROR,
- NULL,
- _("Unexpected error writing to network socket"),
- _("The system error code was %d (%s)"),
- rc, strerror(rc)
- );
-
- }
-
-
- #endif // _WIN32
-
- }
--
libgit2 0.21.2