Comments (6)
Hello. TLSe wants to be transport layer agnostic. The SSL_* functions are just for a basic level of support/testing. You should really use the tls_* interface, which enables you to write your own write function. See tlsclienthello.c:
int send_pending(int client_sock, struct TLSContext *context) {
unsigned int out_buffer_len = 0;
const unsigned char *out_buffer = tls_get_write_buffer(context, &out_buffer_len);
unsigned int out_buffer_index = 0;
int send_res = 0;
while ((out_buffer) && (out_buffer_len > 0)) {
int res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);
if (res <= 0) {
send_res = res;
break;
}
out_buffer_len -= res;
out_buffer_index += res;
}
tls_buffer_clear(context);
return send_res;
}
In my applications, I'm always using epoll/poll/select to check the write-status of the socket.
from tlse.
This issue is not related to a transport level only. You are clearly using system functions "send" and "recv" in _tls_ssl_private_send_pending (and in your example send_pending), therefore you should expect and process some error codes. Imagine the following situation:
_tls_ssl_private_send_pending (or send_pending) was able to send a part of the buffer, then received EINTR or EAGAIN. In reality - nothing happened. For some reason the system just wants you to retry your attempt. But the method will return error code instead. From user point of view, the only legit reaction is to close the connection, which is wrong.
See more here:
https://unix.stackexchange.com/questions/253349/eintr-is-there-a-rationale-behind-it
from tlse.
I understand the idea, but as I said, EAGAIN and EINTR are transport-layer specific. EAGAIN is set by send(transport layer). Assuming that a the TCP send buffer is full, you may get EAGAIN for a long time. TLSe deals only with the TLS layer. I wanted to be extremely portable and lightweight. The socket layer should be managed by you. As you posted, it is extremely simple to alter send_pending
to suit your needs. send_pending isn't part of TLSe, is just an example. You may opt to manage EAGAIN by simply cheching errno or WSAGetLastError ("Error codes set by Windows Sockets are not made available through the errno variable"). I strongly advise you to use tls_* interface instead of SSL_*. When using tls_* you explicitly manage the I/O, see: https://github.com/eduardsui/tlse/blob/master/examples/tlshelloworld.c. In the send_pending
function you may check for EAGAIN.
You may replace standard send/recv functions by using SSL_set_io
. You may simply rewrite send_cb at your convenience.
I think the correct implementation should look something like this (not tested):
int _tls_ssl_private_send_pending(int client_sock, struct TLSContext *context) {
unsigned int out_buffer_len = 0;
const unsigned char *out_buffer = tls_get_write_buffer(context, &out_buffer_len);
unsigned int out_buffer_index = 0;
int send_res = 0;
SOCKET_SEND_CALLBACK write_cb = NULL;
SSLUserData *ssl_data = (SSLUserData *)context->user_data;
if (ssl_data)
write_cb = (SOCKET_SEND_CALLBACK)ssl_data->send;
while ((out_buffer) && (out_buffer_len > 0)) {
int res;
if (write_cb)
res = write_cb(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);
else
res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);
if (res <= 0) {
if ((!write_cb) && (res < 0)) {
#ifdef _WIN32
if (WSAGetLastError() == EAGAIN) {
context->tls_buffer_len = out_buffer_len;
memmove(context->tls_buffer, out_buffer + out_buffer_index, out_buffer_len);
return res;
}
#else
if ((errno == EAGAIN) || (errno == EINTR)) {
context->tls_buffer_len = out_buffer_len;
memmove(context->tls_buffer, out_buffer + out_buffer_index, out_buffer_len);
return res;
}
#endif
}
send_res = res;
break;
}
out_buffer_len -= res;
out_buffer_index += res;
send_res += res;
}
tls_buffer_clear(context);
return send_res;
}
This will transparently pass errno to the application code to be managed there.
Also, as a side note, using poll to manage I/O provides huge advantages, especially in asynchronous implementations.
from tlse.
If you want to keep external interface portable, you can return your own error code. OpenSSL returns SSL_ERROR_SYSCALL from SSL_get_error in such case.
from tlse.
Trying to compile samples in latest master I get this (under WSL)
wqw@wqw-pc:~/tlse/examples$ gcc tlshelloworld.c -o tlshelloworld -DTLS_AMALGAMATION
In file included from tlshelloworld.c:1:0:
../tlse.c: In function ‘_tls_ssl_private_send_pending’:
../tlse.c:10100:22: error: ‘errno’ undeclared (first use in this function)
if ((errno == EAGAIN) || (errno == EINTR)) {
^
../tlse.c:10100:22: note: each undeclared identifier is reported only once for each function it appears in
../tlse.c:10100:31: error: ‘EAGAIN’ undeclared (first use in this function)
if ((errno == EAGAIN) || (errno == EINTR)) {
^
../tlse.c:10100:52: error: ‘EINTR’ undeclared (first use in this function)
if ((errno == EAGAIN) || (errno == EINTR)) {
^
tlshelloworld.c: In function ‘main’:
tlshelloworld.c:192:45: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 4 has type ‘struct TLSContext *’ [-Wformat=]
fprintf(stderr, "Imported context (size: %i): %x\n", size, imported_context);
from tlse.
I forgot to include errno.h. Thanks.
E.
from tlse.
Related Issues (20)
- Failure to notice incorrect handshake on SSL_connect
- TLS 1.3 server incompatible with openssl
- LTC_ARGCHK 'b != NULL' HOT 3
- Support for latest libtomcrypt HOT 5
- SSL_read function strange behavior vs openssl's SSL_read HOT 1
- Merge into tomcrypt HOT 2
- what is "for semantic compatibility" means? HOT 1
- Examples expects testcert folder. HOT 1
- HTTPS Server wont respond when using ECDHE-RSA-AES256GCM-SHA384 cipher HOT 1
- Growtopia wont respond when using TLSe HOT 14
- Async sockets. HOT 5
- Tomcrypt version HOT 2
- Is its possible to make HTTPS Proxy using TLSe? HOT 3
- A website using Cloudflare is giving me 403 when using test client code, but works with Chrome, why? HOT 5
- TLSE fails to contact Cloudflare server, where curl works fine, I eliminated every cause I could think of HOT 8
- How do i set TLSe Client Cipher? HOT 2
- TLS 1.3: Early data
- CHECK_SIZE in tls_parse_verify_tls13 HOT 11
- Examples: tlshelloworld.c, tls_read or recv? HOT 1
- CANNOT READ CERTIFICATE and ALERT MESSAGE ERROR HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tlse.