diff --git a/Makefile.in b/Makefile.in
index 33acbff..9ebfbae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -45,6 +45,8 @@ SOURCES= \
$(wildcard src/selection/*.c) \
$(wildcard src/ssl/*.c) \
$(wildcard src/ssl/@OSNAME@/*.c) \
+ $(wildcard src/network_modules/*.c) \
+ $(wildcard src/network_modules/@OSNAME@/*.c) \
$(BASEDIR)/.tmp/$(LIBNAME)/fallbacks.c
TEST_SOURCES= \
diff --git a/lib3270.cbp b/lib3270.cbp
index 0e12ad8..8c77087 100644
--- a/lib3270.cbp
+++ b/lib3270.cbp
@@ -307,6 +307,10 @@
+
+
+
+
diff --git a/src/core/connect.c b/src/core/connect.c
index afbc2f8..26207c3 100644
--- a/src/core/connect.c
+++ b/src/core/connect.c
@@ -62,7 +62,7 @@
if(ssl_ctx_init(hSession, (SSL_ERROR_MESSAGE *) ssl_error))
return -1;
-#if defined(SSL_ENABLE_CRL_CHECK)
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
lib3270_crl_free_if_expired(hSession);
#endif // defined(SSL_ENABLE_CRL_CHECK)
@@ -71,6 +71,7 @@
#endif // HAVE_LIBSSL
+/*
void connection_failed(H3270 *hSession, const char *message)
{
lib3270_disconnect(hSession);
@@ -94,6 +95,7 @@
lib3270_activate_auto_reconnect(hSession,1000);
}
+*/
int lib3270_allow_reconnect(const H3270 *hSession)
{
@@ -169,16 +171,11 @@
}
- static int bg_start_tls(H3270 *hSession, void *message)
- {
-
- }
-
- int lib3270_start_tls(H3270 *hSession)
+ int lib3270_start_tls(H3270 *hSession, Bool required)
{
int rc = 0;
- if(hSession->network.module->start_tls)
+ if(hSession->network.module->start_tls,required)
{
LIB3270_NETWORK_STATE state;
memset(&state,0,sizeof(state));
diff --git a/src/core/host.c b/src/core/host.c
index d182d99..fbb06a3 100644
--- a/src/core/host.c
+++ b/src/core/host.c
@@ -42,6 +42,7 @@
#endif // HAVE_MALLOC_H
#include
+#include
#include "resources.h"
#include "hostc.h"
@@ -279,7 +280,7 @@ static void update_url(H3270 *hSession)
lib3270_free(hSession->host.url);
hSession->host.url = url;
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
lib3270_crl_free(hSession);
#endif // SSL_ENABLE_CRL_CHECK
diff --git a/src/core/iocalls.c b/src/core/iocalls.c
index cb6e64e..aa34aa7 100644
--- a/src/core/iocalls.c
+++ b/src/core/iocalls.c
@@ -299,13 +299,10 @@ static void internal_remove_poll(H3270 *session, void *id)
}
-/*
LIB3270_EXPORT void lib3270_remove_poll(H3270 *session, void *id)
{
- debug("%s(%d,%p)",__FUNCTION__,session->connection.sock,id);
remove_poll(session, id);
}
-*/
LIB3270_EXPORT void lib3270_set_poll_state(H3270 *session, void *id, int enabled)
{
@@ -520,7 +517,7 @@ LIB3270_EXPORT int lib3270_run_task(H3270 *hSession, int(*callback)(H3270 *h, vo
int non_blocking(H3270 *hSession, Boolean on)
{
- if(hSession->network.module->non_blocking,on)
+ if(hSession->network.module->non_blocking(hSession,on))
return 0;
lib3270_set_poll_state(hSession,hSession->xio.read, on);
diff --git a/src/core/linux/connect.c b/src/core/linux/connect.c
index b8847b8..b33baef 100644
--- a/src/core/linux/connect.c
+++ b/src/core/linux/connect.c
@@ -42,8 +42,6 @@
#include
#include
-// #define SOCK_CLOSE(s) close(s->connection.sock); s->connection.sock = -1;
-
#include
#include "hostc.h"
@@ -58,8 +56,8 @@
/*---[ Implement ]-------------------------------------------------------------------------------*/
-static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED(flag), void GNUC_UNUSED(*dunno))
-{
+ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED(flag), void GNUC_UNUSED(*dunno))
+ {
int err;
socklen_t len = sizeof(err);
@@ -83,91 +81,94 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG
}
else if(err)
{
- lib3270_autoptr(char) body = lib3270_strdup_printf(_("%s (rc=%d)"),strerror(err),err);
- connection_failed(hSession,body);
+ lib3270_autoptr(LIB3270_POPUP) popup =
+ lib3270_popup_clone_printf(
+ NULL,
+ _( "Can't connect to %s:%s"),
+ hSession->host.current,
+ hSession->host.srvc
+ );
+
+ lib3270_autoptr(char) syserror =
+ lib3270_strdup_printf(
+ _("The system error was \"%s\" (rc=%d)"),
+ strerror(err),
+ err
+ );
+
+ if(hSession->cbk.popup(hSession,popup,!hSession->auto_reconnect_inprogress) == 0)
+ lib3270_activate_auto_reconnect(hSession,1000);
+
return;
}
hSession->xio.except = hSession->network.module->add_poll(hSession,LIB3270_IO_FLAG_EXCEPTION,net_exception,0);
hSession->xio.read = hSession->network.module->add_poll(hSession,LIB3270_IO_FLAG_READ,net_input,0);
- if(lib3270_start_tls(hSession))
+ if(lib3270_start_tls(hSession,0))
return;
lib3270_setup_session(hSession);
lib3270_set_connected_initial(hSession);
-}
-
- struct resolver
- {
- const char * message;
- };
+ }
- static int background_connect(H3270 *hSession, void *host)
+ int net_reconnect(H3270 *hSession, int seconds)
{
+ LIB3270_NETWORK_STATE state;
+ memset(&state,0,sizeof(state));
- struct addrinfo hints;
- struct addrinfo * result = NULL;
- struct addrinfo * rp = NULL;
-
- memset(&hints,0,sizeof(hints));
- hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
- hints.ai_socktype = SOCK_STREAM; // Stream socket
- hints.ai_flags = AI_PASSIVE; // For wildcard IP address
- hints.ai_protocol = 0; // Any protocol
-
- status_resolving(hSession);
-
- int rc = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
- if(rc != 0)
+ // Initialize and connect to host
+ if(lib3270_run_task(hSession, (int(*)(H3270 *, void *)) hSession->network.module->connect, &state))
{
- ((struct resolver *) host)->message = gai_strerror(rc);
- return -1;
- }
-
- status_connecting(hSession);
-
- for(rp = result; hSession->connection.sock < 0 && rp != NULL; rp = rp->ai_next)
- {
- hSession->connection.sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if(hSession->connection.sock < 0)
+ lib3270_autoptr(LIB3270_POPUP) popup =
+ lib3270_popup_clone_printf(
+ NULL,
+ _( "Can't connect to %s:%s"),
+ hSession->host.current,
+ hSession->host.srvc
+ );
+
+ if(!popup->summary)
{
- ((struct resolver *) host)->message = strerror(errno);
- continue;
+ popup->summary = popup->body;
+ popup->body = NULL;
}
- // Connected!
- if(connect(hSession->connection.sock, rp->ai_addr, rp->ai_addrlen))
+ lib3270_autoptr(char) syserror = NULL;
+ if(state.syserror)
{
- SOCK_CLOSE(hSession);
- ((struct resolver *) host)->message = strerror(errno);
- continue;
+ syserror = lib3270_strdup_printf(
+ _("The system error was \"%s\" (rc=%d)"),
+ strerror(state.syserror),
+ state.syserror
+ );
}
+#ifdef _WIN32
+ else if(state.winerror)
+ {
+ #error TODO
+ }
+#endif // _WIN32
- }
-
- freeaddrinfo(result);
-
- return 0;
-
- }
+ if(!popup->body)
+ {
+ if(state.error_message)
+ popup->body = state.error_message;
+ else
+ popup->body = syserror;
+ }
- int net_reconnect(H3270 *hSession, int seconds)
- {
- struct resolver host;
- memset(&host,0,sizeof(host));
+ if(hSession->cbk.popup(hSession,popup,!hSession->auto_reconnect_inprogress) == 0)
+ lib3270_activate_auto_reconnect(hSession,1000);
- // Connect to host
- if(lib3270_run_task(hSession, background_connect, &host) || hSession->connection.sock < 0)
- {
- connection_failed(hSession,host.message);
return errno = ENOTCONN;
}
- /* don't share the socket with our children */
- (void) fcntl(hSession->connection.sock, F_SETFD, 1);
+ //
+ // Connected
+ //
hSession->ever_3270 = False;
#if defined(HAVE_LIBSSL)
@@ -182,7 +183,7 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG
// set options for inline out-of-band data and keepalives
int optval = 1;
- if (setsockopt(hSession->connection.sock, SOL_SOCKET, SO_OOBINLINE, (char *)&optval,sizeof(optval)) < 0)
+ if(hSession->network.module->setsockopt(hSession, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof(optval)) < 0)
{
int rc = errno;
lib3270_popup_dialog( hSession,
@@ -191,12 +192,12 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG
_( "setsockopt(SO_OOBINLINE) has failed" ),
"%s",
strerror(rc));
- SOCK_CLOSE(hSession);
+ hSession->network.module->disconnect(hSession);
return rc;
}
optval = lib3270_get_toggle(hSession,LIB3270_TOGGLE_KEEP_ALIVE) ? 1 : 0;
- if (setsockopt(hSession->connection.sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 0)
+ if (hSession->network.module->setsockopt(hSession, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0)
{
int rc = errno;
@@ -209,7 +210,8 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG
buffer,
"%s",
strerror(rc));
- SOCK_CLOSE(hSession);
+
+ hSession->network.module->disconnect(hSession);
return rc;
}
else
@@ -254,7 +256,7 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG
case LIB3270_CONNECTED_INITIAL_E:
case LIB3270_CONNECTED_NVT:
case LIB3270_CONNECTED_SSCP:
- case LIB3270_RESOLVING:
+ case LIB3270_CONNECTING:
break;
case LIB3270_NOT_CONNECTED:
diff --git a/src/core/popup.c b/src/core/popup.c
index b4a0929..f6412fa 100644
--- a/src/core/popup.c
+++ b/src/core/popup.c
@@ -135,7 +135,14 @@ LIB3270_POPUP * lib3270_popup_clone_printf(const LIB3270_POPUP *origin, const ch
// Alocate new struct
LIB3270_POPUP * popup = lib3270_malloc(sizeof(LIB3270_POPUP)+strlen(body)+1);
- *popup = *origin;
+ if(origin)
+ {
+ *popup = *origin;
+ }
+ else
+ {
+ memset(popup,0,sizeof(LIB3270_POPUP));
+ }
strcpy((char *)(popup+1),body);
popup->body = (char *)(popup+1);
@@ -154,7 +161,8 @@ static int def_popup(H3270 *hSession, const LIB3270_POPUP *popup, unsigned char
for(ix = 0; ix < (sizeof(text)/sizeof(text[0])); ix++)
{
- lib3270_write_log(hSession,"popup","%s",text[ix]);
+ if(text[ix])
+ lib3270_write_log(hSession,"popup","%s",text[ix]);
}
return ENOTSUP;
diff --git a/src/core/properties/boolean.c b/src/core/properties/boolean.c
index ffe901b..74ff459 100644
--- a/src/core/properties/boolean.c
+++ b/src/core/properties/boolean.c
@@ -47,7 +47,7 @@
void lib3270_disable_crl_download(H3270 *hSession)
{
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
hSession->ssl.crl.download = 0;
#endif // SSL_ENABLE_CRL_CHECK
}
diff --git a/src/core/properties/string.c b/src/core/properties/string.c
index 06b102a..93c348c 100644
--- a/src/core/properties/string.c
+++ b/src/core/properties/string.c
@@ -28,6 +28,7 @@
*/
#include
+ #include
#include
#include
#include
diff --git a/src/core/rpq.c b/src/core/rpq.c
index 4ce873f..0473d0b 100644
--- a/src/core/rpq.c
+++ b/src/core/rpq.c
@@ -686,7 +686,7 @@ static int get_rpq_address(H3270 *hSession, unsigned char *buf, const int maxlen
struct sockaddr_in6 sa6;
#endif // HAVE_GETADDRINFO
} u;
- int addrlen = sizeof(u);
+ socklen_t addrlen = sizeof(u);
void *src = NULL;
int len = 0;
diff --git a/src/core/screen.c b/src/core/screen.c
index 9869ae2..8459b6a 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -550,19 +550,21 @@ void status_oerr(H3270 *session, int error_type)
*/
void status_resolving(H3270 *hSession)
{
- lib3270_set_cstate(hSession,LIB3270_RESOLVING);
- lib3270_st_changed(hSession, LIB3270_STATE_RESOLVING, True);
+ debug("%s",__FUNCTION__);
mcursor_set(hSession,LIB3270_POINTER_LOCKED);
+
+ lib3270_st_changed(hSession, LIB3270_STATE_RESOLVING, True);
status_changed(hSession, LIB3270_MESSAGE_RESOLVING);
}
void status_connecting(H3270 *hSession)
{
- lib3270_set_cstate(hSession,LIB3270_RESOLVING);
- lib3270_st_changed(hSession, LIB3270_STATE_CONNECTING, True);
+ debug("%s",__FUNCTION__);
mcursor_set(hSession,LIB3270_POINTER_LOCKED);
+
+ lib3270_st_changed(hSession, LIB3270_STATE_CONNECTING, True);
status_changed(hSession, LIB3270_MESSAGE_CONNECTING);
}
diff --git a/src/core/session.c b/src/core/session.c
index e8e53b9..7921ed4 100644
--- a/src/core/session.c
+++ b/src/core/session.c
@@ -84,11 +84,17 @@ void lib3270_session_free(H3270 *h)
lib3270_crl_free(h);
#endif // SSL_ENABLE_CRL_CHECK
+ // Release network module
+ if(h->network.module)
+ {
+ h->network.module->finalize(h);
+ h->network.module = NULL;
+ }
+
// Release state change callbacks
for(f=0;flisteners.state[f]);
-
// Release toggle change listeners.
for(f=0;flisteners.toggle[f]);
@@ -316,7 +322,11 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char
int f;
memset(hSession,0,sizeof(H3270));
-// hSession->sz = sizeof(H3270);
+ lib3270_set_default_network_module(hSession);
+
+#if defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBSSL)
+ hSession->ssl.crl.download = 1;
+#endif // SSL_ENABLE_CRL_CHECK
lib3270_set_host_charset(hSession,charset);
lib3270_reset_callbacks(hSession);
@@ -438,22 +448,11 @@ H3270 * lib3270_session_new(const char *model)
trace("%s - configured=%s",__FUNCTION__,default_session ? "Yes" : "No");
hSession = lib3270_malloc(sizeof(H3270));
- hSession->id = 0;
-
-#ifdef HAVE_LIBSSL
- hSession->ssl.protocol.min_version = 0;
- hSession->ssl.protocol.max_version = 0;
-#endif // HAVE_LIBSSL
-
-#if defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBSSL)
- hSession->ssl.crl.download = 1;
-#endif // SSL_ENABLE_CRL_CHECK
+ lib3270_session_init(hSession, model, "bracket" );
if(!default_session)
default_session = hSession;
- lib3270_session_init(hSession, model, "bracket" );
-
if(screen_init(hSession))
return NULL;
diff --git a/src/core/state.c b/src/core/state.c
index 1f59643..bfdf34b 100644
--- a/src/core/state.c
+++ b/src/core/state.c
@@ -38,12 +38,12 @@ LIB3270_EXPORT LIB3270_CSTATE lib3270_get_connection_state(const H3270 *h)
LIB3270_EXPORT int lib3270_pconnected(const H3270 *h)
{
- return (((int) h->connection.state) >= (int)LIB3270_RESOLVING);
+ return (((int) h->connection.state) >= (int)LIB3270_CONNECTING);
}
LIB3270_EXPORT int lib3270_half_connected(const H3270 *h)
{
- return (h->connection.state == LIB3270_RESOLVING || h->connection.state == LIB3270_PENDING);
+ return (h->connection.state == LIB3270_CONNECTING || h->connection.state == LIB3270_PENDING);
}
LIB3270_EXPORT int lib3270_is_disconnected(const H3270 *h)
diff --git a/src/core/telnet.c b/src/core/telnet.c
index 2c35576..be37c3c 100644
--- a/src/core/telnet.c
+++ b/src/core/telnet.c
@@ -261,7 +261,6 @@ static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
#define SE_EAGAIN WSAEINPROGRESS
#define SE_EPIPE WSAECONNABORTED
#define SE_EINPROGRESS WSAEINPROGRESS
- #define SOCK_CLOSE(s) closesocket(s)
#define SOCK_IOCTL(s, f, v) ioctlsocket(s, f, (void *)v)
#else /*][*/
#define socket_errno() errno
@@ -275,7 +274,6 @@ static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
#define SE_EINPROGRESS EINPROGRESS
#endif /*]*/
- #define SOCK_CLOSE(s) close(s)
#define SOCK_IOCTL ioctl
#endif /*]*/
@@ -539,8 +537,6 @@ LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession)
*/
void net_disconnect(H3270 *hSession)
{
- LIB3270_NETWORK_STATE state;
- memset(&state,0,sizeof(state));
// Disconnect from host
#if defined(HAVE_LIBSSL)
@@ -563,7 +559,7 @@ void net_disconnect(H3270 *hSession)
hSession->xio.write = 0;
}
- hSession->network.module->disconnect(hSession,&state);
+ hSession->network.module->disconnect(hSession);
trace_dsn(hSession,"SENT disconnect\n");
@@ -641,9 +637,9 @@ void net_input(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED
if (hSession->ssl.con != NULL)
nr = SSL_read(hSession->ssl.con, (char *) buffer, BUFSZ);
else
- nr = hSession->network.module->recv(hSession->network.context, buffer, BUFSZ);
+ nr = hSession->network.module->recv(hSession, buffer, BUFSZ);
#else
- nr = hSession->network.module->recv(hSession->network.context, buffer, BUFSZ);
+ nr = hSession->network.module->recv(hSession, buffer, BUFSZ);
#endif // HAVE_LIBSSL
if (nr < 0)
@@ -1602,13 +1598,10 @@ static int process_eor(H3270 *hSession)
return 0;
}
-
-/**
- * @brief Called when there is an exceptional condition on the socket.
- */
+/// @brief Called when there is an exceptional condition on the socket.
void net_exception(H3270 *session, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED(flag), void GNUC_UNUSED(*dunno))
{
- CHECK_SESSION_HANDLE(session);
+ debug("%s",__FUNCTION__);
trace_dsn(session,"RCVD urgent data indication\n");
if (!session->syncing)
@@ -1655,9 +1648,10 @@ LIB3270_INTERNAL int lib3270_sock_send(H3270 *hSession, unsigned const char *buf
if(rc > 0)
return rc;
- // Recv error, notify
+ // Send error, notify
#if defined(HAVE_LIBSSL)
+ #error TODO - The send method should emit popup messages.
if(hSession->ssl.con != NULL)
{
unsigned long e;
@@ -1671,25 +1665,7 @@ LIB3270_INTERNAL int lib3270_sock_send(H3270 *hSession, unsigned const char *buf
}
#endif // HAVE_LIBSSL
- trace_dsn(hSession,"RCVD socket error %d\n", socket_errno());
-
- switch(socket_errno())
- {
- case SE_EPIPE:
- popup_an_error(hSession, "%s", _( "Broken pipe" ));
- break;
-
- case SE_ECONNRESET:
- popup_an_error(hSession, "%s", _( "Connection reset by peer" ));
- break;
-
- case SE_EINTR:
- return 0;
-
- default:
- popup_a_sockerr(NULL, "%s", _( "Socket write error" ) );
-
- }
+ trace_dsn(hSession,"RCVD socket error %d\n", -rc);
return -1;
}
@@ -2029,7 +2005,7 @@ const char * lib3270_connection_state_get_name(const LIB3270_CSTATE cstate)
static const char *state_names[] =
{
"unconnected",
- "resolving",
+ "connecting",
"pending",
"connected initial",
"TN3270 NVT",
diff --git a/src/core/toggles/init.c b/src/core/toggles/init.c
index be02226..14df67c 100644
--- a/src/core/toggles/init.c
+++ b/src/core/toggles/init.c
@@ -77,19 +77,22 @@ static void toggle_nop(H3270 GNUC_UNUSED(*session), const struct lib3270_toggle
{
}
-static void toggle_keepalive(H3270 *session, const struct lib3270_toggle GNUC_UNUSED(*t), LIB3270_TOGGLE_TYPE GNUC_UNUSED(tt))
+static void toggle_keepalive(H3270 *hSession, const struct lib3270_toggle GNUC_UNUSED(*t), LIB3270_TOGGLE_TYPE GNUC_UNUSED(tt))
{
- // Update keep-alive option
- int optval = t->value ? 1 : 0;
-
- if(session->network.module->setsockopt(session, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0)
- {
- if(errno != ENOTCONN)
- popup_a_sockerr(session, _( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
- }
- else
+ if(hSession->network.context)
{
- trace_dsn(session,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
+ // Has network context, update keep-alive option
+ int optval = t->value ? 1 : 0;
+
+ if(hSession->network.module->setsockopt(hSession, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0)
+ {
+ if(errno != ENOTCONN)
+ popup_a_sockerr(hSession, _( "Can't %s network keep-alive" ), optval ? _( "enable" ) : _( "disable" ));
+ }
+ else
+ {
+ trace_dsn(hSession,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" );
+ }
}
}
diff --git a/src/core/util.c b/src/core/util.c
index a00d02a..5a67f9d 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -44,6 +44,10 @@
#include
#endif // HAVE_LIBSSL
+#if defined(HAVE_MALLOC_H)
+ #include
+#endif // defined
+
#define my_isspace(c) isspace((unsigned char)c)
/**
diff --git a/src/core/windows/connect.c b/src/core/windows/connect.c
index ced762a..91daf41 100644
--- a/src/core/windows/connect.c
+++ b/src/core/windows/connect.c
@@ -47,8 +47,6 @@
#include
#endif // HAVE_ICONV
-#define SOCK_CLOSE(s) closesocket(s->connection.sock); s->connection.sock = -1;
-
#include "hostc.h"
#include "trace_dsc.h"
#include "telnetc.h"
diff --git a/src/include/internals.h b/src/include/internals.h
index 40f2885..5414361 100644
--- a/src/include/internals.h
+++ b/src/include/internals.h
@@ -883,10 +883,16 @@ LIB3270_INTERNAL int non_blocking(H3270 *session, Boolean on);
/// @brief Fire CState change.
LIB3270_INTERNAL int lib3270_set_cstate(H3270 *hSession, LIB3270_CSTATE cstate);
- inline LIB3270_NET_CONTEXT * lib3270_get_net_context(H3270 *hSession) {
- return hSession->network.context;
- }
-
- LIB3270_INTERNAL int lib3270_start_tls(H3270 *hSession);
+ ///
+ /// @brief Start TLS/SSL
+ ///
+ /// @param hSession Session handle.
+ /// @param required Non zero if the SSL/TLS is not optional.
+ ///
+ /// @return 0 if ok, non zero if failed.
+ ///
+ /// @retval ENOTSUP TLS/SSL is not supported by library.
+ ///
+ LIB3270_INTERNAL int lib3270_start_tls(H3270 *hSession, Bool required);
diff --git a/src/include/lib3270.h b/src/include/lib3270.h
index 6e49a94..62fe9a2 100644
--- a/src/include/lib3270.h
+++ b/src/include/lib3270.h
@@ -252,7 +252,7 @@
typedef enum lib3270_cstate
{
LIB3270_NOT_CONNECTED, ///< @brief no socket, disconnected
- LIB3270_RESOLVING, ///< @brief resolving hostname
+ LIB3270_CONNECTING, ///< @brief connecting to host
LIB3270_PENDING, ///< @brief connection pending
LIB3270_CONNECTED_INITIAL, ///< @brief connected, no mode yet
LIB3270_CONNECTED_ANSI, ///< @brief connected in NVT ANSI mode
diff --git a/src/include/networking.h b/src/include/networking.h
index ab73371..3bc2b68 100644
--- a/src/include/networking.h
+++ b/src/include/networking.h
@@ -41,34 +41,23 @@
DWORD winerror; ///< @brief Win32 error got from GetLastError()
#endif // _WIN32
+ const char * error_message; /// @brief System error message.
+
const LIB3270_POPUP *popup; /// @brief Detailed info for popup.
} LIB3270_NETWORK_STATE;
- typedef struct _lib3270_new_context LIB3270_NET_CONTEXT;
+ typedef struct _lib3270_net_context LIB3270_NET_CONTEXT;
typedef struct lib3270_net_module {
- const char * name; ///< @brief The network module name.
-
- /// @brief Initialize network module
- ///
- /// @param hSession TN3270 session.
- /// @param state Pointer to state message.
- ///
- /// @return Allocated network context.
- ///
- /// @retval NULL Initialization failed.
- ///
- LIB3270_NET_CONTEXT * (*init)(H3270 *hSession, LIB3270_NETWORK_STATE *state);
-
/// @brief Deinitialize network module.
///
/// @param context Network context.
/// @param hSession TN3270 session.
/// @param state Pointer to state message.
///
- void (*deinit)(H3270 *hSession, LIB3270_NETWORK_STATE *state);
+ void (*finalize)(H3270 *hSession);
/// @brief Connect to host.
///
@@ -77,7 +66,7 @@
/// @param seconds Seconds for timeout.
/// @param state Pointer to state message.
///
- int (*connect)(H3270 *hSession, int seconds, LIB3270_NETWORK_STATE *state);
+ int (*connect)(H3270 *hSession, LIB3270_NETWORK_STATE *state);
/// @brief Disconnect from host.
///
@@ -85,9 +74,9 @@
/// @param hSession TN3270 session.
/// @param state Pointer to state message.
///
- int (*disconnect)(H3270 *hSession, LIB3270_NETWORK_STATE *state);
+ int (*disconnect)(H3270 *hSession);
- int (*start_tls)(H3270 *hSession, LIB3270_NETWORK_STATE *msg);
+ int (*start_tls)(H3270 *hSession, LIB3270_NETWORK_STATE *msg, unsigned char required);
/// @brief Send on network context.
///
@@ -126,16 +115,26 @@
int (*getsockname)(const H3270 *hSession, struct sockaddr *addr, socklen_t *addrlen);
/// @brief Set socket options.
- int (*setsockopt)(H3270 *hSession, int level, int optname, void *optval, size_t optlen);
+ int (*setsockopt)(H3270 *hSession, int level, int optname, const void *optval, size_t optlen);
/// @brief Get socket options.
int (*getsockopt)(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen);
} LIB3270_NET_MODULE;
- LIB3270_NET_CONTEXT * lib3270_get_net_context(H3270 *hSession);
- LIB3270_NET_CONTEXT * lib3270_get_default_net_context(void);
-
+ /**
+ * @brief Activate the default (and insecure) network module.
+ *
+ */
+ LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession);
+
+ /**
+ * @brief Connect to host, returns a connected socket.
+ *
+ * @return The Socket number or -1 in case of failure.
+ *
+ */
+ LIB3270_INTERNAL int lib3270_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state);
#endif // LIB3270_NETWORKING_H_INCLUDED
diff --git a/src/network_modules/linux/connect.c b/src/network_modules/linux/connect.c
new file mode 100644
index 0000000..c273992
--- /dev/null
+++ b/src/network_modules/linux/connect.c
@@ -0,0 +1,118 @@
+/*
+ * "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 networking.h 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 Default networking methods.
+ *
+ */
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include
+ #include
+ #include
+
+int lib3270_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
+
+ //
+ // Resolve hostname
+ //
+ struct addrinfo hints;
+ struct addrinfo * result = NULL;
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
+ hints.ai_socktype = SOCK_STREAM; // Stream socket
+ hints.ai_flags = AI_PASSIVE; // For wildcard IP address
+ hints.ai_protocol = 0; // Any protocol
+
+ status_resolving(hSession);
+
+ int rc = getaddrinfo(hSession->host.current, hSession->host.srvc, &hints, &result);
+ if(rc)
+ {
+ state->error_message = gai_strerror(rc);
+ return -1;
+ }
+
+ //
+ // Try connecting to hosts.
+ //
+ int sock = -1;
+ struct addrinfo * rp = NULL;
+
+ status_connecting(hSession);
+
+ for(rp = result; sock < 0 && rp != NULL; rp = rp->ai_next)
+ {
+ // Got socket from host definition.
+ sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if(sock < 0)
+ {
+ // Can't get socket.
+ state->syserror = errno;
+ continue;
+ }
+
+ // Try connect.
+ if(connect(sock, rp->ai_addr, rp->ai_addrlen))
+ {
+ // Can't connect to host
+ state->syserror = errno;
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ }
+
+ freeaddrinfo(result);
+
+ if(sock < 0)
+ {
+ static const LIB3270_POPUP popup = {
+ .name = "CantConnect",
+ .type = LIB3270_NOTIFY_ERROR,
+ .summary = N_("Can't connect to host"),
+ .label = N_("Try again")
+ };
+
+ state->popup = &popup;
+ return sock;
+ }
+
+ // don't share the socket with our children
+ (void) fcntl(sock, F_SETFD, 1);
+
+ return sock;
+}
diff --git a/src/network_modules/private.h b/src/network_modules/private.h
new file mode 100644
index 0000000..e45ae92
--- /dev/null
+++ b/src/network_modules/private.h
@@ -0,0 +1,52 @@
+/*
+ * "Software G3270, 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 private.h 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)
+ *
+ */
+
+#ifndef LIB3270_NETWORK_MODULES_PRIVATE_H_INCLUDED
+
+ #define LIB3270_NETWORK_MODULES_PRIVATE_H_INCLUDED
+
+ #include
+
+ #ifdef _WIN32
+ #include
+ #include
+ #else
+ #include
+ #include
+ #endif // _WIN32
+
+ #include
+ #include
+
+ #include
+ #include
+
+ LIB3270_INTERNAL ssize_t unsecure_network_send(H3270 *hSession, const void *buffer, size_t length);
+
+#endif // !LIB3270_NETWORK_MODULES_PRIVATE_H_INCLUDED
diff --git a/src/network_modules/unsecure.c b/src/network_modules/unsecure.c
index 998e1eb..f764a82 100644
--- a/src/network_modules/unsecure.c
+++ b/src/network_modules/unsecure.c
@@ -32,45 +32,41 @@
*
*/
- #include
- #ifdef _WIN32
- #include
- #include
- #endif // _WIN32
+ #include "private.h"
- #include
- #include
+ #include
+ #include
+ #include
- struct _lib3270_new_context {
+ struct _lib3270_net_context {
int sock;
};
- LIB3270_NET_CONTEXT * unsecure_network_init(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
+ static void unsecure_network_finalize(H3270 *hSession) {
- LIB3270_NET_CONTEXT * context = lib3270_malloc(sizeof(LIB3270_NET_CONTEXT));
-
- context->sock = -1;
+ debug("%s",__FUNCTION__);
- return context;
- }
+ if(hSession->network.context) {
+ lib3270_free(hSession->network.context);
+ hSession->network.context = NULL;
+ }
- void unsecure_network_deinit(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
- unsecure_network_disconnect(hSession->network.context,hSession,state);
- lib3270_free(context);
}
-int unsecure_network_disconnect(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
+ static int unsecure_network_disconnect(H3270 *hSession) {
debug("%s",__FUNCTION__);
- if(context->sock >= 0) {
- shutdown(hSession.network.context->sock, 2);
+
+ if(hSession->network.context->sock >= 0) {
+ shutdown(hSession->network.context->sock, 2);
close(hSession->network.context->sock);
- hSession.network.context->sock = -1;
+ hSession->network.context->sock = -1;
}
-}
+ return 0;
+ }
-ssize_t unsecure_network_send(H3270 *hSession, const void *buffer, size_t length) {
+ ssize_t unsecure_network_send(H3270 *hSession, const void *buffer, size_t length) {
if(hSession->network.context->sock < 0) {
return -(errno = ENOTCONN);
@@ -78,19 +74,68 @@ ssize_t unsecure_network_send(H3270 *hSession, const void *buffer, size_t length
ssize_t bytes = send(hSession->network.context->sock,buffer,length,0);
- if(bytes < 0)
- return -errno;
+ debug("%s bytes=%d",__FUNCTION__,(int) bytes);
- return 0;
-}
+ if(bytes >= 0)
+ return bytes;
+
+ int rc = errno;
-ssize_t unsecure_network_recv(H3270 *hSession, void *buf, size_t len) {
+ debug("%s: %s",__FUNCTION__,strerror(rc));
+
+ 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)
+ );
+
+ }
+
+ return -rc;
+ }
+
+ static ssize_t unsecure_network_recv(H3270 *hSession, void *buf, size_t len) {
+
+ debug("%s",__FUNCTION__);
if(hSession->network.context->sock < 0) {
return -(errno = ENOTCONN);
}
- ssize_t bytes = recv(hSession->network.context->sock, (char *) buffer, len, 0);
+ ssize_t bytes = recv(hSession->network.context->sock, (char *) buf, len, 0);
+
+ debug("%s bytes=%d",__FUNCTION__,(int) bytes);
if(bytes < 0) {
return -errno;
@@ -99,17 +144,17 @@ ssize_t unsecure_network_recv(H3270 *hSession, void *buf, size_t len) {
return bytes;
}
-int unsecure_getsockname(const H3270 *hSession, struct sockaddr *addr, socklen_t *addrlen) {
+static int unsecure_network_getsockname(const H3270 *hSession, struct sockaddr *addr, socklen_t *addrlen) {
if(hSession->network.context->sock < 0)
return -(errno = ENOTCONN);
- return getsockname(hSession->network.context->sock, buf, addrlen);
+ return getsockname(hSession->network.context->sock, addr, addrlen);
}
-void * unsecure_add_poll(H3270 *hSession, LIB3270_IO_FLAG flag, void(*call)(H3270 *, int, LIB3270_IO_FLAG, void *), void *userdata) {
+static void * unsecure_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);
}
-int unsecure_non_blocking(H3270 *hSession, const unsigned char on) {
+static int unsecure_network_non_blocking(H3270 *hSession, const unsigned char on) {
if(hSession->network.context->sock < 0)
return 0;
@@ -165,29 +210,93 @@ int unsecure_non_blocking(H3270 *hSession, const unsigned char on) {
debug("Socket %d is now %s",hSession->network.context->sock,(on ? "Non Blocking" : "Blocking"));
+ return 0;
}
-int unsecure_is_connected(H3270 *hSession) {
- return hSession->network.context.sock > 0;
+static int unsecure_network_is_connected(H3270 *hSession) {
+ return hSession->network.context->sock > 0;
}
-int unsecure_setsockopt(H3270 *hSession, int level, int optname, const void *optval, size_t optlen) {
+static int unsecure_network_setsockopt(H3270 *hSession, int level, int optname, const void *optval, size_t optlen) {
- if(hSession->network.context.sock < 0) {
+ if(hSession->network.context->sock < 0) {
errno = ENOTCONN;
return -1;
}
- return setsockopt(hSession->network.context.sock, level, optname, optval, optlen);
+ return setsockopt(hSession->network.context->sock, level, optname, optval, optlen);
}
-int unsecure_getsockopt(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen) {
+static int unsecure_network_getsockopt(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen) {
- if(hSession->network.context.sock < 0) {
+ if(hSession->network.context->sock < 0) {
errno = ENOTCONN;
return -1;
}
- return getsockopt(hSession->network.context.sock, level, optname, optval, optlen)
+ return getsockopt(hSession->network.context->sock, level, optname, optval, optlen);
+}
+
+static int unsecure_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state) {
+
+ hSession->network.context->sock = lib3270_network_connect(hSession, state);
+ if(hSession->network.context->sock < 0)
+ return hSession->network.context->sock;
+
+ return 0;
}
+
+static int unsecure_network_start_tls(H3270 GNUC_UNUSED(*hSession), LIB3270_NETWORK_STATE *msg, unsigned char required) {
+
+ if(required) {
+
+ // TODO: Replace network module with the openssl version, initialize and execute start_tls on it.
+
+ static const LIB3270_POPUP popup = {
+ .type = LIB3270_NOTIFY_ERROR,
+ .summary = N_("Can't activate SSL/TLS"),
+ .body = N_("The protocol library was build without SSL/TLS support")
+ };
+
+ msg->popup = &popup;
+
+ return ENOTSUP;
+
+ }
+
+ return 0;
+}
+
+void lib3270_set_default_network_module(H3270 *hSession) {
+
+ static const LIB3270_NET_MODULE module = {
+ .finalize = unsecure_network_finalize,
+ .connect = unsecure_network_connect,
+ .disconnect = unsecure_network_disconnect,
+ .start_tls = unsecure_network_start_tls,
+ .send = unsecure_network_send,
+ .recv = unsecure_network_recv,
+ .add_poll = unsecure_network_add_poll,
+ .non_blocking = unsecure_network_non_blocking,
+ .is_connected = unsecure_network_is_connected,
+ .getsockname = unsecure_network_getsockname,
+ .setsockopt = unsecure_network_setsockopt,
+ .getsockopt = unsecure_network_getsockopt
+ };
+
+ debug("%s",__FUNCTION__);
+
+ if(hSession->network.context) {
+ // Has context, finalize it.
+ hSession->network.module->finalize(hSession);
+ }
+
+ hSession->network.context = lib3270_malloc(sizeof(LIB3270_NET_CONTEXT));
+ memset(hSession->network.context,0,sizeof(LIB3270_NET_CONTEXT));
+ hSession->network.context->sock = -1;
+
+ hSession->network.module = &module;
+
+}
+
diff --git a/src/ssl/linux/private.h b/src/ssl/linux/private.h
index e3096e7..89f2317 100644
--- a/src/ssl/linux/private.h
+++ b/src/ssl/linux/private.h
@@ -45,14 +45,14 @@
#include
#include
- #ifdef HAVE_LDAP
+ #if defined(HAVE_LIBSSL) && defined(HAVE_LDAP)
/// @brief Use libldap to get CRL.
LIB3270_INTERNAL X509_CRL * get_crl_using_ldap(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl);
#endif // HAVE_LDAP
- #ifdef HAVE_LIBCURL
+ #if defined (HAVE_LIBSSL) && defined(HAVE_LIBCURL)
/// @brief Use libcurl to get CRL.
LIB3270_INTERNAL X509_CRL * get_crl_using_url(H3270 *hSession, SSL_ERROR_MESSAGE * message, const char *consturl);
diff --git a/src/ssl/properties.c b/src/ssl/properties.c
index c3f49ac..3300149 100644
--- a/src/ssl/properties.c
+++ b/src/ssl/properties.c
@@ -51,7 +51,7 @@ LIB3270_EXPORT int lib3270_get_secure_host(const H3270 *hSession)
}
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
LIB3270_EXPORT char * lib3270_get_ssl_crl_text(const H3270 *hSession)
{
@@ -120,7 +120,7 @@ LIB3270_EXPORT char * lib3270_get_ssl_peer_certificate_text(const H3270 *hSessio
#pragma GCC diagnostic ignored "-Wunused-parameter"
const char * lib3270_crl_get_url(const H3270 *hSession)
{
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
if(hSession->ssl.crl.url)
return hSession->ssl.crl.url;
@@ -144,7 +144,7 @@ LIB3270_EXPORT char * lib3270_get_ssl_peer_certificate_text(const H3270 *hSessio
FAIL_IF_ONLINE(hSession);
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSS) && defined(SSL_ENABLE_CRL_CHECK)
if(hSession->ssl.crl.url)
{
@@ -197,7 +197,7 @@ LIB3270_EXPORT char * lib3270_get_ssl_peer_certificate_text(const H3270 *hSessio
#pragma GCC diagnostic ignored "-Wunused-parameter"
const char * lib3270_crl_get_preferred_protocol(const H3270 *hSession)
{
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(SSL_ENABLE_CRL_CHECK)
if(hSession->ssl.crl.prefer)
return hSession->ssl.crl.prefer;
#endif
@@ -213,7 +213,7 @@ LIB3270_EXPORT char * lib3270_get_ssl_peer_certificate_text(const H3270 *hSessio
FAIL_IF_ONLINE(hSession);
-#ifdef SSL_ENABLE_CRL_CHECK
+#if defined(HAVE_LIBSSL) && defined(HAVE_SSL_ENABLE_CRL_CHECK)
if(hSession->ssl.crl.prefer)
{
--
libgit2 0.21.2