Commit 0f98ce19fe66a4af2b6b4faa1cbfcf874d777ff9

Authored by Perry Werneck
1 parent 699d861e

SSL networking is now modular.

lib3270.cbp
... ... @@ -337,7 +337,7 @@
337 337 <Unit filename="src/network_modules/state.c">
338 338 <Option compilerVar="CC" />
339 339 </Unit>
340   - <Unit filename="src/network_modules/translate.c">
  340 + <Unit filename="src/network_modules/tools.c">
341 341 <Option compilerVar="CC" />
342 342 </Unit>
343 343 <Unit filename="src/selection/actions.c">
... ...
src/core/host.c
... ... @@ -388,13 +388,14 @@ LIB3270_EXPORT int lib3270_set_url(H3270 *h, const char *n)
388 388 { 0, "telnet://", "telnet" }
389 389  
390 390 };
  391 + int f;
391 392 */
  393 +
392 394 lib3270_autoptr(char) str = strdup(n);
393 395 char * hostname = lib3270_set_network_module_from_url(h,str);
394 396 const char * srvc;
395 397 char * ptr;
396 398 char * query = "";
397   - int f;
398 399  
399 400 trace("%s(%s)",__FUNCTION__,str);
400 401  
... ...
src/include/networking.h
... ... @@ -177,7 +177,7 @@
177 177 * @retval -EAGAIN Try again.
178 178 *
179 179 */
180   - LIB3270_INTERNAL int lib3270_network_recv_failed(H3270 *hSession);
  180 + LIB3270_INTERNAL int lib3270_socket_recv_failed(H3270 *hSession);
181 181  
182 182 /**
183 183 * @brief Translate system socket send error codes, show popup if needed.
... ... @@ -187,7 +187,9 @@
187 187 * @return Translated error code.
188 188 *
189 189 */
190   - LIB3270_INTERNAL int lib3270_network_send_failed(H3270 *hSession);
  190 + LIB3270_INTERNAL int lib3270_socket_send_failed(H3270 *hSession);
  191 +
  192 + LIB3270_INTERNAL int lib3270_socket_set_non_blocking(H3270 *hSession, int sock, const unsigned char on);
191 193  
192 194 /**
193 195 * @breif Select the network context from URL.
... ... @@ -195,7 +197,8 @@
195 197 * @return Pointer to the hostname or NULL if failed (sets errno).
196 198 *
197 199 */
198   - LIB3270_INTERNAL const char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url);
  200 + LIB3270_INTERNAL char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url);
  201 +
199 202  
200 203 /**
201 204 * @brief Select the default (unsecure) network context.
... ... @@ -205,6 +208,10 @@
205 208 */
206 209 LIB3270_INTERNAL void lib3270_set_default_network_module(H3270 *hSession);
207 210  
  211 +#ifdef HAVE_LIBSSL
  212 + LIB3270_INTERNAL void lib3270_set_libssl_network_module(H3270 *hSession);
  213 +#endif // HAVE_LIBSSL
  214 +
208 215 LIB3270_INTERNAL int lib3270_activate_ssl_network_module(H3270 *hSession, int sock);
209 216  
210 217 #endif // LIB3270_NETWORKING_H_INCLUDED
... ...
src/network_modules/default/main.c
... ... @@ -33,7 +33,6 @@
33 33 */
34 34  
35 35 #include "private.h"
36   - #include <fcntl.h>
37 36  
38 37 static void unsecure_network_finalize(H3270 *hSession) {
39 38  
... ... @@ -70,7 +69,7 @@
70 69 if(bytes >= 0)
71 70 return bytes;
72 71  
73   - return lib3270_network_send_failed(hSession);
  72 + return lib3270_socket_send_failed(hSession);
74 73  
75 74 }
76 75  
... ... @@ -82,7 +81,7 @@
82 81 return bytes;
83 82 }
84 83  
85   - return lib3270_network_recv_failed(hSession);
  84 + return lib3270_socket_recv_failed(hSession);
