in lib/delphi/src/Thrift.Socket.pas [1294:1494]
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;
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
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;
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);
One := 1;
setsockopt(Socket, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @one, SizeOf(One));
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;
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;
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;
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;
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;
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;
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);
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;
end;