(*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *)

unit Thrift.Socket;

{$I Thrift.Defines.inc}
{$I-}  // prevent annoying errors with default log delegate and no console

interface
{$IFNDEF OLD_SOCKETS} // not for OLD_SOCKETS

uses
  Winapi.Windows, Winapi.Winsock2;

const
  AI_PASSIVE                = $00000001;  // Socket address will be used in bind() call
  AI_CANONNAME              = $00000002;  // Return canonical name in first ai_canonname
  AI_NUMERICHOST            = $00000004;  // Nodename must be a numeric address string
  AI_NUMERICSERV            = $00000008;  // Servicename must be a numeric port number

  AI_ALL                    = $00000100;  // Query both IP6 and IP4 with AI_V4MAPPED
  AI_ADDRCONFIG             = $00000400;  // Resolution only if global address configured
  AI_V4MAPPED               = $00000800;  // On v6 failure, query v4 and convert to V4MAPPED format

  AI_NON_AUTHORITATIVE      = $00004000;  // LUP_NON_AUTHORITATIVE
  AI_SECURE                 = $00008000;  // LUP_SECURE
  AI_RETURN_PREFERRED_NAMES = $00010000;  // LUP_RETURN_PREFERRED_NAMES

  AI_FQDN                   = $00020000;  // Return the FQDN in ai_canonname
  AI_FILESERVER             = $00040000;  // Resolving fileserver name resolution

type
  PAddrInfoA = ^TAddrInfoA;
  TAddrInfoA = record
    ai_flags: Integer;
    ai_family: Integer;
    ai_socktype: Integer;
    ai_protocol: Integer;
    ai_addrlen: NativeUInt;
    ai_canonname: PAnsiChar;
    ai_addr: PSockAddr;
    ai_next: PAddrInfoA;
  end;

  PAddrInfoW = ^TAddrInfoW;
  TAddrInfoW = record
    ai_flags: Integer;
    ai_family: Integer;
    ai_socktype: Integer;
    ai_protocol: Integer;
    ai_addrlen: NativeUInt;
    ai_canonname: PChar;
    ai_addr: PSockAddr;
    ai_next: PAddrInfoW;
  end;

  TAddressFamily = USHORT;

  TIn6Addr = record
  case Integer of
    0: (_Byte: array[0..15] of UCHAR);
    1: (_Word: array[0..7] of USHORT);
  end;

  TScopeId = record
  public
    Value: ULONG;
  strict private
    function GetBitField(Loc: Integer): Integer; inline;
    procedure SetBitField(Loc: Integer; const aValue: Integer); inline;
  public
    property Zone: Integer index $0028 read GetBitField write SetBitField;
    property Level: Integer index $2804 read GetBitField write SetBitField;
  end;

  TSockAddrIn6 = record
    sin6_family: TAddressFamily;
    sin6_port: USHORT;
    sin6_flowinfo: ULONG;
    sin6_addr: TIn6Addr;
  case Integer of
    0: (sin6_scope_id: ULONG);
    1: (sin6_scope_struct: TScopeId);
  end;
  PSockAddrIn6 = ^TSockAddrIn6;

const
  NI_NOFQDN      = $01;  // Only return nodename portion for local hosts
  NI_NUMERICHOST = $02;  // Return numeric form of the host's address
  NI_NAMEREQD    = $04;  // Error if the host's name not in DNS
  NI_NUMERICSERV = $08;  // Return numeric form of the service (port #)
  NI_DGRAM       = $10;  // Service is a datagram service

  NI_MAXHOST     = 1025;  // Max size of a fully-qualified domain name
  NI_MAXSERV     = 32;    // Max size of a service name

function getaddrinfo(pNodeName, pServiceName: PAnsiChar; const pHints: TAddrInfoA; var ppResult: PAddrInfoA): Integer; stdcall;
function GetAddrInfoW(pNodeName, pServiceName: PWideChar; const pHints: TAddrInfoW; var ppResult: PAddrInfoW): Integer; stdcall;
procedure freeaddrinfo(pAddrInfo: PAddrInfoA); stdcall;
procedure FreeAddrInfoW(pAddrInfo: PAddrInfoW); stdcall;
function getnameinfo(const pSockaddr: TSockAddr; SockaddrLength: Integer; pNodeBuffer: PAnsiChar; NodeBufferSize: DWORD; pServiceBuffer: PAnsiChar;
  ServiceBufferSize: DWORD; Flags: Integer): Integer; stdcall;
function GetNameInfoW(const pSockaddr: TSockAddr; SockaddrLength: Integer; pNodeBuffer: PWideChar; NodeBufferSize: DWORD; pServiceBuffer: PWideChar;
  ServiceBufferSize: DWORD; Flags: Integer): Integer; stdcall;

