From 0669cde0aa80aed19ced0b75f2f8e6f8e41c37d4 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Wed, 29 Jul 2020 17:17:48 -0300 Subject: [PATCH] Refactoring network subsystem for modularity. --- lib3270.cbp | 4 ++++ src/core/connect.c | 40 +++++++++++++++++++++++++++++++++++++++- src/core/iocalls.c | 66 ++++++------------------------------------------------------------ src/core/linux/connect.c | 20 +++++++------------- src/core/model.c | 1 + src/core/rpq.c | 2 +- src/core/session.c | 7 +++---- src/core/telnet.c | 65 ++++++++++++++++++++++++++++++++++++++++------------------------- src/core/toggles/init.c | 22 ++++++++++------------ src/core/util.c | 3 ++- src/include/internals.h | 27 +++++++++++++++++++++++---- src/include/lib3270/session.h | 2 +- src/include/networking.h | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/include/telnetc.h | 2 +- src/network_modules/unsecure.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 472 insertions(+), 123 deletions(-) create mode 100644 src/include/networking.h create mode 100644 src/network_modules/unsecure.c diff --git a/lib3270.cbp b/lib3270.cbp index 06988b7..0e12ad8 100644 --- a/lib3270.cbp +++ b/lib3270.cbp @@ -271,6 +271,7 @@ + @@ -306,6 +307,9 @@ + + diff --git a/src/core/connect.c b/src/core/connect.c index 19c1543..afbc2f8 100644 --- a/src/core/connect.c +++ b/src/core/connect.c @@ -121,7 +121,7 @@ return 0; } - if(hSession->connection.sock > 0) + if(hSession->network.module->is_connected(hSession)) { errno = EISCONN; return 0; @@ -169,3 +169,41 @@ } + static int bg_start_tls(H3270 *hSession, void *message) + { + + } + + int lib3270_start_tls(H3270 *hSession) + { + int rc = 0; + + if(hSession->network.module->start_tls) + { + LIB3270_NETWORK_STATE state; + memset(&state,0,sizeof(state)); + + non_blocking(hSession,False); + + rc = lib3270_run_task( + hSession, + (int(*)(H3270 *h, void *)) hSession->network.module->start_tls, + &state + ); + + if(state.popup) { + if(lib3270_popup(hSession,state.popup,1)) { + lib3270_disconnect(hSession); + return rc; + } + + // User has selected "continue", ignore error. + return 0; + } + + } + + return rc; + } + + diff --git a/src/core/iocalls.c b/src/core/iocalls.c index 1138ca9..cb6e64e 100644 --- a/src/core/iocalls.c +++ b/src/core/iocalls.c @@ -299,19 +299,18 @@ 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) { if(id) - { - debug("%s: Polling on %d (%p) is %s",__FUNCTION__,session->connection.sock,id,(enabled ? "enabled" : "disabled")); set_poll_state(session, id, enabled); - } } LIB3270_EXPORT void lib3270_remove_poll_fd(H3270 *session, int fd) @@ -349,7 +348,7 @@ LIB3270_EXPORT void lib3270_update_poll_fd(H3270 *session, int fd, LIB3270_IO_FL } LIB3270_EXPORT void * lib3270_add_poll_fd(H3270 *session, int fd, LIB3270_IO_FLAG flag, void(*call)(H3270 *, int, LIB3270_IO_FLAG, void *), void *userdata ) { - debug("%s(%d)",__FUNCTION__,session->connection.sock); + debug("%s(%d)",__FUNCTION__,fd); return add_poll(session,fd,flag,call,userdata); } @@ -400,11 +399,10 @@ void x_except_on(H3270 *h) if(reading) lib3270_remove_poll(h,h->xio.read); - h->xio.except = lib3270_add_poll_fd(h,h->connection.sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0); + h->xio.except = h->network.module->add_poll(h,LIB3270_IO_FLAG_EXCEPTION,net_exception,0); if(reading) - h->xio.read = lib3270_add_poll_fd(h,h->connection.sock,LIB3270_IO_FLAG_READ,net_input,0); - debug("%s",__FUNCTION__); + h->xio.read = h->network.module->add_poll(h,LIB3270_IO_FLAG_READ,net_input,0); } @@ -522,61 +520,9 @@ LIB3270_EXPORT int lib3270_run_task(H3270 *hSession, int(*callback)(H3270 *h, vo int non_blocking(H3270 *hSession, Boolean on) { - - if(hSession->connection.sock < 0) + if(hSession->network.module->non_blocking,on) return 0; -#ifdef WIN32 - - WSASetLastError(0); - u_long iMode= on ? 1 : 0; - - if(ioctlsocket(hSession->connection.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->connection.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->connection.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->connection.sock,(on ? "Non Blocking" : "Blocking")); - lib3270_set_poll_state(hSession,hSession->xio.read, on); lib3270_set_poll_state(hSession,hSession->xio.write, on); lib3270_set_poll_state(hSession,hSession->xio.except, on); diff --git a/src/core/linux/connect.c b/src/core/linux/connect.c index 88b38ff..b8847b8 100644 --- a/src/core/linux/connect.c +++ b/src/core/linux/connect.c @@ -42,7 +42,7 @@ #include #include -#define SOCK_CLOSE(s) close(s->connection.sock); s->connection.sock = -1; +// #define SOCK_CLOSE(s) close(s->connection.sock); s->connection.sock = -1; #include @@ -69,7 +69,7 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG hSession->xio.write = NULL; } - if(getsockopt(hSession->connection.sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0) + if(hSession->network.module->getsockopt(hSession, SOL_SOCKET, SO_ERROR, (char *) &err, &len) < 0) { lib3270_disconnect(hSession); lib3270_popup_dialog( @@ -88,16 +88,11 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG return; } - hSession->xio.except = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_EXCEPTION,net_exception,0); - hSession->xio.read = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_READ,net_input,0); + 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 defined(HAVE_LIBSSL) - if(hSession->ssl.con && hSession->ssl.state == LIB3270_SSL_UNDEFINED) - { - if(ssl_negotiate(hSession)) - return; - } -#endif + if(lib3270_start_tls(hSession)) + return; lib3270_setup_session(hSession); lib3270_set_connected_initial(hSession); @@ -238,8 +233,7 @@ static void net_connected(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG lib3270_set_cstate(hSession, LIB3270_PENDING); lib3270_st_changed(hSession, LIB3270_STATE_HALF_CONNECT, True); - hSession->xio.write = lib3270_add_poll_fd(hSession,hSession->connection.sock,LIB3270_IO_FLAG_WRITE,net_connected,0); - // hSession->ns_write_id = AddOutput(hSession->sock, hSession, net_connected); + hSession->xio.write = hSession->network.module->add_poll(hSession,LIB3270_IO_FLAG_WRITE,net_connected,0); trace("%s: Connection in progress",__FUNCTION__); diff --git a/src/core/model.c b/src/core/model.c index 1abf682..870a9f7 100644 --- a/src/core/model.c +++ b/src/core/model.c @@ -28,6 +28,7 @@ */ #include + #include #include "screen.h" #include "ctlrc.h" #include "popupsc.h" diff --git a/src/core/rpq.c b/src/core/rpq.c index db0680f..4ce873f 100644 --- a/src/core/rpq.c +++ b/src/core/rpq.c @@ -690,7 +690,7 @@ static int get_rpq_address(H3270 *hSession, unsigned char *buf, const int maxlen void *src = NULL; int len = 0; - if(net_getsockname(hSession, &u, &addrlen) < 0) + if(hSession->network.module->getsockname(hSession, (struct sockaddr *) &u, &addrlen) < 0) return 0; SET16(buf, u.sa.sa_family); x += 2; diff --git a/src/core/session.c b/src/core/session.c index 16f5bbc..e8e53b9 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -74,7 +74,7 @@ void lib3270_session_free(H3270 *h) shutdown_toggles(h); -#ifdef SSL_ENABLE_CRL_CHECK +#if defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBSSL) if(h->ssl.crl.prefer) { free(h->ssl.crl.prefer); @@ -281,7 +281,7 @@ void lib3270_reset_callbacks(H3270 *hSession) memset(&hSession->cbk,0,sizeof(hSession->cbk)); hSession->cbk.write = lib3270_sock_send; - hSession->cbk.disconnect = lib3270_sock_disconnect; +// hSession->cbk.disconnect = lib3270_sock_disconnect; hSession->cbk.update = update_char; hSession->cbk.update_model = update_model; hSession->cbk.update_cursor = update_cursor; @@ -331,7 +331,6 @@ static void lib3270_session_init(H3270 *hSession, const char *model, const char hSession->unlock_delay = 1; hSession->icrnl = 1; hSession->onlcr = 1; - hSession->connection.sock = -1; hSession->model_num = -1; hSession->connection.state = LIB3270_NOT_CONNECTED; hSession->oia.status = -1; @@ -446,7 +445,7 @@ H3270 * lib3270_session_new(const char *model) hSession->ssl.protocol.max_version = 0; #endif // HAVE_LIBSSL -#ifdef SSL_ENABLE_CRL_CHECK +#if defined(SSL_ENABLE_CRL_CHECK) && defined(HAVE_LIBSSL) hSession->ssl.crl.download = 1; #endif // SSL_ENABLE_CRL_CHECK diff --git a/src/core/telnet.c b/src/core/telnet.c index 110ff32..2c35576 100644 --- a/src/core/telnet.c +++ b/src/core/telnet.c @@ -507,9 +507,11 @@ static void connection_complete(H3270 *session) } +/* LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession) { - trace("%s",__FUNCTION__); + LIB3270_NETWORK_STATE state; + memset(&state,0,sizeof(state)); #if defined(HAVE_LIBSSL) if(hSession->ssl.con != NULL) @@ -527,37 +529,47 @@ LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession) hSession->xio.write = 0; } - if(hSession->connection.sock >= 0) - { - shutdown(hSession->connection.sock, 2); - SOCK_CLOSE(hSession->connection.sock); - hSession->connection.sock = -1; - } + hSession->network.module->disconnect(hSession->network.context,hSession,&state); } +*/ /** - * @brief Shut down the socket. + * @brief Disconnect from host. */ -void net_disconnect(H3270 *session) +void net_disconnect(H3270 *hSession) { + LIB3270_NETWORK_STATE state; + memset(&state,0,sizeof(state)); + + // Disconnect from host #if defined(HAVE_LIBSSL) - set_ssl_state(session,LIB3270_SSL_UNSECURE); -#endif // HAVE_LIBSSL + if(hSession->ssl.con != NULL) + { + set_ssl_state(hSession,LIB3270_SSL_UNDEFINED); + SSL_shutdown(hSession->ssl.con); + SSL_free(hSession->ssl.con); + hSession->ssl.con = NULL; + } + else + { + set_ssl_state(hSession,LIB3270_SSL_UNSECURE); + } +#endif - session->cbk.disconnect(session); + if(hSession->xio.write) + { + lib3270_remove_poll(hSession, hSession->xio.write); + hSession->xio.write = 0; + } - trace_dsn(session,"SENT disconnect\n"); + hSession->network.module->disconnect(hSession,&state); - /* Restore terminal type to its default. */ - /* - if (session->termname == CN) - session->termtype = session->full_model_name; - */ + trace_dsn(hSession,"SENT disconnect\n"); // We're not connected to an LU any more. - session->lu.associated = CN; - status_lu(session,CN); + hSession->lu.associated = CN; + status_lu(hSession,CN); } @@ -618,8 +630,8 @@ void net_input(H3270 *hSession, int GNUC_UNUSED(fd), LIB3270_IO_FLAG GNUC_UNUSED for (;;) #endif { - if (hSession->connection.sock < 0) - return; +// if (hSession->connection.sock < 0) +// return; #if defined(X3270_ANSI) hSession->ansi_data = 0; @@ -629,9 +641,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 = recv(hSession->connection.sock, (char *) buffer, BUFSZ, 0); + nr = hSession->network.module->recv(hSession->network.context, buffer, BUFSZ); #else - nr = recv(hSession->connection.sock, (char *) buffer, BUFSZ, 0); + nr = hSession->network.module->recv(hSession->network.context, buffer, BUFSZ); #endif // HAVE_LIBSSL if (nr < 0) @@ -1637,7 +1649,7 @@ LIB3270_INTERNAL int lib3270_sock_send(H3270 *hSession, unsigned const char *buf else rc = send(hSession->connection.sock, (const char *) buf, len, 0); #else - rc = send(hSession->connection.sock, (const char *) buf, len, 0); + rc = hSession->network.module->send(hSession, buf, len); #endif // HAVE_LIBSSL if(rc > 0) @@ -2650,9 +2662,12 @@ void net_abort(H3270 *hSession) #endif /*]*/ /* Return the local address for the socket. */ + +/* int net_getsockname(const H3270 *session, void *buf, int *len) { if (session->connection.sock < 0) return -1; return getsockname(session->connection.sock, buf, (socklen_t *)(void *)len); } +*/ diff --git a/src/core/toggles/init.c b/src/core/toggles/init.c index 2564ef5..be02226 100644 --- a/src/core/toggles/init.c +++ b/src/core/toggles/init.c @@ -79,21 +79,19 @@ 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)) { - if(session->connection.sock > 0) - { - // Update keep-alive option - int optval = t->value ? 1 : 0; + // Update keep-alive option + int optval = t->value ? 1 : 0; - if (setsockopt(session->connection.sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) < 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 - { - trace_dsn(session,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" ); - } - } + else + { + trace_dsn(session,"Network keep-alive is %s\n",optval ? "enabled" : "disabled" ); + } + } static void toggle_connect(H3270 *hSession, const struct lib3270_toggle *toggle, LIB3270_TOGGLE_TYPE tt) diff --git a/src/core/util.c b/src/core/util.c index 32cc6d7..a00d02a 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -516,6 +516,7 @@ LIB3270_EXPORT LIB3270_POINTER lib3270_get_pointer(H3270 *hSession, int baddr) } +/* LIB3270_EXPORT int lib3270_getpeername(H3270 *hSession, struct sockaddr *addr, socklen_t *addrlen) { CHECK_SESSION_HANDLE(hSession); @@ -544,7 +545,7 @@ LIB3270_EXPORT int lib3270_getsockname(H3270 *hSession, struct sockaddr *addr, s return getsockname(hSession->connection.sock, addr, addrlen); } - +*/ static int xdigit_value(const char scanner) { diff --git a/src/include/internals.h b/src/include/internals.h index cffed11..40f2885 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -39,6 +39,7 @@ #include #include #include +#include #if defined(HAVE_LIBSSL) #include @@ -319,12 +320,22 @@ struct _h3270 { struct lib3270_session_callbacks cbk; ///< @brief Callback table - Always the first one. - // Session info - char id; ///< @brief Session Identifier. + /// @brief Session Identifier. + char id; + + // Network + struct { + + /// @brief Network module. + const LIB3270_NET_MODULE * module; + + /// @brief Network context. + LIB3270_NET_CONTEXT * context; + + } network; // Connection info struct { - int sock; ///< @brief Network socket. LIB3270_CSTATE state; ///< @brief Connection state. } connection; @@ -745,7 +756,7 @@ LIB3270_INTERNAL void toggle_rectselect(H3270 *session, const struct lib3270_tog LIB3270_INTERNAL void remove_input_calls(H3270 *session); LIB3270_INTERNAL int lib3270_sock_send(H3270 *hSession, unsigned const char *buf, int len); -LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession); +// LIB3270_INTERNAL void lib3270_sock_disconnect(H3270 *hSession); LIB3270_INTERNAL int lib3270_default_event_dispatcher(H3270 *hSession, int block); @@ -871,3 +882,11 @@ 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); + + diff --git a/src/include/lib3270/session.h b/src/include/lib3270/session.h index 3ff28af..e63a331 100644 --- a/src/include/lib3270/session.h +++ b/src/include/lib3270/session.h @@ -49,7 +49,7 @@ struct lib3270_session_callbacks { int (*write)(H3270 *hSession, unsigned const char *buf, int len); - void (*disconnect)(H3270 *hSession); +// void (*disconnect)(H3270 *hSession); void (*configure)(H3270 *session, unsigned short rows, unsigned short cols); void (*update)(H3270 *session, int baddr, unsigned char c, unsigned short attr, unsigned char cursor); diff --git a/src/include/networking.h b/src/include/networking.h new file mode 100644 index 0000000..ab73371 --- /dev/null +++ b/src/include/networking.h @@ -0,0 +1,141 @@ +/* + * "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 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) + * + */ + +#ifndef LIB3270_NETWORKING_H_INCLUDED + + #define LIB3270_NETWORKING_H_INCLUDED + + #include + #include + + typedef struct lib3270_network_state { + + int syserror; ///< @brief System error (errno) +#ifdef _WIN32 + DWORD winerror; ///< @brief Win32 error got from GetLastError() +#endif // _WIN32 + + const LIB3270_POPUP *popup; /// @brief Detailed info for popup. + + } LIB3270_NETWORK_STATE; + + typedef struct _lib3270_new_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); + + /// @brief Connect to host. + /// + /// @param context Network context. + /// @param hSession TN3270 session. + /// @param seconds Seconds for timeout. + /// @param state Pointer to state message. + /// + int (*connect)(H3270 *hSession, int seconds, LIB3270_NETWORK_STATE *state); + + /// @brief Disconnect from host. + /// + /// @param context Network context. + /// @param hSession TN3270 session. + /// @param state Pointer to state message. + /// + int (*disconnect)(H3270 *hSession, LIB3270_NETWORK_STATE *state); + + int (*start_tls)(H3270 *hSession, LIB3270_NETWORK_STATE *msg); + + /// @brief Send on network context. + /// + /// @return Positive on data received, negative on error. + /// + ssize_t (*send)(H3270 *hSession, const void *buffer, size_t length); + + /// @brief Receive on network context. + /// + /// @return Positive on data received, negative on error. + /// + /// @retval -ENOTCONN Not connected to host. + /// + ssize_t (*recv)(H3270 *hSession, void *buf, size_t len); + + /// @brief Add socket in poll list. + void * (*add_poll)(H3270 *hSession, LIB3270_IO_FLAG flag, void(*call)(H3270 *, int, LIB3270_IO_FLAG, void *), void *userdata); + + /// @brief Set non blocking mode. + /// + /// @retval 0 Not connected or Success. + /// @retval -1 Failed (popup was sent). + int (*non_blocking)(H3270 *hSession, const unsigned char on); + + /// @brief Check if the session is online. + /// + /// @retval 0 The session is offline. + int (*is_connected)(H3270 *hSession); + + /// @brief get socket name. + /// + /// @return On success, zero is returned. On error, -1 is returned, and errno is set appropriately. + /// + /// @retval 0 Success. + /// @retval -1 Error (errno is set). + 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); + + /// @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); + + +#endif // LIB3270_NETWORKING_H_INCLUDED + diff --git a/src/include/telnetc.h b/src/include/telnetc.h index b649dbd..689570a 100644 --- a/src/include/telnetc.h +++ b/src/include/telnetc.h @@ -62,4 +62,4 @@ LIB3270_INTERNAL void space3270out(H3270 *hSession, int n); #define trace_netdata(direction, buf, len) /* */ #endif // X3270_TRACE -LIB3270_INTERNAL int net_getsockname(const H3270 *h3270, void *buf, int *len); +// LIB3270_INTERNAL int net_getsockname(const H3270 *h3270, void *buf, int *len); diff --git a/src/network_modules/unsecure.c b/src/network_modules/unsecure.c new file mode 100644 index 0000000..998e1eb --- /dev/null +++ b/src/network_modules/unsecure.c @@ -0,0 +1,193 @@ +/* + * "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 + #ifdef _WIN32 + #include + #include + #endif // _WIN32 + + #include + #include + + struct _lib3270_new_context { + int sock; + }; + + LIB3270_NET_CONTEXT * unsecure_network_init(H3270 *hSession, LIB3270_NETWORK_STATE *state) { + + LIB3270_NET_CONTEXT * context = lib3270_malloc(sizeof(LIB3270_NET_CONTEXT)); + + context->sock = -1; + + return context; + } + + 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) { + + debug("%s",__FUNCTION__); + if(context->sock >= 0) { + shutdown(hSession.network.context->sock, 2); + close(hSession->network.context->sock); + hSession.network.context->sock = -1; + } + +} + +ssize_t unsecure_network_send(H3270 *hSession, const void *buffer, size_t length) { + + if(hSession->network.context->sock < 0) { + return -(errno = ENOTCONN); + } + + ssize_t bytes = send(hSession->network.context->sock,buffer,length,0); + + if(bytes < 0) + return -errno; + + return 0; +} + +ssize_t unsecure_network_recv(H3270 *hSession, void *buf, size_t len) { + + if(hSession->network.context->sock < 0) { + return -(errno = ENOTCONN); + } + + ssize_t bytes = recv(hSession->network.context->sock, (char *) buffer, len, 0); + + if(bytes < 0) { + return -errno; + } + + return bytes; +} + +int unsecure_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); +} + +void * unsecure_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) { + + 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")); + +} + +int unsecure_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) { + + if(hSession->network.context.sock < 0) { + errno = ENOTCONN; + return -1; + } + + return setsockopt(hSession->network.context.sock, level, optname, optval, optlen); + +} + +int unsecure_getsockopt(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen) { + + if(hSession->network.context.sock < 0) { + errno = ENOTCONN; + return -1; + } + + return getsockopt(hSession->network.context.sock, level, optname, optval, optlen) +} -- libgit2 0.21.2