clientthread.pas
来自「著名的SecureBlackBox控件完整源码」· PAS 代码 · 共 586 行 · 第 1/2 页
PAS
586 行
if (AThread.Connection <> nil) and (AThread.Connection.Socket <> nil) and
(AThread.Connection.Socket.Binding <> nil) then
begin
Conn.FRemoteHost := AThread.Connection.Socket.Binding.PeerIP;
Conn.FRemotePort := AThread.Connection.Socket.Binding.PeerPort;
end;
while (not AThread.Terminated) and
not ((Conn.FInState = icsClosed) and (Conn.FOutState = ocsClosed)) do
begin
// processing socket endpoint
if (Conn.FInState = icsActive) then
begin
if AThread.Connection.Connected then
begin
try
AThread.Connection.CheckForGracefulDisconnect();
AThread.Connection.CheckForDisconnect();
// reading data from socket connection
if (AThread.Connection.InputBuffer.Size > 0) then
begin
//S := AThread.Connection.CurrentReadBuffer;
S := AThread.Connection.InputBuffer.Extract(AThread.Connection.InputBuffer.Size);
if Length(S) > 0 then
Conn.WriteToChannelBuffer(@S[1], Length(S));
end;
// writing cached data to socket connection
repeat
Read := Conn.ReadFromSocketBuffer(@Buf[0], Length(Buf));
if Read > 0 then
AThread.Connection.WriteBuffer(Buf[0], Read);
until Read = 0;
except
on E : Exception do
begin
Log(E.Message, false);
Conn.FInState := icsClosing;
if (AThread.Connection <> nil) and
(AThread.Connection.Connected) and (AThread.Connection.Socket <> nil) and
(AThread.Connection.Socket.Binding <> nil) then
AThread.Connection.Disconnect;
end;
end;
end
else
begin
Conn.FInState := icsClosed;
end;
end;
// processing channel endpoint
if Conn.FOutState = ocsActive then
begin
repeat
Read := Conn.ReadFromChannelBuffer(@Buf[0], Length(Buf));
if Read > 0 then
begin
FCS.Acquire;
try
Conn.FChannel.SendData(@Buf[0], Read);
finally
FCS.Release;
end;
Inc(Conn.FSent, Read);
end;
until Read = 0;
end;
// checking connection states
if (Conn.FInState = icsActive) and (Conn.FOutState in [ocsClosed, ocsClosing]) then
begin
Conn.FInState := icsClosing;
Conn.FThread.Connection.Disconnect;
end
else if (Conn.FOutState = ocsActive) and (Conn.FInState in [icsClosing, icsClosed]) then
begin
Conn.FOutState := ocsClosing;
FCS.Acquire;
try
Conn.FChannel.Close(true);
finally
FCS.Release;
end;
end
else if (Conn.FInState = icsClosing) and (not AThread.Connection.Connected) then
begin
Conn.FInState := icsClosed;
end;
if not FNoGUI then
begin
FGuiCS.Acquire;
try
DoConnectionChange(Conn);
finally
FGuiCS.Release;
end;
end;
Sleep(50);
end;
// clearing the 'Data' property due to a bug in Indy 9 implementation
// (the FreeAndNil is called for object referenced by Data property)
if not FNoGUI then
begin
FGuiCS.Acquire;
try
DoConnectionRemove(Conn);
finally
FGuiCS.Release;
end;
end;
TConnection(AThread.Data).Free;
AThread.Data := nil;
end;
procedure TClientThread.TCPServerThreadTerminate(Sender: TObject);
begin
end;
procedure TClientThread.Execute;
begin
try
FError := false;
// opening listening socket
FTCPServer.Active := true;
// establishing TCP connection
FTCPClient.Connect();
// opening SSH client
FSSHClient.Open;
// running client loop
while (not Terminated) and (not FError) and (FTCPClient.Connected) do
begin
try
while (FTCPClient.Socket <> nil) and (FTCPClient.Socket.Readable()) do
begin
FCS.Acquire;
try
FSSHClient.DataAvailable;
finally
FCS.Release;
end;
end;
Sleep(50);
except
Break;
end;
end;
// closing sockets
if FTCPClient.Connected then
FTCPClient.Disconnect;
if FTCPServer.Active then
FTCPServer.Active := false;
except
on E : Exception do
Log('Error: ' + E.Message, true);
end;
end;
procedure TClientThread.Log(const S : string; Error : boolean);
begin
if not FNoGUI then
begin
FGuiCS.Acquire;
try
FLogString := S;
FLogError := Error;
Synchronize(TriggerLog);
finally
FGuiCS.Release;
end;
end;
end;
procedure TClientThread.DoConnectionAdd(Conn : TConnection);
begin
FConn := Conn;
Synchronize(TriggerConnectionAdd);
end;
procedure TClientThread.DoConnectionRemove(Conn : TConnection);
begin
FConn := Conn;
Synchronize(TriggerConnectionRemove);
end;
procedure TClientThread.DoConnectionChange(Conn : TConnection);
begin
FConn := Conn;
Synchronize(TriggerConnectionChange);
end;
procedure TClientThread.TriggerLog;
begin
if Assigned(FOnLog) then
FOnLog(Self, FLogString, FLogError);
end;
procedure TClientThread.TriggerConnectionChange;
begin
if Assigned(FOnChange) then
FOnChange(Self, FConn);
end;
procedure TClientThread.TriggerConnectionAdd;
begin
if Assigned(FOnConnectionAdd) then
FOnConnectionAdd(Self, FConn);
end;
procedure TClientThread.TriggerConnectionRemove;
begin
if Assigned(FOnConnectionRemove) then
FOnConnectionRemove(Self, FConn);
end;
////////////////////////////////////////////////////////////////////////////////
// TConnection class
constructor TConnection.Create;
begin
inherited;
FChannel := nil;
FThread := nil;
SetLength(FChannelBuffer, 0);
SetLength(FSocketBuffer, 0);
FSharedResource := TElSharedResource.Create;
FInState := icsActive;
FOutState := ocsEstablishing;
FSent := 0;
FReceived := 0;
end;
destructor TConnection.Destroy;
begin
FreeAndNil(FSharedResource);
inherited;
end;
function TConnection.ReadFromSocketBuffer(Buffer: pointer; MaxSize: integer): integer;
begin
FSharedResource.WaitToRead;
try
Result := Min(MaxSize, Length(FSocketBuffer));
Move(FSocketBuffer[0], Buffer^, Result);
Move(FSocketBuffer[Result], FSocketBuffer[0], Length(FSocketBuffer) - Result);
SetLength(FSocketBuffer, Length(FSocketBuffer) - Result);
finally
FSharedResource.Done;
end;
end;
function TConnection.ReadFromChannelBuffer(Buffer: pointer; MaxSize: integer): integer;
begin
FSharedResource.WaitToRead;
try
Result := Min(MaxSize, Length(FChannelBuffer));
Move(FChannelBuffer[0], Buffer^, Result);
Move(FChannelBuffer[Result], FChannelBuffer[0], Length(FChannelBuffer) - Result);
SetLength(FChannelBuffer, Length(FChannelBuffer) - Result);
finally
FSharedResource.Done;
end;
end;
procedure TConnection.WriteToSocketBuffer(Buffer: pointer; Size: integer);
var
OldLen : integer;
begin
FSharedResource.WaitToWrite;
try
OldLen := Length(FSocketBuffer);
SetLength(FSocketBuffer, OldLen + Size);
Move(Buffer^, FSocketBuffer[OldLen], Size);
finally
FSharedResource.Done;
end;
end;
procedure TConnection.WriteToChannelBuffer(Buffer: pointer; Size: integer);
var
OldLen : integer;
begin
FSharedResource.WaitToWrite;
try
OldLen := Length(FChannelBuffer);
SetLength(FChannelBuffer, OldLen + Size);
Move(Buffer^, FChannelBuffer[OldLen], Size);
finally
FSharedResource.Done;
end;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?