Index: ssfpc.inc
===================================================================
--- ssfpc.inc	(revision 209)
+++ ssfpc.inc	(working copy)
@@ -67,6 +67,9 @@
 {$ifdef darwin}
 {$DEFINE SOCK_HAS_SINLEN}               // BSD definition of scoketaddr
 {$endif}
+{$ifdef haiku}
+{$DEFINE SOCK_HAS_SINLEN}               // BSD definition of scoketaddr
+{$endif}

 interface

@@ -103,7 +106,9 @@
 const
   FIONREAD        = termio.FIONREAD;
   FIONBIO         = termio.FIONBIO;
+{$IFNDEF HAIKU}
   FIOASYNC        = termio.FIOASYNC;
+{$ENDIF}

 const
   IPPROTO_IP     =   0;		{ Dummy					}
@@ -212,12 +217,21 @@

   SOMAXCONN       = 1024;

+{$IFDEF HAIKU}
+  IPV6_UNICAST_HOPS     = 27;
+{$ELSE}
   IPV6_UNICAST_HOPS     = sockets.IPV6_UNICAST_HOPS;
+{$ENDIF}
   IPV6_MULTICAST_IF     = sockets.IPV6_MULTICAST_IF;
   IPV6_MULTICAST_HOPS   = sockets.IPV6_MULTICAST_HOPS;
   IPV6_MULTICAST_LOOP   = sockets.IPV6_MULTICAST_LOOP;
+{$IFDEF HAIKU}
+  IPV6_JOIN_GROUP       = 28;
+  IPV6_LEAVE_GROUP      = 29;
+{$ELSE}
   IPV6_JOIN_GROUP       = sockets.IPV6_JOIN_GROUP;
   IPV6_LEAVE_GROUP      = sockets.IPV6_LEAVE_GROUP;
+{$ENDIF}

 const
   SOCK_STREAM     = 1;               { stream socket }
@@ -231,9 +245,9 @@

 { Address families. }

-  AF_UNSPEC       = 0;               { unspecified }
-  AF_INET         = 2;               { internetwork: UDP, TCP, etc. }
-  AF_INET6        = 10;              { Internetwork Version 6 }
+  AF_UNSPEC       = 0;                { unspecified }
+  AF_INET         = sockets.AF_INET;  { internetwork: UDP, TCP, etc. }
+  AF_INET6        = sockets.AF_INET6; { Internetwork Version 6 }
   AF_MAX          = 24;

 { Protocol families, same as address families for now. }
@@ -254,15 +268,31 @@

   MSG_OOB       = sockets.MSG_OOB;      // Process out-of-band data.
   MSG_PEEK      = sockets.MSG_PEEK;     // Peek at incoming messages.
-  {$ifdef DARWIN}
+  {$if defined(DARWIN)}
   MSG_NOSIGNAL  = $20000;  // Do not generate SIGPIPE.
                            // Works under MAC OS X, but is undocumented,
                            // So FPC doesn't include it
+  {$elseif defined(HAIKU)}
+  MSG_NOSIGNAL   = $0800;
   {$else}
-   MSG_NOSIGNAL  = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
+  MSG_NOSIGNAL   = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
   {$endif}

+{$IF DEFINED(HAIKU)}
 const
+  ESysESTALE = (B_POSIX_ERROR_BASE + 40);
+  ESysENOTSOCK = (B_POSIX_ERROR_BASE + 44);
+  ESysEHOSTDOWN = (B_POSIX_ERROR_BASE + 45);
+  ESysEDESTADDRREQ = (B_POSIX_ERROR_BASE + 48);
+  ESysEDQUOT = (B_POSIX_ERROR_BASE + 49);
+  // Fake error codes
+  ESysEUSERS = (B_POSIX_ERROR_BASE + 128);
+  ESysEREMOTE = (B_POSIX_ERROR_BASE + 129);
+  ESysETOOMANYREFS = (B_POSIX_ERROR_BASE + 130);
+  ESysESOCKTNOSUPPORT = (B_POSIX_ERROR_BASE + 131);
+{$ENDIF}
+
+const
   WSAEINTR = ESysEINTR;
   WSAEBADF = ESysEBADF;
   WSAEACCES = ESysEACCES;
