Client/Server TCP TLS communication problem

Just starting out? Need help? Post your questions and find answers here.
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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 ?
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Client/Server TCP TLS communication problem

Post 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)
Windows 10 Pro x64
PureBasic 6.20 x64
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Client/Server TCP TLS communication problem

Post 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.
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Client/Server TCP TLS communication problem

Post 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
Windows 10 Pro x64
PureBasic 6.20 x64
Fred
Administrator
Administrator
Posts: 18178
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Client/Server TCP TLS communication problem

Post 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.
User avatar
HeX0R
Addict
Addict
Posts: 1198
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: Client/Server TCP TLS communication problem

Post 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 :mrgreen:
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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.
Quin
Addict
Addict
Posts: 1132
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Client/Server TCP TLS communication problem

Post 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!
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Client/Server TCP TLS communication problem

Post 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.
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Client/Server TCP TLS communication problem

Post 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.
Windows 10 Pro x64
PureBasic 6.20 x64
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: Client/Server TCP TLS communication problem

Post 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...
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
idle
Always Here
Always Here
Posts: 5884
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Client/Server TCP TLS communication problem

Post 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  
Post Reply