type
  TSmartPointerDestroyer<T> = reference to procedure(Value: T);

  ISmartPointer<T> = reference to function: T;

  TSmartPointer<T> = class(TInterfacedObject, ISmartPointer<T>)
  strict private
    FValue: T;
    FDestroyer: TSmartPointerDestroyer<T>;
  public
    constructor Create(AValue: T; ADestroyer: TSmartPointerDestroyer<T>);
    destructor Destroy; override;
    function Invoke: T;
  end;

  TBaseSocket = class abstract
  public type
    TLogDelegate = reference to procedure( const str: string);
  strict private
    FPort: Integer;
    FSocket: Winapi.Winsock2.TSocket;
    FSendTimeout,
    FRecvTimeout: Longword;
    FKeepAlive: Boolean;
    FLogDelegate: TLogDelegate;
    class constructor Create;
    class destructor Destroy;
    class procedure DefaultLogDelegate(const Str: string);
  strict protected type
    IGetAddrInfoWrapper = interface
      function Init: Integer;
      function GetRes: PAddrInfoW;
      property Res: PAddrInfoW read GetRes;
    end;
    TGetAddrInfoWrapper = class(TInterfacedObject, IGetAddrInfoWrapper)
    strict private
      FNode: string;
      FService: string;
      FHints,
      FRes: PAddrInfoW;
    public
      constructor Create(ANode, AService: string; AHints: PAddrInfoW);
      destructor Destroy; override;
      function Init: Integer;
      function GetRes: PAddrInfoW;
      property Res: PAddrInfoW read GetRes;
    end;
  strict protected
    procedure CommonInit; virtual;
    function CreateSocket(AAddress: string; APort: Integer): IGetAddrInfoWrapper;
    procedure SetRecvTimeout(ARecvTimeout: Longword); virtual;
    procedure SetSendTimeout(ASendTimeout: Longword); virtual;
    procedure SetKeepAlive(AKeepAlive: Boolean); virtual;
    procedure SetSocket(ASocket: Winapi.Winsock2.TSocket);
    property LogDelegate: TLogDelegate read FLogDelegate;
  public
    //
    // Constructs a new socket. Note that this does NOT actually connect the
    // socket.
    //
    constructor Create(ALogDelegate: TLogDelegate = nil); overload;
    constructor Create(APort: Integer; ALogDelegate: TLogDelegate = nil); overload;

    //
    // Destroys the socket object, closing it if necessary.
    //
    destructor Destroy; override;

    //
    // Shuts down communications on the socket
    //
    procedure Close; virtual;

    // The port that the socket is connected to
    property Port: Integer read FPort write FPort;

    // The receive timeout
    property RecvTimeout: Longword read FRecvTimeout write SetRecvTimeout;

    // The send timeout
    property SendTimeout: Longword read FSendTimeout write SetSendTimeout;

    // Set SO_KEEPALIVE
    property KeepAlive: Boolean read FKeepAlive write SetKeepAlive;

    // The underlying socket descriptor
    property Socket: Winapi.Winsock2.TSocket read FSocket write SetSocket;
  end;

  TSocket = class(TBaseSocket)
  strict private type
    TCachedPeerAddr = record
    case Integer of
      0: (ipv4: TSockAddrIn);
      1: (ipv6: TSockAddrIn6);
    end;
  strict private
    FHost: string;
    FPeerHost: string;
    FPeerAddress: string;
    FPeerPort: Integer;
    FInterruptListener: ISmartPointer<Winapi.Winsock2.TSocket>;
    FConnTimeout: Longword;
    FLingerOn: Boolean;
    FLingerVal: Integer;
    FNoDelay: Boolean;
    FMaxRecvRetries: Longword;
    FCachedPeerAddr: TCachedPeerAddr;
    procedure InitPeerInfo;
    procedure OpenConnection(Res: TBaseSocket.IGetAddrInfoWrapper);
    procedure LocalOpen;
    procedure SetGenericTimeout(S: Winapi.Winsock2.TSocket; Timeout: Longword; OptName: Integer);
    function GetIsOpen: Boolean;
    procedure SetNoDelay(ANoDelay: Boolean);
    function GetSocketInfo: string;
    function GetPeerHost: string;
    function GetPeerAddress: string;
    function GetPeerPort: Integer;
    function GetOrigin: string;
  strict protected
    procedure CommonInit; override;
    procedure SetRecvTimeout(ARecvTimeout: Longword); override;
    procedure SetSendTimeout(ASendTimeout: Longword); override;
    procedure SetKeepAlive(AKeepAlive: Boolean); override;
  public
    //
    // Constructs a new socket. Note that this does NOT actually connect the
    // socket.
    //
    constructor Create(ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Constructs a new socket. Note that this does NOT actually connect the
    // socket.
    //
    // @param host An IP address or hostname to connect to
    // @param port The port to connect on
    //
    constructor Create(AHost: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Constructor to create socket from socket descriptor.
    //
    constructor Create(ASocket: Winapi.Winsock2.TSocket; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Constructor to create socket from socket descriptor that
    // can be interrupted safely.
    //
    constructor Create(ASocket: Winapi.Winsock2.TSocket; AInterruptListener: ISmartPointer<Winapi.Winsock2.TSocket>;
      ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Creates and opens the socket
    //
    // @throws ETransportationException If the socket could not connect
    //
    procedure Open;

    //
    // Shuts down communications on the socket
    //
    procedure Close; override;

    //
    // Reads from the underlying socket.
    // \returns the number of bytes read or 0 indicates EOF
    // \throws TTransportException of types:
    //          Interrupted means the socket was interrupted
    //                      out of a blocking call
    //          NotOpen means the socket has been closed
    //          TimedOut means the receive timeout expired
    //          Unknown means something unexpected happened
    //
    function Read(var Buf; Len: Integer): Integer;

    //
    // Writes to the underlying socket.  Loops until done or fail.
    //
    procedure Write(const Buf; Len: Integer);

    //
    // Writes to the underlying socket.  Does single send() and returns result.
    //
    function WritePartial(const Buf; Len: Integer): Integer;

    //
    // Returns a cached copy of the peer address.
    //
    function GetCachedAddress(out Len: Integer): PSockAddr;

    //
    // Set a cache of the peer address (used when trivially available: e.g.
    // accept() or connect()). Only caches IPV4 and IPV6; unset for others.
    //
    procedure SetCachedAddress(const Addr: TSockAddr; Len: Integer);

    //
    // Controls whether the linger option is set on the socket.
    //
    // @param on      Whether SO_LINGER is on
    // @param linger  If linger is active, the number of seconds to linger for
    //
    procedure SetLinger(LingerOn: Boolean; LingerVal: Integer);

    //
    // Calls select() on the socket to see if there is more data available.
    //
    function Peek: Boolean;

    // Whether the socket is alive
    property IsOpen: Boolean read GetIsOpen;

    // The host that the socket is connected to
    property Host: string read FHost write FHost;

    // Whether to enable or disable Nagle's algorithm
    property NoDelay: Boolean read FNoDelay write SetNoDelay;

    // Connect timeout
    property ConnTimeout: Longword read FConnTimeout write FConnTimeout;

    // The max number of recv retries in the case of a WSAEWOULDBLOCK
    property MaxRecvRetries: Longword read FMaxRecvRetries write FMaxRecvRetries;

    // Socket information formatted as a string <Host: x Port: x>
    property SocketInfo: string read GetSocketInfo;

    // The DNS name of the host to which the socket is connected
    property PeerHost: string read GetPeerHost;

    // The address of the host to which the socket is connected
    property PeerAddress: string read GetPeerAddress;

    // The port of the host to which the socket is connected
    property PeerPort: Integer read GetPeerPort;

    // The origin the socket is connected to
    property Origin: string read GetOrigin;
  end;

  TServerSocketFunc = reference to procedure(sock: Winapi.Winsock2.TSocket);

  TServerSocket = class(TBaseSocket)
  strict private
    FAddress: string;
    FAcceptBacklog,
    FRetryLimit,
    FRetryDelay,
    FTcpSendBuffer,
    FTcpRecvBuffer: Integer;
    FAcceptTimeout: Longword;
    FListening,
    FInterruptableChildren: Boolean;
    FInterruptSockWriter,                                               // is notified on Interrupt()
    FInterruptSockReader,                                               // is used in select with FSocket for interruptability
    FChildInterruptSockWriter: Winapi.Winsock2.TSocket;                 // is notified on InterruptChildren()
    FChildInterruptSockReader: ISmartPointer<Winapi.Winsock2.TSocket>;  // if FnterruptableChildren this is shared with child TSockets
    FListenCallback,
    FAcceptCallback: TServerSocketFunc;
    function CreateSocketObj(Client: Winapi.Winsock2.TSocket): TSocket;
    procedure Notify(NotifySocket: Winapi.Winsock2.TSocket);
    procedure SetInterruptableChildren(AValue: Boolean);
  strict protected
    procedure CommonInit; override;
  public const
    DEFAULT_BACKLOG = 1024;
  public
    //
    // Constructor.
    //
    // @param port    Port number to bind to
    //
    constructor Create(APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Constructor.
    //
    // @param port        Port number to bind to
    // @param sendTimeout Socket send timeout
    // @param recvTimeout Socket receive timeout
    //
    constructor Create(APort: Integer; ASendTimeout, ARecvTimeout: Longword; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    //
    // Constructor.
    //
    // @param address Address to bind to
    // @param port    Port number to bind to
    //
    constructor Create(AAddress: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload;

    procedure Listen;
    function Accept: TSocket;
    procedure Interrupt;
    procedure InterruptChildren;
    procedure Close; override;

    property AcceptBacklog: Integer read FAcceptBacklog write FAcceptBacklog;
    property AcceptTimeout: Longword read FAcceptTimeout write FAcceptTimeout;
    property RetryLimit: Integer read FRetryLimit write FRetryLimit;
    property RetryDelay: Integer read FRetryDelay write FRetryDelay;
    property TcpSendBuffer: Integer read FTcpSendBuffer write FTcpSendBuffer;
    property TcpRecvBuffer: Integer read FTcpRecvBuffer write FTcpRecvBuffer;

    // When enabled (the default), new children TSockets will be constructed so
    // they can be interrupted by TServerTransport.InterruptChildren().
    // This is more expensive in terms of system calls (poll + recv) however
    // ensures a connected client cannot interfere with TServer.Stop().
    //
    // When disabled, TSocket children do not incur an additional poll() call.
    // Server-side reads are more efficient, however a client can interfere with
    // the server's ability to shutdown properly by staying connected.
    //
    // Must be called before listen(); mode cannot be switched after that.
    // \throws EPropertyError if listen() has been called
    property InterruptableChildren: Boolean read FInterruptableChildren write SetInterruptableChildren;

    // listenCallback gets called just before listen, and after all Thrift
    // setsockopt calls have been made.  If you have custom setsockopt
    // things that need to happen on the listening socket, this is the place to do it.
    property ListenCallback: TServerSocketFunc read FListenCallback write FListenCallback;

    // acceptCallback gets called after each accept call, on the newly created socket.
    // It is called after all Thrift setsockopt calls have been made.  If you have
    // custom setsockopt things that need to happen on the accepted
    // socket, this is the place to do it.
    property AcceptCallback: TServerSocketFunc read FAcceptCallback write FAcceptCallback;
  end;

{$ENDIF} // not for OLD_SOCKETS
implementation
{$IFNDEF OLD_SOCKETS} // not for OLD_SOCKETS

uses
  System.SysUtils, System.Math, System.DateUtils, Thrift.Transport;

constructor TBaseSocket.TGetAddrInfoWrapper.Create(ANode, AService: string; AHints: PAddrInfoW);
begin
  inherited Create;
  FNode := ANode;
  FService := AService;
  FHints := AHints;
  FRes := nil;
end;

destructor TBaseSocket.TGetAddrInfoWrapper.Destroy;
begin
  if Assigned(FRes) then
    FreeAddrInfoW(FRes);
  inherited Destroy;
end;

function TBaseSocket.TGetAddrInfoWrapper.Init: Integer;
begin
  if FRes = nil then
    Exit(GetAddrInfoW(@FNode[1], @FService[1], FHints^, FRes));
  Result := 0;
end;

function TBaseSocket.TGetAddrInfoWrapper.GetRes: PAddrInfoW;
begin
  Result := FRes;
end;

procedure DestroyerOfFineSockets(ssock: Winapi.Winsock2.TSocket);
begin
  closesocket(ssock);
end;

function TScopeId.GetBitField(Loc: Integer): Integer;
begin
  Result := (Value shr (Loc shr 8)) and ((1 shl (Loc and $FF)) - 1);
end;

procedure TScopeId.SetBitField(Loc: Integer; const aValue: Integer);
begin
  Value := (Value and ULONG((not ((1 shl (Loc and $FF)) - 1)))) or ULONG(aValue shl (Loc shr 8));
end;

function getaddrinfo; external 'ws2_32.dll' name 'getaddrinfo';
function GetAddrInfoW; external 'ws2_32.dll' name 'GetAddrInfoW';
procedure freeaddrinfo; external 'ws2_32.dll' name 'freeaddrinfo';
procedure FreeAddrInfoW; external 'ws2_32.dll' name 'FreeAddrInfoW';
function getnameinfo; external 'ws2_32.dll' name 'getnameinfo';
function GetNameInfoW; external 'ws2_32.dll' name 'GetNameInfoW';

constructor TSmartPointer<T>.Create(AValue: T; ADestroyer: TSmartPointerDestroyer<T>);
begin
  inherited Create;
  FValue := AValue;
  FDestroyer := ADestroyer;
end;

destructor TSmartPointer<T>.Destroy;
begin
  if Assigned(FDestroyer) then FDestroyer(FValue);
  inherited Destroy;
end;

function TSmartPointer<T>.Invoke: T;
begin
  Result := FValue;
end;

class constructor TBaseSocket.Create;
var
  Version: WORD;
  Data: WSAData;
  Error: Integer;
begin
  Version := $0202;
  FillChar(Data, SizeOf(Data), 0);
  Error := WSAStartup(Version, Data);
  if Error <> 0 then
    raise Exception.Create('Failed to initialize Winsock.');
end;

class destructor TBaseSocket.Destroy;
begin
  WSACleanup;
end;

class procedure TBaseSocket.DefaultLogDelegate(const Str: string);
var
  OutStr: string;
begin
  OutStr := Format('Thrift: %s %s', [DateTimeToStr(Now, TFormatSettings.Create), Str]);
  try
    Writeln(OutStr);
    if IoResult <> 0 then OutputDebugString(PChar(OutStr));
  except
    OutputDebugString(PChar(OutStr));
  end;
end;

procedure TBaseSocket.CommonInit;
begin
  FSocket := INVALID_SOCKET;
  FPort := 0;
  FSendTimeout := 0;
  FRecvTimeout := 0;
  FKeepAlive := False;
  FLogDelegate := DefaultLogDelegate;
end;

function TBaseSocket.CreateSocket(AAddress: string; APort: Integer): IGetAddrInfoWrapper;
var
  Hints: TAddrInfoW;
  Res: PAddrInfoW;
  ThePort: array[0..5] of Char;
  Error: Integer;
begin
  FillChar(Hints, SizeOf(Hints), 0);
  Hints.ai_family := PF_UNSPEC;
  Hints.ai_socktype := SOCK_STREAM;
  Hints.ai_flags := AI_PASSIVE;
  StrFmt(ThePort, '%d', [FPort]);

  Result := TGetAddrInfoWrapper.Create(AAddress, ThePort, @Hints);
  Error := Result.Init;
  if Error <> 0 then begin
    LogDelegate(Format('GetAddrInfoW %d: %s', [Error, SysErrorMessage(Error)]));
    Close;
    raise TTransportExceptionNotOpen.Create('Could not resolve host for server socket.');
  end;

  // Pick the ipv6 address first since ipv4 addresses can be mapped
  // into ipv6 space.
  Res := Result.Res;
  while Assigned(Res) do begin
    if (Res^.ai_family = AF_INET6) or (not Assigned(Res^.ai_next)) then
      Break;
    Res := Res^.ai_next;
  end;

  FSocket := Winapi.Winsock2.socket(Res^.ai_family, Res^.ai_socktype, Res^.ai_protocol);
  if FSocket = INVALID_SOCKET then begin
    Error := WSAGetLastError;
    LogDelegate(Format('TBaseSocket.CreateSocket() socket() %s', [SysErrorMessage(Error)]));
    Close;
    raise TTransportExceptionNotOpen.Create(Format('socket(): %s', [SysErrorMessage(Error)]));
  end;
end;

procedure TBaseSocket.SetRecvTimeout(ARecvTimeout: Longword);
begin
  FRecvTimeout := ARecvTimeout;
end;

procedure TBaseSocket.SetSendTimeout(ASendTimeout: Longword);
begin
  FSendTimeout := ASendTimeout;
end;

procedure TBaseSocket.SetKeepAlive(AKeepAlive: Boolean);
begin
  FKeepAlive := AKeepAlive;
end;

procedure TBaseSocket.SetSocket(ASocket: Winapi.Winsock2.TSocket);
begin
  if FSocket <> INVALID_SOCKET then
    Close;
  FSocket := ASocket;
end;

constructor TBaseSocket.Create(ALogDelegate: TLogDelegate);
begin
  inherited Create;
  CommonInit;
  if Assigned(ALogDelegate) then FLogDelegate := ALogDelegate;
end;

constructor TBaseSocket.Create(APort: Integer; ALogDelegate: TLogDelegate);
begin
  inherited Create;
  CommonInit;
  FPort := APort;
  if Assigned(ALogDelegate) then FLogDelegate := ALogDelegate;
end;

destructor TBaseSocket.Destroy;
begin
  Close;
  inherited Destroy;
end;

procedure TBaseSocket.Close;
begin
  if FSocket <> INVALID_SOCKET then begin
    shutdown(FSocket, SD_BOTH);
    closesocket(FSocket);
  end;
  FSocket := INVALID_SOCKET;
end;

procedure TSocket.InitPeerInfo;
begin
  FCachedPeerAddr.ipv4.sin_family := AF_UNSPEC;
  FPeerHost := '';
  FPeerAddress := '';
  FPeerPort := 0;
end;

procedure TSocket.CommonInit;
begin
  inherited CommonInit;
  FHost := '';
  FInterruptListener := nil;
  FConnTimeout := 0;
  FLingerOn := True;
  FLingerVal := 0;
  FNoDelay := True;
  FMaxRecvRetries := 5;
  InitPeerInfo;
end;

procedure TSocket.OpenConnection(Res: TBaseSocket.IGetAddrInfoWrapper);
label
  Done;
var
  ErrnoCopy: Integer;
  Ret,
  Ret2: Integer;
  Fds: TFdSet;
  TVal: TTimeVal;
  PTVal: PTimeVal;
  Val,
  Lon: Integer;
  One,
  Zero: Cardinal;
begin
  if SendTimeout > 0 then SetSendTimeout(SendTimeout);
  if RecvTimeout > 0 then SetRecvTimeout(RecvTimeout);
  if KeepAlive then SetKeepAlive(KeepAlive);
  SetLinger(FLingerOn, FLingerVal);
  SetNoDelay(FNoDelay);

  // Set the socket to be non blocking for connect if a timeout exists
  Zero := 0;
  if FConnTimeout > 0 then begin
    One := 1;
    if ioctlsocket(Socket, Integer(FIONBIO), One) = SOCKET_ERROR then begin
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TSocket.OpenConnection() ioctlsocket() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() failed: %s', [SysErrorMessage(ErrnoCopy)]));
    end;
  end
  else begin
    if ioctlsocket(Socket, Integer(FIONBIO), Zero) = SOCKET_ERROR then begin
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TSocket.OpenConnection() ioctlsocket() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() failed: %s', [SysErrorMessage(ErrnoCopy)]));
    end;
  end;

  Ret := connect(Socket, Res.Res^.ai_addr^, Res.Res^.ai_addrlen);
  if Ret = 0 then goto Done;

  ErrnoCopy := WSAGetLastError;
  if (ErrnoCopy <> WSAEINPROGRESS) and (ErrnoCopy <> WSAEWOULDBLOCK) then begin
    LogDelegate(Format('TSocket.OpenConnection() connect() ', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('connect() failed: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  FD_ZERO(Fds);
  _FD_SET(Socket, Fds);
  if FConnTimeout > 0 then begin
    TVal.tv_sec := FConnTimeout div 1000;
    TVal.tv_usec := (FConnTimeout mod 1000) * 1000;
    PTVal := @TVal;
  end
  else
    PTVal := nil;
  Ret := select(1, nil, @Fds, nil, PTVal);

  if Ret > 0 then begin
    // Ensure the socket is connected and that there are no errors set
    Lon := SizeOf(Val);
    Ret2 := getsockopt(Socket, SOL_SOCKET, SO_ERROR, @Val, Lon);
    if Ret2 = SOCKET_ERROR then begin
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TSocket.OpenConnection() getsockopt() ', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionNotOpen.Create(Format('getsockopt(): %s', [SysErrorMessage(ErrnoCopy)]));
    end;
    // no errors on socket, go to town
    if Val = 0 then goto Done;
    LogDelegate(Format('TSocket.OpenConnection() error on socket (after select()) ', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('socket OpenConnection() error: %s', [SysErrorMessage(Val)]));
  end
  else if Ret = 0 then begin
    // socket timed out
    LogDelegate(Format('TSocket.OpenConnection() timed out ', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create('OpenConnection() timed out');
  end
  else begin
    // error on select()
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TSocket.OpenConnection() select() ', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('select() failed: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

Done:
  // Set socket back to normal mode (blocking)
  ioctlsocket(Socket, Integer(FIONBIO), Zero);
  SetCachedAddress(Res.Res^.ai_addr^, Res.Res^.ai_addrlen);
end;

procedure TSocket.LocalOpen;
var
  Res: TBaseSocket.IGetAddrInfoWrapper;
begin
  if IsOpen then Exit;

  // Validate port number
  if (Port < 0) or (Port > $FFFF) then
    raise TTransportExceptionBadArgs.Create('Specified port is invalid');

  Res := CreateSocket(Host, Port);

  OpenConnection(Res);
end;

procedure TSocket.SetGenericTimeout(S: Winapi.Winsock2.TSocket; Timeout: Longword; OptName: Integer);
var
  Time: DWORD;
begin
  if S = INVALID_SOCKET then
    Exit;

  Time := Timeout;

  if setsockopt(S, SOL_SOCKET, OptName, @Time, SizeOf(Time)) = SOCKET_ERROR then
    LogDelegate(Format('SetGenericTimeout() setsockopt() %s', [SysErrorMessage(WSAGetLastError)]));
end;

function TSocket.GetIsOpen: Boolean;
begin
  Result := Socket <> INVALID_SOCKET;
end;

procedure TSocket.SetNoDelay(ANoDelay: Boolean);
var
  V: Integer;
begin
  FNoDelay := ANoDelay;
  if Socket = INVALID_SOCKET then
    Exit;

  V := IfThen(FNoDelay, 1, 0);
  if setsockopt(Socket, IPPROTO_TCP, TCP_NODELAY, @V, SizeOf(V)) = SOCKET_ERROR then
    LogDelegate(Format('TSocket.SetNoDelay() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)]));
end;

function TSocket.GetSocketInfo: string;
begin
  if (FHost = '') or (Port = 0) then
    Result := '<Host: ' + GetPeerAddress + ' Port: ' + GetPeerPort.ToString + '>'
  else
    Result := '<Host: ' + FHost + ' Port: ' + Port.ToString + '>';
end;

function TSocket.GetPeerHost: string;
var
  Addr: TSockAddrStorage;
  AddrPtr: PSockAddr;
  AddrLen: Integer;
  ClientHost: array[0..NI_MAXHOST-1] of Char;
  ClientService: array[0..NI_MAXSERV-1] of Char;
begin
  if FPeerHost = '' then begin
    if Socket = INVALID_SOCKET then
      Exit(FPeerHost);

    AddrPtr := GetCachedAddress(AddrLen);
    if AddrPtr = nil then begin
      AddrLen := SizeOf(Addr);
      if getpeername(Socket, PSockAddr(@Addr)^, AddrLen) <> 0 then
        Exit(FPeerHost);
      AddrPtr := PSockAddr(@Addr);
      SetCachedAddress(AddrPtr^, AddrLen);
    end;

    GetNameInfoW(AddrPtr^, AddrLen, ClientHost, NI_MAXHOST, ClientService, NI_MAXSERV, 0);
    FPeerHost := ClientHost;
  end;
  Result := FPeerHost;
end;

function TSocket.GetPeerAddress: string;
var
  Addr: TSockAddrStorage;
  AddrPtr: PSockAddr;
  AddrLen: Integer;
  ClientHost: array[0..NI_MAXHOST-1] of Char;
  ClientService: array[0..NI_MAXSERV-1] of Char;
begin
  if FPeerAddress = '' then begin
    if Socket = INVALID_SOCKET then
      Exit(FPeerAddress);

    AddrPtr := GetCachedAddress(AddrLen);
    if AddrPtr = nil then begin
      AddrLen := SizeOf(Addr);
      if getpeername(Socket, PSockAddr(@Addr)^, AddrLen) <> 0 then
        Exit(FPeerHost);
      AddrPtr := PSockAddr(@Addr);
      SetCachedAddress(AddrPtr^, AddrLen);
    end;

    GetNameInfoW(AddrPtr^, AddrLen, ClientHost, NI_MAXHOST, ClientService, NI_MAXSERV, NI_NUMERICHOST or NI_NUMERICSERV);
    FPeerAddress := ClientHost;
    TryStrToInt(ClientService, FPeerPort);
  end;
  Result := FPeerAddress
end;

function TSocket.GetPeerPort: Integer;
begin
  GetPeerAddress;
  Result := FPeerPort;
end;

function TSocket.GetOrigin: string;
begin
  Result := GetPeerHost + ':' + GetPeerPort.ToString;
end;

procedure TSocket.SetRecvTimeout(ARecvTimeout: Longword);
begin
  inherited SetRecvTimeout(ARecvTimeout);
  SetGenericTimeout(Socket, ARecvTimeout, SO_RCVTIMEO);
end;

procedure TSocket.SetSendTimeout(ASendTimeout: Longword);
begin
  inherited SetSendTimeout(ASendTimeout);
  SetGenericTimeout(Socket, ASendTimeout, SO_SNDTIMEO);
end;

procedure TSocket.SetKeepAlive(AKeepAlive: Boolean);
var
  Value: Integer;
begin
  inherited SetKeepAlive(AKeepAlive);

  Value := IfThen(KeepAlive, 1, 0);
  if setsockopt(Socket, SOL_SOCKET, SO_KEEPALIVE, @Value, SizeOf(Value)) = SOCKET_ERROR then
    LogDelegate(Format('TSocket.SetKeepAlive() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)]));
end;

constructor TSocket.Create(ALogDelegate: TBaseSocket.TLogDelegate = nil);
begin
  // Not needed, but just a placeholder
  inherited Create(ALogDelegate);
end;

constructor TSocket.Create(AHost: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate);
begin
  inherited Create(APort, ALogDelegate);
  FHost := AHost;
end;

constructor TSocket.Create(ASocket: Winapi.Winsock2.TSocket; ALogDelegate: TBaseSocket.TLogDelegate);
begin
  inherited Create(ALogDelegate);
  Socket := ASocket;
end;

constructor TSocket.Create(ASocket: Winapi.Winsock2.TSocket; AInterruptListener: ISmartPointer<Winapi.Winsock2.TSocket>;
  ALogDelegate: TBaseSocket.TLogDelegate);
begin
  inherited Create(ALogDelegate);
  Socket := ASocket;
  FInterruptListener := AInterruptListener;
end;

procedure TSocket.Open;
begin
  if IsOpen then Exit;
  LocalOpen;
end;

procedure TSocket.Close;
begin
  inherited Close;
  InitPeerInfo;
end;

function TSocket.Read(var Buf; Len: Integer): Integer;
label
  TryAgain;
var
  Retries: Longword;
  EAgainThreshold,
  ReadElapsed: UInt64;
  Start: TDateTime;
  Got: Integer;
  Fds: TFdSet;
  ErrnoCopy: Integer;
  TVal: TTimeVal;
  PTVal: PTimeVal;
  Ret: Integer;
begin
  if Socket = INVALID_SOCKET then
    raise TTransportExceptionNotOpen.Create('Called read on non-open socket');

  Retries := 0;

  // THRIFT_EAGAIN can be signalled both when a timeout has occurred and when
  // the system is out of resources (an awesome undocumented feature).
  // The following is an approximation of the time interval under which
  // THRIFT_EAGAIN is taken to indicate an out of resources error.
  EAgainThreshold := 0;
  if RecvTimeout <> 0 then
    // if a readTimeout is specified along with a max number of recv retries, then
    // the threshold will ensure that the read timeout is not exceeded even in the
    // case of resource errors
    EAgainThreshold := RecvTimeout div IfThen(FMaxRecvRetries > 0, FMaxRecvRetries, 2);

TryAgain:
  // Read from the socket
  if RecvTimeout > 0 then
    Start := Now
  else
    // if there is no read timeout we don't need the TOD to determine whether
    // an THRIFT_EAGAIN is due to a timeout or an out-of-resource condition.
    Start := 0;

  if Assigned(FInterruptListener) then begin
    FD_ZERO(Fds);
    _FD_SET(Socket, Fds);
    _FD_SET(FInterruptListener, Fds);
    if RecvTimeout > 0 then begin
      TVal.tv_sec := RecvTimeout div 1000;
      TVal.tv_usec := (RecvTimeout mod 1000) * 1000;
      PTVal := @TVal;
    end
    else
      PTVal := nil;

    Ret := select(2, @Fds, nil, nil, PTVal);
    ErrnoCopy := WSAGetLastError;
    if Ret < 0 then begin
      // error cases
      if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin
        Inc(Retries);
        goto TryAgain;
      end;
      LogDelegate(Format('TSocket.Read() select() %s', [SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)]));
    end
    else if Ret > 0 then begin
      // Check the interruptListener
      if FD_ISSET(FInterruptListener, Fds) then
        raise TTransportExceptionInterrupted.Create('Interrupted');
    end
    else // Ret = 0
      raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (timed out)');

    // falling through means there is something to recv and it cannot block
  end;

  Got := recv(Socket, Buf, Len, 0);
  ErrnoCopy := WSAGetLastError;
  // Check for error on read
  if Got < 0 then begin
    if ErrnoCopy = WSAEWOULDBLOCK then begin
      // if no timeout we can assume that resource exhaustion has occurred.
      if RecvTimeout = 0 then
        raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (unavailable resources)');
      // check if this is the lack of resources or timeout case
      ReadElapsed := MilliSecondsBetween(Now, Start);
      if (EAgainThreshold = 0) or (ReadElapsed < EAgainThreshold) then begin
        if Retries < FMaxRecvRetries then begin
          Inc(Retries);
          Sleep(1);
          goto TryAgain;
        end
        else
          raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (unavailable resources)');
      end
      else
        // infer that timeout has been hit
        raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (timed out)');
    end;

    // If interrupted, try again
    if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin
      Inc(Retries);
      goto TryAgain;
    end;

    if ErrnoCopy = WSAECONNRESET then
      Exit(0);

    // This ish isn't open
    if ErrnoCopy = WSAENOTCONN then
      raise TTransportExceptionNotOpen.Create('WSAENOTCONN');

    // Timed out!
    if ErrnoCopy = WSAETIMEDOUT then
      raise TTransportExceptionNotOpen.Create('WSAETIMEDOUT');

    // Now it's not a try again case, but a real probblez
    LogDelegate(Format('TSocket.Read() recv() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)]));

    // Some other error, whatevz
    raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  Result := Got;
end;

procedure TSocket.Write(const Buf; Len: Integer);
var
  Sent, B: Integer;
begin
  Sent := 0;
  while Sent < Len do begin
    B := WritePartial((PByte(@Buf) + Sent)^, Len - Sent);
    if B = 0 then
      // This should only happen if the timeout set with SO_SNDTIMEO expired.
      // Raise an exception.
      raise TTransportExceptionTimedOut.Create('send timeout expired');
    Inc(Sent, B);
  end;
end;

function TSocket.WritePartial(const Buf; Len: Integer): Integer;
var
  B: Integer;
  ErrnoCopy: Integer;
begin
  if Socket = INVALID_SOCKET then
    raise TTransportExceptionNotOpen.Create('Called write on non-open socket');

  B := send(Socket, Buf, Len, 0);

  if B < 0 then begin
    // Fail on a send error
    ErrnoCopy := WSAGetLastError;
    if ErrnoCopy = WSAEWOULDBLOCK then
      Exit(0);

    LogDelegate(Format('TSocket.WritePartial() send() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)]));

    if (ErrnoCopy = WSAECONNRESET) or (ErrnoCopy = WSAENOTCONN) then begin
      Close;
      raise TTransportExceptionNotOpen.Create(Format('write() send(): %s', [SysErrorMessage(ErrnoCopy)]));
    end;

    raise TTransportExceptionUnknown.Create(Format('write() send(): %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // Fail on blocked send
  if B = 0 then
    raise TTransportExceptionNotOpen.Create('Socket send returned 0.');

  Result := B;
end;

function TSocket.GetCachedAddress(out Len: Integer): PSockAddr;
begin
  case FCachedPeerAddr.ipv4.sin_family of
    AF_INET: begin
      Len := SizeOf(TSockAddrIn);
      Result := PSockAddr(@FCachedPeerAddr.ipv4);
    end;
    AF_INET6: begin
      Len := SizeOf(TSockAddrIn6);
      Result := PSockAddr(@FCachedPeerAddr.ipv6);
    end;
  else
    Len := 0;
    Result := nil;
  end;
end;

procedure TSocket.SetCachedAddress(const Addr: TSockAddr; Len: Integer);
begin
  case Addr.sa_family of
    AF_INET: if Len = SizeOf(TSockAddrIn) then FCachedPeerAddr.ipv4 := PSockAddrIn(@Addr)^;
    AF_INET6: if Len = SizeOf(TSockAddrIn6) then FCachedPeerAddr.ipv6 := PSockAddrIn6(@Addr)^;
  end;
  FPeerAddress := '';
  FPeerHost := '';
  FPeerPort := 0;
end;

procedure TSocket.SetLinger(LingerOn: Boolean; LingerVal: Integer);
var
  L: TLinger;
begin
  FLingerOn := LingerOn;
  FLingerVal := LingerVal;
  if Socket = INVALID_SOCKET then
    Exit;

  L.l_onoff := IfThen(FLingerOn, 1, 0);
  L.l_linger := LingerVal;

  if setsockopt(Socket, SOL_SOCKET, SO_LINGER, @L, SizeOf(L)) = SOCKET_ERROR then
    LogDelegate(Format('TSocket.SetLinger() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)]));
end;

function TSocket.Peek: Boolean;
var
  Retries: Longword;
  Fds: TFdSet;
  TVal: TTimeVal;
  PTVal: PTimeVal;
  Ret: Integer;
  ErrnoCopy: Integer;
  Buf: Byte;
begin
  if not IsOpen then Exit(False);

  if Assigned(FInterruptListener) then begin
    Retries := 0;
    while true do begin
      FD_ZERO(Fds);
      _FD_SET(Socket, Fds);
      _FD_SET(FInterruptListener, Fds);
      if RecvTimeout > 0 then begin
        TVal.tv_sec := RecvTimeout div 1000;
        TVal.tv_usec := (RecvTimeout mod 1000) * 1000;
        PTVal := @TVal;
      end
      else
        PTVal := nil;

      Ret := select(2, @Fds, nil, nil, PTVal);
      ErrnoCopy := WSAGetLastError;
      if Ret < 0 then begin
        // error cases
        if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin
          Inc(Retries);
          Continue;
        end;
        LogDelegate(Format('TSocket.Peek() select() %s', [SysErrorMessage(ErrnoCopy)]));
        raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)]));
      end
      else if Ret > 0 then begin
        // Check the interruptListener
        if FD_ISSET(FInterruptListener, Fds) then
          Exit(False);
        // There must be data or a disconnection, fall through to the PEEK
        Break;
      end
      else
        // timeout
        Exit(False);
    end;
  end;

  // Check to see if data is available or if the remote side closed
  Ret := recv(Socket, Buf, 1, MSG_PEEK);
  if Ret = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    if ErrnoCopy = WSAECONNRESET then begin
      Close;
      Exit(False);
    end;
    LogDelegate(Format('TSocket.Peek() recv() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionUnknown.Create(Format('recv(): %s', [SysErrorMessage(ErrnoCopy)]));
  end;
  Result := Ret > 0;
end;

function TServerSocket.CreateSocketObj(Client: Winapi.Winsock2.TSocket): TSocket;
begin
  if FInterruptableChildren then
    Result := TSocket.Create(Client, FChildInterruptSockReader)
  else
    Result := TSocket.Create(Client);
end;

procedure TServerSocket.Notify(NotifySocket: Winapi.Winsock2.TSocket);
var
  Byt: Byte;
begin
  if NotifySocket <> INVALID_SOCKET then begin
    Byt := 0;
    if send(NotifySocket, Byt, SizeOf(Byt), 0) = SOCKET_ERROR then
      LogDelegate(Format('TServerSocket.Notify() send() %s', [SysErrorMessage(WSAGetLastError)]));
  end;
end;

procedure TServerSocket.SetInterruptableChildren(AValue: Boolean);
begin
  if FListening then
    raise Exception.Create('InterruptableChildren cannot be set after listen()');
  FInterruptableChildren := AValue;
end;

procedure TServerSocket.CommonInit;
begin
  inherited CommonInit;
  FInterruptableChildren := True;
  FAcceptBacklog := DEFAULT_BACKLOG;
  FAcceptTimeout := 0;
  FRetryLimit := 0;
  FRetryDelay := 0;
  FTcpSendBuffer := 0;
  FTcpRecvBuffer := 0;
  FListening := False;
  FInterruptSockWriter := INVALID_SOCKET;
  FInterruptSockReader := INVALID_SOCKET;
  FChildInterruptSockWriter := INVALID_SOCKET;
end;

constructor TServerSocket.Create(APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil);
begin
  // Unnecessary, but here for documentation purposes
  inherited Create(APort, ALogDelegate);
end;

constructor TServerSocket.Create(APort: Integer; ASendTimeout, ARecvTimeout: Longword; ALogDelegate: TBaseSocket.TLogDelegate);
begin
  inherited Create(APort, ALogDelegate);
  SendTimeout := ASendTimeout;
  RecvTimeout := ARecvTimeout;
end;

constructor TServerSocket.Create(AAddress: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate);
begin
  inherited Create(APort, ALogDelegate);
  FAddress := AAddress;
end;

procedure TServerSocket.Listen;

  function CreateSocketPair(var Reader, Writer: Winapi.Winsock2.TSocket): Integer;
  label
    Error;
  type
    TSAUnion = record
    case Integer of
      0: (inaddr: TSockAddrIn);
      1: (addr: TSockAddr);
    end;
  var
    a: TSAUnion;
    listener: Winapi.Winsock2.TSocket;
    e: Integer;
    addrlen: Integer;
    flags: DWORD;
    reuse: Integer;
  begin
    addrlen := SizeOf(a.inaddr);
    flags := 0;
    reuse := 1;

    listener := Winapi.Winsock2.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if listener = INVALID_SOCKET then
      Exit(SOCKET_ERROR);

    FillChar(a, SizeOf(a), 0);
    a.inaddr.sin_family := AF_INET;
    a.inaddr.sin_addr.s_addr := htonl(INADDR_LOOPBACK);
    a.inaddr.sin_port := 0;
    Reader := INVALID_SOCKET;
    Writer := INVALID_SOCKET;

    // ignore errors coming out of this setsockopt.  This is because
    // SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
    // want to force socket pairs to be an admin.
    setsockopt(listener, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @reuse, SizeOf(reuse));
    if bind(listener, a.addr, SizeOf(a.inaddr)) = SOCKET_ERROR then
      goto Error;

    if getsockname(listener, a.addr, addrlen) = SOCKET_ERROR then
      goto Error;

    if Winapi.Winsock2.listen(listener, 1) = SOCKET_ERROR then
      goto Error;

    Reader := WSASocket(AF_INET, SOCK_STREAM, 0, nil, 0, flags);
    if Reader = INVALID_SOCKET then
      goto Error;

    if connect(Reader, a.addr, SizeOf(a.inaddr)) = SOCKET_ERROR then
      goto Error;

    Writer := Winapi.Winsock2.accept(listener, nil, nil);
    if Writer = INVALID_SOCKET then
      goto Error;

    closesocket(listener);
    Exit(0);

  Error:
    e := WSAGetLastError;
    closesocket(listener);
    closesocket(Reader);
    closesocket(Writer);
    WSASetLastError(e);
    Result := SOCKET_ERROR;
  end;

var
  TempIntReader,
  TempIntWriter: Winapi.Winsock2.TSocket;
  One: Cardinal;
  ErrnoCopy: Integer;
  Ling: TLinger;
  Retries: Integer;
  AddrInfo: IGetAddrInfoWrapper;
  SA: TSockAddrStorage;
  Len: Integer;
begin
  // Create the socket pair used to interrupt
  if CreateSocketPair(TempIntReader, TempIntWriter) = SOCKET_ERROR then begin
    LogDelegate(Format('TServerSocket.Listen() CreateSocketPair() Interrupt %s', [SysErrorMessage(WSAGetLastError)]));
    FInterruptSockReader := INVALID_SOCKET;
    FInterruptSockWriter := INVALID_SOCKET;
  end
  else begin
    FInterruptSockReader := TempIntReader;
    FInterruptSockWriter := TempIntWriter;
  end;

  // Create the socket pair used to interrupt all clients
  if CreateSocketPair(TempIntReader, TempIntWriter) = SOCKET_ERROR then begin
    LogDelegate(Format('TServerSocket.Listen() CreateSocketPair() ChildInterrupt %s', [SysErrorMessage(WSAGetLastError)]));
    FChildInterruptSockReader := TSmartPointer<Winapi.Winsock2.TSocket>.Create(INVALID_SOCKET, nil);
    FChildInterruptSockWriter := INVALID_SOCKET;
  end
  else begin
    FChildInterruptSockReader := TSmartPointer<Winapi.Winsock2.TSocket>.Create(TempIntReader, DestroyerOfFineSockets);
    FChildInterruptSockWriter := TempIntWriter;
  end;

  if (Port < 0) or (Port > $FFFF) then
    raise TTransportExceptionBadArgs.Create('Specified port is invalid');

  AddrInfo := CreateSocket(FAddress, Port);

  // Set SO_EXCLUSIVEADDRUSE to prevent 2MSL delay on accept
  One := 1;
  setsockopt(Socket, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @one, SizeOf(One));
  // ignore errors coming out of this setsockopt on Windows.  This is because
  // SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
  // want to force servers to be an admin.

  // Set TCP buffer sizes
  if FTcpSendBuffer > 0 then begin
    if setsockopt(Socket, SOL_SOCKET, SO_SNDBUF, @FTcpSendBuffer, SizeOf(FTcpSendBuffer)) = SOCKET_ERROR then begin
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_SNDBUF %s', [SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionNotOpen.Create(Format('Could not set SO_SNDBUF: %s', [SysErrorMessage(ErrnoCopy)]));
    end;
  end;

  if FTcpRecvBuffer > 0 then begin
    if setsockopt(Socket, SOL_SOCKET, SO_RCVBUF, @FTcpRecvBuffer, SizeOf(FTcpRecvBuffer)) = SOCKET_ERROR then begin
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_RCVBUF %s', [SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionNotOpen.Create(Format('Could not set SO_RCVBUF: %s', [SysErrorMessage(ErrnoCopy)]));
    end;
  end;

  // Turn linger off, don't want to block on calls to close
  Ling.l_onoff := 0;
  Ling.l_linger := 0;
  if setsockopt(Socket, SOL_SOCKET, SO_LINGER, @Ling, SizeOf(Ling)) = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_LINGER %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('Could not set SO_LINGER: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // TCP Nodelay, speed over bandwidth
  if setsockopt(Socket, IPPROTO_TCP, TCP_NODELAY, @One, SizeOf(One)) = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TServerSocket.Listen() setsockopt() TCP_NODELAY %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('Could not set TCP_NODELAY: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // Set NONBLOCK on the accept socket
  if ioctlsocket(Socket, Integer(FIONBIO), One) = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TServerSocket.Listen() ioctlsocket() FIONBIO %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() FIONBIO: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // prepare the port information
  // we may want to try to bind more than once, since THRIFT_NO_SOCKET_CACHING doesn't
  // always seem to work. The client can configure the retry variables.
  Retries := 0;
  while True do begin
    if bind(Socket, AddrInfo.Res^.ai_addr^, AddrInfo.Res^.ai_addrlen) = 0 then
      Break;
    Inc(Retries);
    if Retries > FRetryLimit then
      Break;
    Sleep(FRetryDelay * 1000);
  end;

  // retrieve bind info
  if (Port = 0) and (Retries < FRetryLimit) then begin
    Len := SizeOf(SA);
    FillChar(SA, Len, 0);
    if getsockname(Socket, PSockAddr(@SA)^, Len) = SOCKET_ERROR then
      LogDelegate(Format('TServerSocket.Listen() getsockname() %s', [SysErrorMessage(WSAGetLastError)]))
    else begin
      if SA.ss_family = AF_INET6 then
        Port := ntohs(PSockAddrIn6(@SA)^.sin6_port)
      else
        Port := ntohs(PSockAddrIn(@SA)^.sin_port);
    end;
  end;

  // throw an error if we failed to bind properly
  if (Retries > FRetryLimit) then begin
    LogDelegate(Format('TServerSocket.Listen() BIND %d', [Port]));
    Close;
    raise TTransportExceptionNotOpen.Create(Format('Could not bind: %s', [SysErrorMessage(WSAGetLastError)]));
  end;

  if Assigned(FListenCallback) then
    FListenCallback(Socket);

  // Call listen
  if Winapi.Winsock2.listen(Socket, FAcceptBacklog) = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TServerSocket.Listen() listen() %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionNotOpen.Create(Format('Could not listen: %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // The socket is now listening!
end;

function TServerSocket.Accept: TSocket;
var
  Fds: TFdSet;
  MaxEInters,
  NumEInters: Integer;
  TVal: TTimeVal;
  PTVal: PTimeVal;
  ErrnoCopy: Integer;
  Buf: Byte;
  ClientAddress: TSockAddrStorage;
  Size: Integer;
  ClientSocket: Winapi.Winsock2.TSocket;
  Zero: Cardinal;
  Client: TSocket;
  Ret: Integer;
begin
  MaxEInters := 5;
  NumEInters := 0;

  while True do begin
    FD_ZERO(Fds);
    _FD_SET(Socket, Fds);
    _FD_SET(FInterruptSockReader, Fds);
    if FAcceptTimeout > 0 then begin
      TVal.tv_sec := FAcceptTimeout div 1000;
      TVal.tv_usec := (FAcceptTimeout mod 1000) * 1000;
      PTVal := @TVal;
    end
    else
      PTVal := nil;

    // TODO: if WSAEINTR is received, we'll restart the timeout.
    // To be accurate, we need to fix this in the future.
    Ret := select(2, @Fds, nil, nil, PTVal);

    if Ret < 0 then begin
      // error cases
      if (WSAGetLastError = WSAEINTR) and (NumEInters < MaxEInters) then begin
        // THRIFT_EINTR needs to be handled manually and we can tolerate
        // a certain number
        Inc(NumEInters);
        Continue;
      end;
      ErrnoCopy := WSAGetLastError;
      LogDelegate(Format('TServerSocket.Accept() select() %s', [SysErrorMessage(ErrnoCopy)]));
      raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)]));
    end
    else if Ret > 0 then begin
      // Check for an interrupt signal
      if (FInterruptSockReader <> INVALID_SOCKET) and FD_ISSET(FInterruptSockReader, Fds) then begin
        if recv(FInterruptSockReader, Buf, SizeOf(Buf), 0) = SOCKET_ERROR then
          LogDelegate(Format('TServerSocket.Accept() recv() interrupt %s', [SysErrorMessage(WSAGetLastError)]));
        raise TTransportExceptionInterrupted.Create('interrupted');
      end;

      // Check for the actual server socket being ready
      if FD_ISSET(Socket, Fds) then
        Break;
    end
    else begin
      LogDelegate('TServerSocket.Accept() select() 0');
      raise TTransportExceptionUnknown.Create('unknown error');
    end;
  end;

  Size := SizeOf(ClientAddress);
  ClientSocket := Winapi.Winsock2.accept(Socket, @ClientAddress, @Size);
  if ClientSocket = INVALID_SOCKET then begin
    ErrnoCopy := WSAGetLastError;
    LogDelegate(Format('TServerSocket.Accept() accept() %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionUnknown.Create(Format('accept(): %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  // Make sure client socket is blocking
  Zero := 0;
  if ioctlsocket(ClientSocket, Integer(FIONBIO), Zero) = SOCKET_ERROR then begin
    ErrnoCopy := WSAGetLastError;
    closesocket(ClientSocket);
    LogDelegate(Format('TServerSocket.Accept() ioctlsocket() FIONBIO %s', [SysErrorMessage(ErrnoCopy)]));
    raise TTransportExceptionUnknown.Create(Format('ioctlsocket(): %s', [SysErrorMessage(ErrnoCopy)]));
  end;

  Client := CreateSocketObj(ClientSocket);
  if SendTimeout > 0 then
    Client.SendTimeout := SendTimeout;
  if RecvTimeout > 0 then
    Client.RecvTimeout := RecvTimeout;
  if KeepAlive then
    Client.KeepAlive := KeepAlive;
  Client.SetCachedAddress(PSockAddr(@ClientAddress)^, Size);

  if Assigned(FAcceptCallback) then
    FAcceptCallback(ClientSocket);

  Result := Client;
end;

procedure TServerSocket.Interrupt;
begin
  Notify(FInterruptSockWriter);
end;

procedure TServerSocket.InterruptChildren;
begin
  Notify(FChildInterruptSockWriter);
end;

procedure TServerSocket.Close;
begin
  inherited Close;
  if FInterruptSockWriter <> INVALID_SOCKET then
    closesocket(FInterruptSockWriter);
  if FInterruptSockReader <> INVALID_SOCKET then
    closesocket(FInterruptSockReader);
  if FChildInterruptSockWriter <> INVALID_SOCKET then
    closesocket(FChildInterruptSockWriter);
  FChildInterruptSockReader := TSmartPointer<Winapi.Winsock2.TSocket>.Create(INVALID_SOCKET, nil);
  FListening := False;
end;

{$ENDIF} // not for OLD_SOCKETS
end.
