Page 2 of 4
Re: Client/Server TCP TLS communication problem
Posted: Tue Mar 18, 2025 9:54 pm
by idle
HeX0R wrote: Tue Mar 18, 2025 2:20 pm
It's really time for a native GetNetworkError() function.
It's more or less impossible to write a server without it.
PB could wrap the error check so a -1 returned from send or receive actually means bail out and close
but I still have a questions how does it deal with the returns from send and recv?
A socket will return
n bytes processed
-1 on error
0 when the connection is broken
@Fred
is ReceiveNetworkData just a plain alias to recv() and returns whatever recv() returns ?
Re: Client/Server TCP TLS communication problem
Posted: Thu Mar 20, 2025 2:12 pm
by tatanas
More of my tests, the results are strange...
I tested with a small string (25 bytes) sent by a client to the server (TLS1.3).
It can work fine for (like) 10 OpenNetworkConnection()+SendNetworkString() : the server receives 3 #PB_NetworkEvent_Data, ReceiveNetworkData returns -2 for the two first event and the third contains the data.
But during the 11th SendNetworkString(), the server receives only one #PB_NetworkEvent_Data (ReceiveNetworkData returns -2) and nothing more.
Sometimes there is a second #PB_NetworkEvent_Data and ReceiveNetworkData returns -1 but no data.
I've got no problem when I don't use TLS.
EDIT : the client is on Windows 10 and the server on Linux (Debian 11)
Re: Client/Server TCP TLS communication problem
Posted: Thu Mar 20, 2025 5:25 pm
by infratec
I can confirm, that at first 2 data events coming in with -2 as length.
At least in Linux with PB 6.20 x64
I would say it is a bug.
And only -1 is documented.
Re: Client/Server TCP TLS communication problem
Posted: Thu Mar 20, 2025 9:19 pm
by idle
you need to keep looping on TLS_WANT_POLLIN=-2 or TLS_WANT_POLLOUT=-3.
if you get a -1 you need to look up the error and of those errors there are 6 cases where you should keep going but there are at least 20 errors that are fatal as in close the connection.
i'm currently testing these functions to handle complete transfers in the webserver but I'm not sure if the wsa constants are the same values on linux.
https://www.purebasic.fr/english/viewtopic.php?t=86576
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 8:10 am
by tatanas
idle,
Based on your advice I made this procedure but it never triggers when my problem arises :
Code: Select all
ImportC ""
errno_location() As "__errno_location"
EndImport
Procedure _IsNetworkError()
Protected Result, ret
#EWOULDBLOCK = 11
#EMFILE = 24
#EALREADY = 114
#EINPROGRESS = 115
ret = PeekL(errno_location())
Select ret
Case #EWOULDBLOCK
Result = #True
Case #EMFILE
Result = #True
Case #EALREADY
Result = #True
Case #EINPROGRESS
Result = #True
Default
Debug "other error code " + ret
EndSelect
ProcedureReturn Result
EndProcedure
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 9:11 am
by Fred
idle wrote: Tue Mar 18, 2025 9:54 pm
@Fred
is ReceiveNetworkData just a plain alias to recv() and returns whatever recv() returns ?
Yes. I also agree for a new NetworkError() function to get more info about this.
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 9:35 am
by HeX0R
Fred wrote: Fri Mar 21, 2025 9:11 am
Yes. I also agree for a new NetworkError() function to get more info about this.
Finally 
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 11:08 am
by idle
tatanas wrote: Fri Mar 21, 2025 8:10 am
idle,
Based on your advice I made this procedure but it never triggers when my problem arises :
Code: Select all
ImportC ""
errno_location() As "__errno_location"
EndImport
Procedure _IsNetworkError()
Protected Result, ret
#EWOULDBLOCK = 11
#EMFILE = 24
#EALREADY = 114
#EINPROGRESS = 115
ret = PeekL(errno_location())
Select ret
Case #EWOULDBLOCK
Result = #True
Case #EMFILE
Result = #True
Case #EALREADY
Result = #True
Case #EINPROGRESS
Result = #True
Default
Debug "other error code " + ret
EndSelect
ProcedureReturn Result
EndProcedure
you missed out the tls errors that are specificly your issue -2 and -3 my function is network error continue
If it returns 1 it means try again and you check it if the return from a send or receive networkdata is < 0 as they will now return
N bytes read
0 dropped
-1 socket error
-2 tls want pollin
-3 Ttls want pollout
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 12:05 pm
by idle
Fred wrote: Fri Mar 21, 2025 9:11 am
idle wrote: Tue Mar 18, 2025 9:54 pm
@Fred
is ReceiveNetworkData just a plain alias to recv() and returns whatever recv() returns ?
Yes. I also agree for a new NetworkError() function to get more info about this.
So currently send/recv networkdata will return
N bytes read
0 dropped
-1 socket error
-2 tls want poll in
-3 tls want poll out
The errors that you need to try again are in the networkErrorContinue function and it's important to keep the case 0 as an error may be cleared before its read.
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 12:33 pm
by Quin
Fred wrote: Fri Mar 21, 2025 9:11 am
I also agree for a new NetworkError() function to get more info about this.
I almost just woke up someone with the excited noise I just made. I sooo hope to see this soon! You're the man, Fred!
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 2:48 pm
by tatanas
To get back to my problem, here is a new test : The client requests with a string, the server responds to this request with a string
- 14 connections + receivedata + deconnection : OK (each time there are 2 data events and receivenetworkdata returns -2 then the 3rd contains the data from the client)
- During the 15th, the server receives only one data event and receivenetworkdata returns -2 (errno is always = 0) AND the client freezes (I don't know where because the receivenetworkdata is inside a thread). I have to kill it. The server still works fine.
Weird...
EDIT :
https://man.openbsd.org/tls_read.3
Callers of these functions cannot rely on the value of the global errno. To prevent mishandling of error conditions, tls_read(), tls_write(), tls_handshake(), and tls_close() all explicitly clear errno.
If tls_read is behind the ReceiveNetworkData(), now I understand why errno returns 0.
Re: Client/Server TCP TLS communication problem
Posted: Fri Mar 21, 2025 9:36 pm
by idle
I just realized that my error function was wrong, a case of not doing what I expected
so when it was getting The #TLS_WANT_POLLIN and POLLOut it wasn't checking them and they simply came back with 0 as the functions tls_write tls_read will have likely already cleared the error which would be an Eagain
dyslexia sucks I've been looking at it the whole time thinking it's right but I need to pass in the result as well as the connection ID.
Your problems sound very similar to what I'm seeing on windows with x86 backend, in my reverse proxy function
it literally hangs on a file and locks up the thread, x64 has no issues but I also had the issues with the function on linux.
I'm also using sendnetworkstring in the function so that is worth checking out incase it's not dealing with the errors properly due to changes with the TLS.
I've got my reverse proxy working again on x86 but I'm somewhat confused as I'm still getting resets to the errno, which aren't TLS want pollin or pollout, so maybe I need to rearrange and check the error immediately, you'd think after 30 or 40 years it'd be possible to make a thread safe error that's not subject to race conditions.
Still after half a day I'm still clueless what the cause is of getting the 0 return from the error look up but as far as the reverse proxy and server goes it's working fine.
https://www.purebasic.fr/english/viewtopic.php?t=86576
Re: Client/Server TCP TLS communication problem
Posted: Mon Mar 24, 2025 8:34 am
by tatanas
Thank you very much idle.
I was testing your previous version of Send/ReceiveNetworkDataEx() and NetworkErrorContinue(). It was way better than my own code.
I will test the new one and give you some feedback.
Re: Client/Server TCP TLS communication problem
Posted: Thu Apr 10, 2025 1:22 pm
by tatanas
Here is some feedback.
Because my tcp server was using recv and send socket functions, I rewrote everything and now i'm using internal PB functions through your wrappers Receive/SendNetworkDataEx().
Everything is working great without TLS : 320 clients + 1 admin console at peak simultaneous connections (each connection is persistent)
So I switched to TLS with only one client and the console (to be able getting data from the server and command the client).
Here is the dialog schema :
The console connects to the server
The console sends a string to request data
The server receives and sends the data to the console (around 400000 bytes)
The console receives the data
If I use your wrappers as is, my console crashes when receiving the data. When I put a Debug() line to see the error of ReceiveNetworkData() I've got between 18 to 20 "none" errors from NetworkErrorContinue() (inside ReceiveNetworkDataEx) but no crash anymore and data is received.
I therefore replace the debug line by a Delay(10) and I've got only 1 "none" error now. It's working fine.
I also noticed that those 20 "-1" ReceivedNetworkData errors only appears the first time the console communicates with the server and not after. This seems to be linked to TLS discussion...
So why do I get all this "-1" error from ReceiveNetworkData() if it's coming from a initial TLS dialog ? Strange...
Re: Client/Server TCP TLS communication problem
Posted: Thu Apr 10, 2025 9:11 pm
by idle
When you get a none i presume the error has been reset by the tls lib. I had the same issue for a while and I'm not sure what I did now to fix it.
I will look a little later today.
this is my current error continue function
Code: Select all
;-Extra functions
#PB_Network_Error_Fatal = -1
#PB_Network_Error_timeout = -2
#PB_Network_Error_Dropped = -3
#PB_Network_Error_Memory = -4
Procedure Atomic_Server_NetworkErrorContinue(ID,val=0)
Protected ret,error.l
#WSA_IO_INCOMPLETE = 996
#WSA_IO_PENDING = 997
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
#WSA_IO_INCOMPLETE = 996
#WSA_IO_PENDING = 997
#WSAEINTR = 10004
#WSAEMFILE = 10024
#WSAEWOULDBLOCK = 10035
#WSAEINPROGRESS = 10036
#WSAEALREADY = 10037
CompilerElse
#WSAEINTR = 4 ;EINTR
#WSAEMFILE = 17 ;2 ;ENOFILE ENOENT 2
#WSAEWOULDBLOCK = 11 ;Eagain
#WSAEINPROGRESS = 115 ;EINPROGRESS
#WSAEALREADY = 114 ;EALREADY
CompilerEndIf
#TLS_WANT_POLLIN = -2
#TLS_WANT_POLLOUT = -3
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
error = WSAGetLastError_()
CompilerElse
CompilerIf #PB_Compiler_Backend = #PB_Backend_C
!#include "errno.h"
!extern int errno;
!v_error=errno;
CompilerElse
error = PeekL(__errno_location())
CompilerEndIf
CompilerEndIf
If val = #TLS_WANT_POLLIN
Debug "#TLS_WANT_POLLIN"
ProcedureReturn 1
EndIf
If val = #TLS_WANT_POLLOUT
Debug "#TLS_WANT_POLLOUT"
ProcedureReturn 1
EndIf
Select error
Case 0
ret = 0
Debug "None"
Case #WSAEWOULDBLOCK
ret = 1
Debug "#WSAEWOULDBLOCK"
Case #WSAEINPROGRESS
Debug "#WSAEINPROGRESS"
ret = 1
Case #WSAEALREADY
Debug "#WSAEALREADY"
ret = 1
Case #WSA_IO_INCOMPLETE
Debug "#WSA_IO_INCOMPLETE"
ret =1
Case #WSA_IO_PENDING
Debug "#WSA_IO_PENDING"
ret = 1
Case #WSAEMFILE
ret =1
Debug "#WSAEMFILE"
Default
Debug error
EndSelect
ProcedureReturn ret
EndProcedure