@@ -755,7 +785,7 @@
 begin
   Result := 0;
   FillChar(Sin, Sizeof(Sin), 0);
-  Sin.sin_port := Resolveport(port, family, SockProtocol, SockType);
+  Sin.sin_port := htons(Resolveport(port, family, SockProtocol, SockType));
   TwoPass := False;
   if Family = AF_UNSPEC then
   begin
@@ -858,7 +888,7 @@
   ProtoEnt: TProtocolEntry;
   ServEnt: TServiceEntry;
 begin
-  Result := synsock.htons(StrToIntDef(Port, 0));
+  Result := StrToIntDef(Port, 0);
   if Result = 0 then
   begin
     ProtoEnt.Name := '';
@@ -865,7 +895,7 @@
     GetProtocolByNumber(SockProtocol, ProtoEnt);
     ServEnt.port := 0;
     GetServiceByName(Port, ProtoEnt.Name, ServEnt);
-    Result := ServEnt.port;
+    Result := ntohs(ServEnt.port);
   end;
 end;
Index: blcksock.pas
===================================================================
--- blcksock.pas	(revision 278)
+++ blcksock.pas	(working copy)
@@ -1234,6 +1234,8 @@
   TCustomSSL = class(TObject)
   private
   protected
+    FSessionOld: Pointer;
+    FSessionNew: Pointer;
     FOnVerifyCert: THookVerifyCert;
     FSocket: TTCPBlockSocket;
     FSSLEnabled: Boolean;
@@ -1368,6 +1370,9 @@

     {:Return error description of last SSL operation.}
     property LastErrorDesc: string read FLastErrorDesc;
+
+    {:Used for session resumption }
+    property Session: Pointer read FSessionNew write FSessionOld;
   published
     {:Here you can specify requested SSL/TLS mode. Default is autodetection, but
      on some servers autodetection not working properly. In this case you must
@@ -2518,6 +2523,8 @@
 begin
   repeat
     s := RecvPacket(Timeout);
+    if (Length(s) = 0) then
+      Break;
     if FLastError = 0 then
       WriteStrToStream(Stream, s);
   until FLastError <> 0;
Index: ftpsend.pas
===================================================================
--- ftpsend.pas	(revision 209)
+++ ftpsend.pas	(working copy)
@@ -870,6 +870,11 @@
       end;
     FDSock.CloseSocket;
     FDSock.Bind(FIPInterface, cAnyPort);
+
+    if FIsDataTLS then begin
+      FDSock.SSL.Session := FSock.SSL.Session;
+    end;
+
     FDSock.Connect(FDataIP, FDataPort);
     Result := FDSock.LastError = 0;
   end
Index: ssl_openssl.pas
===================================================================
--- ssl_openssl.pas	(revision 278)
+++ ssl_openssl.pas	(working copy)
@@ -77,8 +77,9 @@
 accepting of new connections!
 }

-{$INCLUDE 'jedi.inc'}
-
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
 {$H+}

 {$IFDEF UNICODE}