86 85  
87 86 }
88 87  
... ... @@ -95,62 +94,7 @@ static void * unsecure_network_add_poll(H3270 *hSession, LIB3270_IO_FLAG flag, v
95 94 }
96 95  
97 96 static int unsecure_network_non_blocking(H3270 *hSession, const unsigned char on) {
98   -
99   - if(hSession->network.context->sock < 0)
100   - return 0;
101   -
102   -#ifdef WIN32
103   -
104   - WSASetLastError(0);
105   - u_long iMode= on ? 1 : 0;
106   -
107   - if(ioctlsocket(hSession->network.context->sock,FIONBIO,&iMode))
108   - {
109   - lib3270_popup_dialog( hSession,
110   - LIB3270_NOTIFY_ERROR,
111   - _( "Connection error" ),
112   - _( "ioctlsocket(FIONBIO) failed." ),
113   - "%s", lib3270_win32_strerror(GetLastError()));
114   - return -1;
115   - }
116   -
117   -#else
118   -
119   - int f;
120   -
121   - if ((f = fcntl(hSession->network.context->sock, F_GETFL, 0)) == -1)
122   - {
123   - lib3270_popup_dialog( hSession,
124   - LIB3270_NOTIFY_ERROR,
125   - _( "Socket error" ),
126   - _( "fcntl() error when getting socket state." ),
127   - _( "%s" ), strerror(errno)
128   - );
129   -
130   - return -1;
131   - }
132   -
133   - if (on)
134   - f |= O_NDELAY;
135   - else
136   - f &= ~O_NDELAY;
137   -
138   - if (fcntl(hSession->network.context->sock, F_SETFL, f) < 0)
139   - {
140   - lib3270_popup_dialog( hSession,
141   - LIB3270_NOTIFY_ERROR,
142   - _( "Socket error" ),
143   - on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
144   - _( "%s" ), strerror(errno)
145   - );
146   - return -1;
147   - }
148   -
149   -#endif
150   -
151   - debug("Socket %d is now %s",hSession->network.context->sock,(on ? "Non Blocking" : "Blocking"));
152   -
153   - return 0;
  97 + return lib3270_socket_set_non_blocking(hSession, hSession->network.context->sock, on);
154 98 }
155 99  
156 100 static int unsecure_network_is_connected(const H3270 *hSession) {
... ...
src/network_modules/openssl/main.c
... ... @@ -79,45 +79,102 @@ static int openssl_network_disconnect(H3270 *hSession) {
79 79  
80 80 ssize_t openssl_network_send(H3270 *hSession, const void *buffer, size_t length) {
81 81  
82   -/*
83   - if(hSession->network.context->sock < 0) {
84   - return -(errno = ENOTCONN);
  82 + int rc = SSL_write(hSession->network.context->con, (const char *) buffer, length);
  83 + if(rc > 0)
  84 + return rc;
  85 +
  86 + // https://www.openssl.org/docs/man1.0.2/man3/SSL_get_error.html
  87 + int ssl_error = SSL_get_error(hSession->network.context->con, rc);
  88 + switch(ssl_error) {
  89 + case SSL_ERROR_ZERO_RETURN:
  90 +
  91 + trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
  92 +
  93 + lib3270_popup_dialog(
  94 + hSession,
  95 + LIB3270_NOTIFY_ERROR,
  96 + NULL,
  97 + _("Disconnected from host"),
  98 + "%s",
  99 + _("The secure connection has been closed cleanly.")
  100 + );
  101 + return 0;
  102 +
  103 + case SSL_ERROR_WANT_READ:
  104 + case SSL_ERROR_WANT_X509_LOOKUP:
  105 + return -EWOULDBLOCK; // Force a new loop.
  106 +
  107 + case SSL_ERROR_SYSCALL:
  108 + return lib3270_socket_send_failed(hSession);
  109 +
85 110 }
86 111  
87   - ssize_t bytes = SSL_write(hSession->network.context->con, (const char *) buffer, length);
  112 + // Build error message.
  113 + char err_buf[120];
  114 + (void) ERR_error_string(ssl_error, err_buf);
  115 + trace_dsn(hSession,"RCVD SSL_write error %d (%s)\n", ssl_error, err_buf);
88 116  
89   - debug("%s bytes=%d",__FUNCTION__,(int) bytes);
  117 + lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf);
90 118  
91   - if(bytes >= 0)
92   - return bytes;
  119 + LIB3270_POPUP popup = {
  120 + .summary = _("Error writing to host"),
  121 + .body = body
  122 + };
93 123  
94   - // SSL Write has failed, using SSL_get_error to identify what has happened.
95   - int error = SSL_get_error(hSession->network.context->con,(int) bytes);
  124 + lib3270_popup(hSession,&popup,0);
96 125  
97   - if(error == SSL_ERROR_SYSCALL) {
  126 + return -1;
98 127  
99   - #error Use errno!
  128 +}
100 129  
101   - return -1;
  130 +static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
  131 +
  132 + int rc = SSL_read(hSession->network.context->con, (char *) buf, len);
  133 + if(rc > 0) {
  134 + return rc;
102 135 }
103 136  
104   - // Not a system error, inspects the result.
  137 + // https://www.openssl.org/docs/man1.0.2/man3/SSL_get_error.html
  138 + int ssl_error = SSL_get_error(hSession->network.context->con, rc);
  139 + switch(ssl_error) {
  140 + case SSL_ERROR_ZERO_RETURN:
105 141  
  142 + trace_ssl(hSession,"%s","The secure connection has been closed cleanly");
106 143  
  144 + lib3270_popup_dialog(
  145 + hSession,
  146 + LIB3270_NOTIFY_ERROR,
  147 + NULL,
  148 + _("Disconnected from host"),
  149 + "%s",
  150 + _("The secure connection has been closed cleanly.")
  151 + );
  152 + return 0;
107 153  
108   - lib3270_popup(hSession,&popup,0);
  154 + case SSL_ERROR_WANT_READ:
  155 + case SSL_ERROR_WANT_X509_LOOKUP:
  156 + return -EWOULDBLOCK; // Force a new loop.
109 157  
110   - return -1;
111   -*/
  158 + case SSL_ERROR_SYSCALL:
  159 + return lib3270_socket_recv_failed(hSession);
112 160  
113   -}
  161 + }
114 162  
115   -static ssize_t openssl_network_recv(H3270 *hSession, void *buf, size_t len) {
  163 + // Build error message.
  164 + char err_buf[120];
  165 + (void) ERR_error_string(ssl_error, err_buf);
  166 + trace_dsn(hSession,"RCVD SSL_read error %d (%s)\n", ssl_error, err_buf);
116 167  
117   -// return SSL_read(hSession->network.context->con, (char *) buf, len);
  168 + lib3270_autoptr(char) body = lib3270_strdup_printf(_("The SSL error message was %s"), err_buf);
118 169  
  170 + LIB3270_POPUP popup = {
  171 + .summary = _("Error reading from host"),
  172 + .body = body
  173 + };
119 174  
  175 + lib3270_popup(hSession,&popup,0);
120 176  
  177 + return -1;
121 178 }
122 179  
123 180 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
125 182 }
126 183  
127 184 static void * openssl_network_add_poll(H3270 *hSession, LIB3270_IO_FLAG flag, void(*call)(H3270 *, int, LIB3270_IO_FLAG, void *), void *userdata) {
128   -
  185 + return lib3270_add_poll_fd(hSession,hSession->network.context->sock,flag,call,userdata);
129 186 }
130 187  
131 188 static int openssl_network_non_blocking(H3270 *hSession, const unsigned char on) {
132   -
  189 + return lib3270_socket_set_non_blocking(hSession, hSession->network.context->sock, on);
133 190 }
134 191  
135   -static int openssl_network_is_connected(H3270 *hSession) {
136   -
  192 +static int openssl_network_is_connected(const H3270 *hSession) {
  193 + return hSession->network.context->sock > 0;
137 194 }
138 195  
139 196 static int openssl_network_setsockopt(H3270 *hSession, int level, int optname, const void *optval, size_t optlen) {
140   -
  197 + return setsockopt(hSession->network.context->sock, level, optname, optval, optlen);
141 198 }
142 199  
143 200 static int openssl_network_getsockopt(H3270 *hSession, int level, int optname, void *optval, socklen_t *optlen) {
  201 + return getsockopt(hSession->network.context->sock, level, optname, optval, optlen);
144 202 }
145 203  
146 204 static int openssl_network_init(H3270 *hSession) {
... ... @@ -151,8 +209,6 @@ static int openssl_network_init(H3270 *hSession) {
151 209 if(!ctx_context)
152 210 return -1;
153 211  
154   - LIB3270_NET_CONTEXT * context = hSession->network.context;
155   -
156 212 return 0;
157 213 }
158 214  
... ... @@ -202,11 +258,13 @@ static int openssl_network_connect(H3270 *hSession, LIB3270_NETWORK_STATE *state
202 258 hSession->ssl.host = 1;
203 259 context->sock = lib3270_network_connect(hSession, state);
204 260  
  261 + debug("%s: sock=%d",__FUNCTION__,context->sock);
  262 +
205 263 return (context->sock < 0 ? -1 : 0);
206 264  
207 265 }
208 266  
209   -void lib3270_set_openssl_network_module(H3270 *hSession) {
  267 +void lib3270_set_libssl_network_module(H3270 *hSession) {
210 268  
211 269 static const LIB3270_NET_MODULE module = {
212 270 .name = "tn3270s",
... ... @@ -244,7 +302,7 @@ void lib3270_set_openssl_network_module(H3270 *hSession) {
244 302  
245 303 int lib3270_activate_ssl_network_module(H3270 *hSession, int sock) {
246 304  
247   - lib3270_set_openssl_network_module(hSession);
  305 + lib3270_set_libssl_network_module(hSession);
248 306  
249 307 int rc = openssl_network_init(hSession);
250 308  
... ... @@ -261,3 +319,5 @@ void lib3270_openssl_crl_free(LIB3270_NET_CONTEXT *context) {
261 319 }
262 320 }
263 321  
  322 +
  323 +
... ...
src/network_modules/select.c
... ... @@ -18,7 +18,7 @@
18 18 * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
19 19 * St, Fifth Floor, Boston, MA 02110-1301 USA
20 20 *
21   - * Este programa está nomeado como unsecure.c e possui - linhas de código.
  21 + * Este programa está nomeado como - e possui - linhas de código.
22 22 *
23 23 * Contatos:
24 24 *
... ... @@ -41,14 +41,24 @@
41 41  
42 42 /*--[ Implement ]------------------------------------------------------------------------------------*/
43 43  
44   - const char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url) {
  44 + char * lib3270_set_network_module_from_url(H3270 *hSession, const char *url) {
45 45  
46 46 static const struct {
47 47 const char *scheme; ///< @brief URL scheme for module.
48 48 void (*activate)(H3270 *hSession); ///< @brief Selection method.
49 49 } modules[] = {
50 50  
51   - { "tn3270://", lib3270_set_default_network_module },
  51 + { "tn3270://", lib3270_set_default_network_module },
  52 +
  53 +#ifdef HAVE_LIBSSL
  54 +
  55 + { "tn3270s://", lib3270_set_libssl_network_module },
  56 +
  57 + // Compatibility schemes.
  58 + { "L://", lib3270_set_libssl_network_module },
  59 + { "L:", lib3270_set_libssl_network_module },
  60 +
  61 +#endif // HAVE_LIBSSL
52 62  
53 63 };
54 64  
... ...
src/network_modules/tools.c 0 → 100644
... ... @@ -0,0 +1,214 @@
  1 +/*
  2 + * "Software PW3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral ', conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como unsecure.c e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça)
  27 + *
  28 + */
  29 +
  30 + /**
  31 + * @brief Common methods for send/recv errors.
  32 + *
  33 + */
  34 +
  35 + #include <config.h>
  36 + #include <lib3270.h>
  37 + #include <lib3270/log.h>
  38 + #include <internals.h>
  39 + #include <networking.h>
  40 + #include <fcntl.h>
  41 +
  42 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  43 +
  44 + int lib3270_socket_recv_failed(H3270 *hSession) {
  45 +
  46 +#ifdef _WIN32
  47 +
  48 + int wsaError = WSAGetLastError();
  49 +
  50 + // EWOULDBLOCK & EAGAIN should return directly.
  51 + if(wsaError == WSAEWOULDBLOCK)
  52 + return -EWOULDBLOCK;
  53 +
  54 + if(wsaError == WSAEINPROGRESS)
  55 + return -EAGAIN;
  56 +
  57 + int rc = -wsaError;
  58 +
  59 + LIB3270_POPUP popup = {
  60 + .name = "RecvFailed",
  61 + .type = LIB3270_NOTIFY_ERROR,
  62 + .summary = _("Error receiving data from host"),
  63 + }
  64 +
  65 + // TODO: Translate WSA Error, update message body.
  66 +
  67 + lib3270_popup(hSession,&popup,0);
  68 +
  69 +#else
  70 +
  71 + // EWOULDBLOCK & EAGAIN should return directly.
  72 + if(errno == EWOULDBLOCK || errno == EAGAIN)
  73 + return -errno;
  74 +
  75 + // Network error, notify user
  76 + int rc = -errno;
  77 +
  78 + lib3270_autoptr(char) body = lib3270_strdup_printf(
  79 + _("The system error code was %d (%s)"),
  80 + errno,
  81 + strerror(errno)
  82 + );
  83 +
  84 + LIB3270_POPUP popup = {
  85 + .name = "RecvFailed",
  86 + .type = LIB3270_NOTIFY_ERROR,
  87 + .summary = _("Error receiving data from host"),
  88 + .body = body
  89 + };
  90 +
  91 + lib3270_popup(hSession,&popup,0);
  92 +
  93 +#endif // _WIN32
  94 +
  95 + return rc;
  96 +
  97 + }
  98 +
  99 + int lib3270_socket_send_failed(H3270 *hSession) {
  100 +
  101 + #ifdef _WIN32
  102 +
  103 + int rc = WSAGetLastError();
  104 +
  105 + #error Have work to do.
  106 +
  107 + #else
  108 +
  109 + int rc = errno;
  110 +
  111 + switch(rc) {
  112 + case EPIPE:
  113 + lib3270_popup_dialog(
  114 + hSession,
  115 + LIB3270_NOTIFY_ERROR,
  116 + NULL,
  117 + _("Broken pipe"),
  118 + _("The system error code was %d"),
  119 + rc
  120 + );
  121 + break;
  122 +
  123 + case ECONNRESET:
  124 + lib3270_popup_dialog(
  125 + hSession,
  126 + LIB3270_NOTIFY_ERROR,
  127 + NULL,
  128 + _("Connection reset by peer"),
  129 + _("The system error code was %d"),
  130 + rc
  131 + );
  132 + break;
  133 +
  134 + case EINTR:
  135 + return 0;
  136 +
  137 + default:
  138 + lib3270_popup_dialog(
  139 + hSession,
  140 + LIB3270_NOTIFY_ERROR,
  141 + NULL,
  142 + _("Unexpected error writing to network socket"),
  143 + _("The system error code was %d (%s)"),
  144 + rc, strerror(rc)
  145 + );
  146 +
  147 + }
  148 +
  149 +
  150 + #endif // _WIN32
  151 +
  152 + return -1;
  153 +
  154 + }
  155 +
  156 +int lib3270_socket_set_non_blocking(H3270 *hSession, int sock, const unsigned char on) {
  157 +
  158 + if(sock < 0)
  159 + return 0;
  160 +
  161 +#ifdef WIN32
  162 +
  163 + WSASetLastError(0);
  164 + u_long iMode= on ? 1 : 0;
  165 +
  166 + if(ioctlsocket(sock,FIONBIO,&iMode))
  167 + {
  168 + lib3270_popup_dialog( hSession,
  169 + LIB3270_NOTIFY_ERROR,
  170 + _( "Connection error" ),
  171 + _( "ioctlsocket(FIONBIO) failed." ),
  172 + "%s", lib3270_win32_strerror(GetLastError()));
  173 + return -1;
  174 + }
  175 +
  176 +#else
  177 +
  178 + int f;
  179 +
  180 + if ((f = fcntl(sock, F_GETFL, 0)) == -1)
  181 + {
  182 + lib3270_popup_dialog( hSession,
  183 + LIB3270_NOTIFY_ERROR,
  184 + _( "Socket error" ),
  185 + _( "fcntl() error when getting socket state." ),
  186 + _( "%s" ), strerror(errno)
  187 + );
  188 +
  189 + return -1;
  190 + }
  191 +
  192 + if (on)
  193 + f |= O_NDELAY;
  194 + else
  195 + f &= ~O_NDELAY;
  196 +
  197 + if (fcntl(sock, F_SETFL, f) < 0)
  198 + {
  199 + lib3270_popup_dialog( hSession,
  200 + LIB3270_NOTIFY_ERROR,
  201 + _( "Socket error" ),
  202 + on ? _( "Can't set socket to blocking mode." ) : _( "Can't set socket to non blocking mode" ),
  203 + _( "%s" ), strerror(errno)
  204 + );
  205 + return -1;
  206 + }
  207 +
  208 +#endif
  209 +
  210 + debug("Socket %d is now %s",sock,(on ? "Non Blocking" : "Blocking"));
  211 +
  212 + return 0;
  213 +
  214 +}
... ...
src/network_modules/translate.c
... ... @@ -1,151 +0,0 @@
1   -/*
2   - * "Software PW3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
3   - * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
4   - * aplicativos mainframe. Registro no INPI sob o nome G3270.
5   - *
6   - * Copyright (C) <2008> <Banco do Brasil S.A.>
7   - *
8   - * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
9   - * os termos da GPL v.2 - Licença Pública Geral ', conforme publicado pela
10   - * Free Software Foundation.
11   - *
12   - * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
13   - * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
14   - * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
15   - * obter mais detalhes.
16   - *
17   - * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
18   - * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
19   - * St, Fifth Floor, Boston, MA 02110-1301 USA
20   - *
21   - * Este programa está nomeado como unsecure.c e possui - linhas de código.
22   - *
23   - * Contatos:
24   - *
25   - * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
26   - * erico.mendonca@gmail.com (Erico Mascarenhas de Mendonça)
27   - *
28   - */
29   -
30   - /**
31   - * @brief Common methods for send/recv errors.
32   - *
33   - */
34   -
35   - #include <config.h>
36   - #include <lib3270.h>
37   - #include <lib3270/log.h>
38   - #include <internals.h>
39   - #include <networking.h>
40   -
41   -/*--[ Implement ]------------------------------------------------------------------------------------*/
42   -
43   - int lib3270_network_recv_failed(H3270 *hSession) {
44   -
45   -#ifdef _WIN32
46   -
47   - int wsaError = WSAGetLastError();
48   -
49   - // EWOULDBLOCK & EAGAIN should return directly.
50   - if(wsaError == WSAEWOULDBLOCK)
51   - return -EWOULDBLOCK;
52   -
53   - if(wsaError == WSAEINPROGRESS)
54   - return -EAGAIN;
55   -
56   - int rc = -wsaError;
57   -
58   - LIB3270_POPUP popup = {
59   - .name = "RecvFailed",
60   - .type = LIB3270_NOTIFY_ERROR,
61   - .summary = _("Error receiving data from host"),
62   - }
63   -
64   - // TODO: Translate WSA Error, update message body.
65   -
66   - lib3270_popup(hSession,&popup,0);
67   -
68   -#else
69   -
70   - // EWOULDBLOCK & EAGAIN should return directly.
71   - if(errno == EWOULDBLOCK || errno == EAGAIN)
72   - return -errno;
73   -
74   - // Network error, notify user
75   - int rc = -errno;
76   -
77   - lib3270_autoptr(char) body = lib3270_strdup_printf(
78   - _("The system error code was %d (%s)"),
79   - errno,
80   - strerror(errno)
81   - );
82   -
83   - LIB3270_POPUP popup = {
84   - .name = "RecvFailed",
85   - .type = LIB3270_NOTIFY_ERROR,
86   - .summary = _("Error receiving data from host"),
87   - .body = body
88   - };
89   -
90   - lib3270_popup(hSession,&popup,0);
91   -
92   -#endif // _WIN32
93   -
94   - return rc;
95   -
96   - }
97   -
98   - int lib3270_network_send_failed(H3270 *hSession) {
99   -
100   - #ifdef _WIN32
101   -
102   - int rc = WSAGetLastError();
103   -
104   - #error Have work to do.
105   -
106   - #else
107   -
108   - int rc = errno;
109   -
110   - switch(rc) {
111   - case EPIPE:
112   - lib3270_popup_dialog(
113   - hSession,
114   - LIB3270_NOTIFY_ERROR,
115   - NULL,
116   - _("Broken pipe"),
117   - _("The system error code was %d"),
118   - rc
119   - );
120   - break;
121   -
122   - case ECONNRESET:
123   - lib3270_popup_dialog(
124   - hSession,
125   - LIB3270_NOTIFY_ERROR,
126   - NULL,
127   - _("Connection reset by peer"),
128   - _("The system error code was %d"),
129   - rc
130   - );
131   - break;
132   -
133   - case EINTR:
134   - return 0;
135   -
136   - default:
137   - lib3270_popup_dialog(
138   - hSession,
139   - LIB3270_NOTIFY_ERROR,
140   - NULL,
141   - _("Unexpected error writing to network socket"),
142   - _("The system error code was %d (%s)"),
143   - rc, strerror(rc)
144   - );
145   -
146   - }
147   -
148   -
149   - #endif // _WIN32
150   -
151   - }