@@ -86,7 +87,7 @@
   {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
 {$ENDIF}

-unit ssl_openssl{$IFDEF SUPPORTS_DEPRECATED} deprecated{$IFDEF SUPPORTS_DEPRECATED_DETAILS} 'Use ssl_openssl3 with OpenSSL 3.0 instead'{$ENDIF}{$ENDIF};
+unit ssl_openssl;

 interface

@@ -495,6 +496,11 @@
 function TSSLOpenSSL.DeInit: Boolean;
 begin
   Result := True;
+  if Assigned(FSessionNew) then
+  begin
+    SslSessionFree(FSessionNew);
+    FSessionNew := nil;
+  end;
   if assigned (Fssl) then
     sslfree(Fssl);
   Fssl := nil;
@@ -538,6 +544,10 @@
       SSLCheck;
       Exit;
     end;
+    // Reuse session
+    if Assigned(FSessionOld) then begin
+      SslSetSession(Fssl, FSessionOld);
+    end;
     if SNIHost<>'' then
     begin
       SSLCtrl(Fssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, PAnsiChar(AnsiString(SNIHost)));
@@ -579,6 +589,9 @@
     FSSLEnabled := True;
     Result := True;
   end;
+  if Result and (FSessionOld = nil) then begin
+    FSessionNew := SslGet1Session(Fssl);
+  end;
 end;

 function TSSLOpenSSL.Accept: boolean;
Index: ssl_openssl_lib.pas
===================================================================
--- ssl_openssl_lib.pas	(revision 278)
+++ ssl_openssl_lib.pas	(working copy)
@@ -813,6 +813,9 @@
   function SSLGetVerifyResult(ssl: PSSL):Integer;
   function SSLCtrl(ssl: PSSL; cmd: integer; larg: integer; parg: SslPtr):Integer;
   function SslSet1Host(ssl: PSSL; hostname: PAnsiChar):Integer;
+  procedure SslSessionFree(session: PSslPtr);
+  function SslGet1Session(ssl: PSSL):PSslPtr;
+  function SslSetSession(ssl: PSSL; session: PSslPtr): Integer;

 // libeay.dll
   function X509New: PX509;
@@ -940,6 +943,9 @@
   TSSLGetVerifyResult = function(ssl: PSSL):Integer; cdecl;
   TSSLCtrl = function(ssl: PSSL; cmd: integer; larg: integer; parg: SslPtr):Integer; cdecl;
   TSslSet1Host = function(ssl: PSSL; hostname: PAnsiChar):Integer; cdecl;
+  TSslSessionFree = procedure(session: PSslPtr); cdecl;
+  TSslGet1Session = function(ssl: PSSL):PSslPtr; cdecl;
+  TSslSetSession = function(ssl: PSSL; session: PSslPtr): Integer; cdecl;

   TSSLSetTlsextHostName = function(ssl: PSSL; buf: PAnsiChar):Integer; cdecl;

@@ -1049,6 +1055,9 @@
   _SSLGetVerifyResult: TSSLGetVerifyResult = nil;
   _SSLCtrl: TSSLCtrl = nil;
   _SslSet1Host: TSslSet1Host = nil;
+  _SslSessionFree: TSslSessionFree = nil;
+  _SslGet1Session: TSslGet1Session = nil;
+  _SslSetSession: TSslSetSession = nil;

 // libeay.dll
   _X509New: TX509New = nil;
@@ -1474,6 +1483,28 @@
     Result := 0;
 end;

+procedure SslSessionFree(session: PSslPtr);
+begin
+  if InitSSLInterface and Assigned(_SslSessionFree) then
+    _SslSessionFree(session);
+end;
+
+function SslGet1Session(ssl: PSSL): PSslPtr;
+begin
+  if InitSSLInterface and Assigned(_SslGet1Session) then
+    Result := _SslGet1Session(ssl)
+  else
+    Result := nil;
+end;
+
+function SslSetSession(ssl: PSSL; session: PSslPtr): Integer;
+begin
+  if InitSSLInterface and Assigned(_SslSetSession) then
+    Result := _SslSetSession(ssl, session)
+  else
+    Result := 0;
+end;
+
 // libeay.dll
 function X509New: PX509;
 begin
@@ -1924,7 +1955,7 @@
 {$ENDIF}
 end;

-function GetLibFileName(Handle: THandle): string;
+function GetLibFileName(Handle: TLibHandle): string;
 var
   n: integer;
 begin
@@ -2022,6 +2053,9 @@
         _SslGetVerifyResult := GetProcAddr(SSLLibHandle, 'SSL_get_verify_result');
         _SslCtrl := GetProcAddr(SSLLibHandle, 'SSL_ctrl');
         _SslSet1Host := GetProcAddr(SSLLibHandle, 'SSL_set1_host');
+        _SslSessionFree := GetProcAddr(SSLLibHandle, 'SSL_SESSION_free');
+        _SslGet1Session := GetProcAddr(SSLLibHandle, 'SSL_get1_session');
+        _SslSetSession := GetProcAddr(SSLLibHandle, 'SSL_set_session');

         _X509New := GetProcAddr(SSLUtilHandle, 'X509_new');
         _X509Free := GetProcAddr(SSLUtilHandle, 'X509_free');
@@ -2213,6 +2247,9 @@
     _SslGetVerifyResult := nil;
     _SslCtrl := nil;
     _SslSet1Host := nil;
+    _SslSessionFree := nil;
+    _SslGet1Session := nil;
+    _SslSetSession := nil;

     _X509New := nil;
     _X509Free := nil;
