7 Classes } {, IdException},
8 IdComponent
, IdGlobal
, IdSocketHandle
, IdIntercept
;
11 GRecvBufferSizeDefault
= 32768;
12 GSendBufferSizeDefault
= 32768;
15 TIdBuffer
= object({TMemoryStream}TStream
)
17 procedure RemoveXBytes(const AByteCount
: integer);
24 TIdTCPConnection
= object(TIdComponent
)
26 FASCIIFilter
: boolean;
27 FBinding
: PIdSocketHandle
;//TIdSocketHandle;
28 FBuffer
: PIdBuffer
;//TIdBuffer;
29 FClosedGracefully
: boolean;
30 FCmdResultDetails
: PStrList
;
31 FIntercept
: PIdConnectionIntercept
;//TIdConnectionIntercept;
32 FInterceptEnabled
: Boolean;
33 FOnDisconnected
: TOnEvent
;//TNotifyEvent;
34 FReadLnTimedOut
: Boolean;
35 FRecvBuffer
: PIdBuffer
;//TIdBuffer;
37 FSendBufferSize
: Integer;
38 FWriteBuffer
: PIdBuffer
;//TIdBuffer;
39 FWriteBufferThreshhold
: Integer;
41 procedure DoOnDisconnected
; virtual;
42 function GetCmdResult
: string;
43 function GetRecvBufferSize
: Integer;
44 // procedure Notification(AComponent: PObj{TComponent}; Operation: TOperation);
46 procedure ResetConnection
; virtual;
47 procedure SetIntercept(AValue
: PIdConnectionIntercept
{TIdConnectionIntercept});
48 procedure SetInterceptEnabled(AValue
: Boolean);
49 procedure SetRecvBufferSize(const Value
: Integer);
51 procedure Init
; virtual;
52 function AllData
: string; virtual;
53 procedure CancelWriteBuffer
;
54 procedure Capture(ADest
: TObject
; const ADelim
: string = '.'; const
55 AIsRFCMessage
: Boolean = False);
56 procedure CheckForDisconnect(const ARaiseExceptionIfDisconnected
: boolean =
58 const AIgnoreBuffer
: boolean = false); virtual;
59 procedure CheckForGracefulDisconnect(const ARaiseExceptionIfDisconnected
:
62 function CheckResponse(const AResponse
: SmallInt
; const AAllowedResponses
:
65 procedure ClearWriteBuffer
;
66 procedure CloseWriteBuffer
;
67 function Connected
: boolean; virtual;
68 { constructor Create(AOwner: TComponent); override;
69 } function CurrentReadBuffer
: string;
70 function CurrentReadBufferSize
: integer;
72 virtual; procedure Disconnect
; virtual;
73 procedure DisconnectSocket
; virtual;
74 function ExtractXBytesFromBuffer(const AByteCount
: Integer): string;
76 procedure FlushWriteBuffer(const AByteCount
: Integer = -1);
77 function GetResponse(const AAllowedResponses
: array of SmallInt
): SmallInt
;
79 function InputLn(const AMask
: string = ''): string;
80 procedure OpenWriteBuffer(const AThreshhold
: Integer = -1);
81 procedure RaiseExceptionForCmdResult
; overload
; virtual;
82 // procedure RaiseExceptionForCmdResult(axException: TClassIdException);
84 procedure ReadBuffer(var ABuffer
; const AByteCount
: Longint);
85 function ReadCardinal(const AConvert
: boolean = true): Cardinal;
86 function ReadFromStack(const ARaiseExceptionIfDisconnected
: boolean = true;
87 const ATimeout
: integer = IdTimeoutInfinite
; const AUseBuffer
: boolean =
89 ADestStream
: {T}PIdBuffer
= nil): integer;
91 function ReadInteger(const AConvert
: boolean = true): Integer;
92 function ReadLn(const ATerminator
: string = '';
93 const ATimeout
: integer = IdTimeoutInfinite
): string; virtual;
94 function ReadLnWait
: string;
95 function ReadSmallInt(const AConvert
: boolean = true): SmallInt
;
96 procedure ReadStream(AStream
: PStream
{TStream}; AByteCount
: LongInt = -1;
97 const AReadUntilDisconnect
: boolean = false);
98 function ReadString(const ABytes
: integer): string;
99 procedure RemoveXBytesFromBuffer(const AByteCount
: Integer); virtual;
100 function SendCmd(const AOut
: string; const AResponse
: SmallInt
= -1):
102 function SendCmd(const AOut
: string; const AResponse
: array of SmallInt
):
105 function WaitFor(const AString
: string): string;
106 procedure Write(AOut
: string); virtual;
107 procedure WriteBuffer(var{const} ABuffer
; AByteCount
: Longint; const AWriteNow
:
109 procedure WriteCardinal(AValue
: Cardinal; const AConvert
: boolean = true);
110 procedure WriteHeader(axHeader
: PStrList
);
111 procedure WriteInteger(AValue
: Integer; const AConvert
: boolean = true);
112 procedure WriteLn(const AOut
: string = ''); virtual;
113 procedure WriteSmallInt(AValue
: SmallInt
; const AConvert
: boolean = true);
114 procedure WriteStream(AStream
: PStream
{TStream}; const AAll
: boolean = true;
115 const AWriteByteCount
: Boolean = false); virtual;
116 procedure WriteStrings(AValue
: PStrList
);
117 function WriteFile(AFile
: string; const AEnableTransferFile
: boolean =
121 property Binding
: PIdSocketHandle
{TIdSocketHandle} read FBinding
;
122 property ClosedGracefully
: boolean read FClosedGracefully
;
123 property CmdResult
: string read GetCmdResult
;
124 property CmdResultDetails
: PStrList read FCmdResultDetails
;
125 property ReadLnTimedOut
: Boolean read FReadLnTimedOut
;
126 property ResultNo
: SmallInt read FResultNo
;
128 property ASCIIFilter
: boolean read FASCIIFilter write FASCIIFilter default
130 property Intercept
: PIdConnectionIntercept
{TIdConnectionIntercept} read FIntercept write
132 property InterceptEnabled
: Boolean read FInterceptEnabled write
133 SetInterceptEnabled default
False;
134 // property OnDisconnected: TNotifyEvent read FOnDisconnected write
137 // property OnWorkBegin;
138 // property OnWorkEnd;
139 property RecvBufferSize
: Integer read GetRecvBufferSize write
140 SetRecvBufferSize default GRecvBufferSizeDefault
;
141 property SendBufferSize
: Integer read FSendBufferSize write FSendBufferSize
142 default GSendBufferSizeDefault
;
144 PIdTCPConnection
=^TIdTCPConnection
;
145 function NewIdBuffer
:PIdBuffer
;
146 function NewIdTCPConnection(AOwner
: {TComponent}PControl
):PIdTCPConnection
;
148 EIdTCPConnectionError = object(EIdException);
149 PBuffer=^dBuffer; type MyStupid86104=DWord;
150 EIdObjectTypeNotSupported = object(EIdTCPConnectionError);
151 Puffer=^Buffer; type MyStupid20258=DWord;
152 EIdNotEnoughDataInBuffer = object(EIdTCPConnectionError);
153 Pffer=^uffer; type MyStupid27292=DWord;
154 EIdInterceptPropIsNil = object(EIdTCPConnectionError);
155 Pfer=^ffer; type MyStupid67165=DWord;
156 EIdInterceptPropInvalid = object(EIdTCPConnectionError);
157 Per=^fer; type MyStupid31869=DWord;
158 EIdNoDataToRead = object(EIdTCPConnectionError);
159 Pr=^er; type MyStupid16179=DWord; }
165 IdStack
, IdStackConsts
, IdResourceStrings
,
168 function NewIdBuffer
:PIdBuffer
;
170 // New( Result, Create );
171 Result
:=PIdBuffer(NewMemoryStream
);//_NewStream(MemoryMethods);
174 function TIdTCPConnection
.AllData
: string;
181 Result
:= Result
+ CurrentReadBuffer
;
183 finally EndWork(wmRead
);
187 procedure TIdTCPConnection
.Capture(ADest
: TObject
; const ADelim
: string = '.';
188 const AIsRFCMessage
: Boolean = False);
201 if AIsRFCMessage
and (Copy(s
, 1, 2) = '..') then
206 { if ADest is PStrList then
208 PStrList(ADest).Add(s);
211 if ADest is TStream then
213 TStream(ADest).WriteBuffer(s[1], Length(s));
215 TStream(ADest).WriteBuffer(s[1], Length(s));
220 raise EIdObjectTypeNotSupported.Create(RSObjectTypeNotSupported);
223 finally EndWork(wmRead
);
227 procedure TIdTCPConnection
.CheckForDisconnect(const
228 ARaiseExceptionIfDisconnected
: boolean = true;
229 const AIgnoreBuffer
: boolean = false);
231 if ClosedGracefully
or (Binding
.HandleAllocated
= false) then
233 if Binding
.HandleAllocated
then
237 if ((CurrentReadBufferSize
= 0) or AIgnoreBuffer
) and
238 ARaiseExceptionIfDisconnected
then
240 (* ************************************************************* //
241 ------ If you receive an exception here, please read. ----------
245 The client has disconnected the socket normally and this exception is used to notify the
246 server handling code. This exception is normal and will only happen from within the IDE, not
247 while your program is running as an EXE. If you do not want to see this, add this exception
248 or EIdSilentException to the IDE options as exceptions not to break on.
250 From the IDE just hit F9 again and Indy will catch and handle the exception.
252 Please see the FAQ and help file for possible further information.
253 The FAQ is at http://www.nevrona.com/Indy/FAQ.html
257 The server side of this connection has disconnected normaly but your client has attempted
258 to read or write to the connection. You should trap this error using a try..except.
259 Please see the help file for possible further information.
261 // ************************************************************* *)
262 // raise EIdConnClosedGracefully.Create(RSConnectionClosedGracefully);
267 function TIdTCPConnection
.Connected
: boolean;
269 CheckForDisconnect(False);
270 result
:= Binding
.HandleAllocated
;
273 //constructor TIdTCPConnection.Create(AOwner: TComponent);
274 function NewIdTCPConnection(AOwner
: {TComponent}PControl
):PIdTCPConnection
;
277 New( Result
, Create
);
281 // FBinding := TIdSocketHandle.Create(nil);
282 // FCmdResultDetails := PStrList.Create;
283 // FRecvBuffer := TIdBuffer.Create;
285 // RecvBufferSize := GRecvBufferSizeDefault;
286 // FSendBufferSize := GSendBufferSizeDefault;
287 // FBuffer := TIdBuffer.Create;
291 procedure TIdTCPConnection
.Init
;
296 FBinding
:= NewIdSocketHandle(nil);//TIdSocketHandle.Create(nil);
297 FCmdResultDetails
:= NewStrList
;//PStrList.Create;
298 FRecvBuffer
:= NewIdBuffer
;//TIdBuffer.Create;
300 RecvBufferSize
:= GRecvBufferSizeDefault
;
301 FSendBufferSize
:= GSendBufferSizeDefault
;
302 FBuffer
:= NewIdBuffer
;//TIdBuffer.Create;
306 function TIdTCPConnection
.CurrentReadBuffer
: string;
311 ReadFromStack(False);
312 result
:= ExtractXBytesFromBuffer(FBuffer
.Size
);
316 function TIdTCPConnection
.CurrentReadBufferSize
: integer;
318 result
:= FBuffer
.Size
;
321 destructor TIdTCPConnection
.Destroy
;
324 FreeAndNil(FRecvBuffer
);
325 FreeAndNil(FCmdResultDetails
);
326 FreeAndNil(FBinding
);
330 procedure TIdTCPConnection
.Disconnect
;
335 procedure TIdTCPConnection
.DoOnDisconnected
;
337 // if assigned(OnDisconnected) then
339 // OnDisconnected(Self);
344 function TIdTCPConnection
.ExtractXBytesFromBuffer(const AByteCount
: Integer):
347 if AByteCount
> FBuffer
.Size
then
349 // raise EIdNotEnoughDataInBuffer.Create(RSNotEnoughDataInBuffer);
351 SetString(result
, PChar(FBuffer
.Memory
), AByteCount
);
352 RemoveXBytesFromBuffer(AByteCount
);
355 function TIdTCPConnection
.GetCmdResult
: string;
358 if CmdResultDetails
.Count
> 0 then
360 result
:= CmdResultDetails
.Items
[CmdResultDetails
.Count
- 1];
364 function TIdTCPConnection
.GetRecvBufferSize
: Integer;
366 result
:= FRecvBuffer
.Size
;
369 function TIdTCPConnection
.GetResponse(const AAllowedResponses
: array of
372 sLine
, sTerm
: string;
374 CmdResultDetails
.Clear
;
376 CmdResultDetails
.Add(sLine
);
377 if length(sLine
) > 3 then
379 if sLine
[4] = '-' then
381 sTerm
:= Copy(sLine
, 1, 3) + ' ';
384 CmdResultDetails
.Add(sLine
);
385 until (Length(sLine
) < 4) or (AnsiSameText(Copy(sLine
, 1, 4), sTerm
));
389 if AnsiSameText(Copy(CmdResult
, 1, 3), '+OK') then
394 if AnsiSameText(Copy(CmdResult
, 1, 4), '-ERR') then
400 FResultNo
:= StrToIntDef(Copy(CmdResult
, 1, 3), 0);
403 Result
:= CheckResponse(ResultNo
, AAllowedResponses
);
406 {procedure TIdTCPConnection.RaiseExceptionForCmdResult(axException:
409 // raise axException.Create(CmdResult);
413 procedure TIdTCPConnection
.RaiseExceptionForCmdResult
;
415 // raise EIdProtocolReplyError.CreateError(ResultNo, CmdResult);
418 procedure TIdTCPConnection
.ReadBuffer(var ABuffer
; const AByteCount
: Integer);
420 if (AByteCount
> 0) and (@ABuffer
<> nil) then
422 while CurrentReadBufferSize
< AByteCount
do
426 Move(PChar(FBuffer
.Memory
)[0], ABuffer
, AByteCount
);
427 RemoveXBytesFromBuffer(AByteCount
);
431 function TIdTCPConnection
.ReadFromStack(const ARaiseExceptionIfDisconnected
:
433 const ATimeout
: integer = IdTimeoutInfinite
; const AUseBuffer
: boolean = true;
434 ADestStream
: {T}PIdBuffer
= nil): integer;
436 nByteCount
, j
: Integer;
438 procedure DefaultRecv
;
440 nByteCount
:= Binding
.Recv(ADestStream
.Memory
^, ADestStream
.Size
, 0);
445 CheckForDisconnect(ARaiseExceptionIfDisconnected
);
448 if ADestStream
= nil then
450 ADestStream
:= FRecvBuffer
;
452 if Binding
.Readable(ATimeout
) then
454 if InterceptEnabled
then
456 if Intercept
.RecvHandling
then
458 nByteCount
:= Intercept
.Recv(ADestStream
.Memory
^, ADestStream
.Size
);
470 FClosedGracefully
:= nByteCount
= 0;
471 if not ClosedGracefully
then
473 if GStack
.CheckForSocketError(nByteCount
, [Id_WSAESHUTDOWN
]) then
476 if Binding
.HandleAllocated
then
480 if CurrentReadBufferSize
= 0 then
482 GStack
.RaiseSocketError(Id_WSAESHUTDOWN
);
487 for j
:= 1 to nByteCount
do
489 PChar(ADestStream
.Memory
)[j
] := Chr(Ord(PChar(ADestStream
.Memory
)[j
])
496 FBuffer
.Position
:= FBuffer
.Size
;
497 FBuffer
.Write
{Buffer}(ADestStream
.Memory
^, nByteCount
);
501 DoWork(wmRead
, nByteCount
);
503 if InterceptEnabled
then
505 Intercept
.DataReceived(ADestStream
.Memory
^, nByteCount
);
507 CheckForDisconnect(ARaiseExceptionIfDisconnected
);
508 result
:= nByteCount
;
513 function TIdTCPConnection
.ReadInteger(const AConvert
: boolean = true): Integer;
515 ReadBuffer(Result
, SizeOf(Result
));
518 Result
:= Integer(GStack
.WSNToHL(LongWord(Result
)));
522 function TIdTCPConnection
.ReadLn(const ATerminator
: string = '';
523 const ATimeout
: integer = IdTimeoutInfinite
): string;
529 if Length(ATerminator
) = 0 then
535 LTerminator
:= ATerminator
;
537 FReadLnTimedOut
:= False;
540 if CurrentReadBufferSize
> 0 then
542 SetString(s
, PChar(FBuffer
.Memory
), FBuffer
.Size
);
543 i
:= Pos(LTerminator
, s
);
547 CheckForDisconnect(True, True);
548 FReadLnTimedOut
:= ReadFromStack(True, ATimeout
) = 0;
549 if ReadLnTimedout
then
556 Result
:= ExtractXBytesFromBuffer(i
+ Length(LTerminator
) - 1);
557 SetLength(Result
, i
- 1);
558 if (Length(ATerminator
) = 0) and (Copy(Result
, Length(Result
), 1) = CR
) then
560 SetLength(Result
, Length(Result
) - 1);
564 function TIdTCPConnection
.ReadLnWait
: string;
567 while length(Result
) = 0 do
569 Result
:= Trim(ReadLn
);
573 procedure TIdTCPConnection
.ReadStream(AStream
: PStream
{TStream}; AByteCount
: Integer =
575 const AReadUntilDisconnect
: boolean = false);
578 LBuffer
:PIdBuffer
;// TIdBuffer;
579 LBufferCount
: integer;
582 procedure AdjustStreamSize(AStream
: PStream
{TStream}; const ASize
: integer);
586 LStreamPos
:= AStream
.Position
;
587 AStream
.Size
:= ASize
;
588 if AStream
.Position
<> LStreamPos
then
590 AStream
.Position
:= LStreamPos
;
595 if (AByteCount
= -1) and (AReadUntilDisconnect
= False) then
597 AByteCount
:= ReadInteger
;
599 if AByteCount
> -1 then
601 AdjustStreamSize(AStream
, AStream
.Position
+ AByteCount
);
604 if AReadUntilDisconnect
then
606 LWorkCount
:= High(LWorkCount
);
611 LWorkCount
:= AByteCount
;
612 BeginWork(wmRead
, LWorkCount
);
615 LBufferCount
:= Min(CurrentReadBufferSize
, LWorkCount
);
616 Dec(LWorkCount
, LBufferCount
);
617 AStream
.Write
{Buffer}(FBuffer
.Memory
^, LBufferCount
);
618 FBuffer
.RemoveXBytes(LBufferCount
);
620 LBuffer
:= NewIdBuffer();//TIdBuffer.Create;
622 while Connected
and (LWorkCount
> 0) do
624 i
:= Min(LWorkCount
, RecvBufferSize
);
625 if LBuffer
.Size
<> i
then
629 i
:= ReadFromStack(not AReadUntilDisconnect
, IdTimeoutInfinite
, False,
631 if AStream
.Position
+ i
> AStream
.Size
then
633 AdjustStreamSize(AStream
, AStream
.Size
+ 4 * CurrentReadBufferSize
);
635 AStream
.Write
{Buffer}(LBuffer
.Memory
^, i
);
638 finally LBuffer
.Free
;
640 finally EndWork(wmRead
);
642 if AStream
.Size
> AStream
.Position
then
644 AStream
.Size
:= AStream
.Position
;
648 procedure TIdTCPConnection
.RemoveXBytesFromBuffer(const AByteCount
: Integer);
650 FBuffer
.RemoveXBytes(AByteCount
);
651 DoWork(wmRead
, AByteCount
);
654 procedure TIdTCPConnection
.ResetConnection
;
658 FClosedGracefully
:= False;
661 function TIdTCPConnection
.SendCmd(const AOut
: string; const AResponse
: array of
668 Result
:= GetResponse(AResponse
);
671 {procedure TIdTCPConnection.Notification(AComponent: TComponent; Operation:
675 if (Operation = opRemove) then
677 if (AComponent = FIntercept) then
684 procedure TIdTCPConnection
.SetIntercept(AValue
: PIdConnectionIntercept
{TIdConnectionIntercept});
686 FIntercept
:= AValue
;
687 if FIntercept
= nil then
689 FInterceptEnabled
:= false;
693 if assigned(FIntercept
) then
695 // FIntercept.FreeNotification(self);
700 procedure TIdTCPConnection
.SetInterceptEnabled(AValue
: Boolean);
702 { if (Intercept = nil) and (not (csLoading in ComponentState)) and AValue then
704 raise EIdInterceptPropIsNil.Create(RSInterceptPropIsNil);
706 FInterceptEnabled
:= AValue
;
709 procedure TIdTCPConnection
.SetRecvBufferSize(const Value
: Integer);
711 FRecvBuffer
.Size
:= Value
;
714 procedure TIdTCPConnection
.Write(AOut
: string);
716 if Length(AOut
) > 0 then
718 WriteBuffer(AOut
[1], length(AOut
));
722 procedure TIdTCPConnection
.WriteBuffer(var{const} ABuffer
; AByteCount
: Integer;
723 const AWriteNow
: boolean = false);
725 nPos
, nByteCount
: Integer;
727 procedure DefaultSend
;
729 nByteCount
:= Binding
.Send(PChar(@ABuffer
)[nPos
- 1], AByteCount
- nPos
+ 1,
731 // TIdAntiFreezeBase.DoProcess(False);
735 if (AByteCount
> 0) and (@ABuffer
<> nil) then
737 CheckForDisconnect(True, True);
739 if (FWriteBuffer
= nil) or AWriteNow
then
743 if InterceptEnabled
then
745 if Intercept
.SendHandling
then
747 nByteCount
:= Intercept
.Send(PChar(@ABuffer
)[nPos
- 1], AByteCount
-
759 FClosedGracefully
:= nByteCount
= 0;
761 if GStack
.CheckForSocketError(nByteCount
, [ID_WSAESHUTDOWN
]) then
764 GStack
.RaiseSocketError(ID_WSAESHUTDOWN
);
766 DoWork(wmWrite
, nByteCount
);
767 if InterceptEnabled
then
769 Intercept
.DataSent(PChar(@ABuffer
)[nPos
- 1], AByteCount
- nPos
+ 1);
771 nPos
:= nPos
+ nByteCount
772 until nPos
> AByteCount
;
776 FWriteBuffer
.Write
{Buffer}(ABuffer
, AByteCount
);
777 if (FWriteBuffer
.Size
>= FWriteBufferThreshhold
) and
778 (FWriteBufferThreshhold
> 0) then
780 FlushWriteBuffer(FWriteBufferThreshhold
);
786 function TIdTCPConnection
.WriteFile(AFile
: string; const AEnableTransferFile
:
790 LFileStream
: PStream
;//TFileStream;
792 if assigned(GServeFileProc
) and (InterceptEnabled
= false) and
793 AEnableTransferFile
then
795 result
:= GServeFileProc(Binding
.Handle
, AFile
);
799 LFileStream
:= NewFileStream(AFile
, fmOpenRead
or fmShareDenyNone
{???} or ofOpenAlways
{???});//TFileStream.Create(AFile, fmOpenRead or fmShareDenyNone);
801 WriteStream(LFileStream
);
802 result
:= LFileStream
.Size
;
803 finally LFileStream
.free
;
808 procedure TIdTCPConnection
.WriteHeader(axHeader
: PStrList
);
812 for i
:= 0 to axHeader
.Count
- 1 do
814 WriteLn(StringReplace(axHeader
.Items
[i
], '=', ': ', []));
819 procedure TIdTCPConnection
.WriteInteger(AValue
: Integer; const AConvert
: boolean
824 AValue
:= Integer(GStack
.WSHToNl(LongWord(AValue
)));
826 WriteBuffer(AValue
, SizeOf(AValue
));
829 procedure TIdTCPConnection
.WriteLn(const AOut
: string = '');
834 procedure TIdTCPConnection
.WriteStream(AStream
: PStream
{TStream}; const AAll
: boolean =
836 const AWriteByteCount
: Boolean = false);
839 LBuffer
: PStream
;//TMemoryStream;
843 AStream
.Position
:= 0;
845 LSize
:= AStream
.Size
- AStream
.Position
;
846 if AWriteByteCount
then
850 BeginWork(wmWrite
, LSize
);
852 LBuffer
:= NewMemoryStream
;//TMemoryStream.Create;
854 LBuffer
.Size
:=FSendBufferSize
;//SetSize(FSendBufferSize);
857 LSize
:= Min(AStream
.Size
- AStream
.Position
, FSendBufferSize
);
862 LSize
:= AStream
.Read(LBuffer
.Memory
^, LSize
);
865 // raise EIdNoDataToRead.Create(RSIdNoDataToRead);
867 WriteBuffer(LBuffer
.Memory
^, LSize
);
869 finally FreeAndNil(LBuffer
);
871 finally EndWork(wmWrite
);
875 procedure TIdTCPConnection
.WriteStrings(AValue
: PStrList
);
879 for i
:= 0 to AValue
.Count
- 1 do
881 WriteLn(AValue
.{Strings}Items
[i
]);
885 function TIdTCPConnection
.SendCmd(const AOut
: string; const AResponse
:
888 if AResponse
= -1 then
890 result
:= SendCmd(AOut
, []);
894 result
:= SendCmd(AOut
, [AResponse
]);
898 procedure TIdTCPConnection
.DisconnectSocket
;
900 if Binding
.HandleAllocated
then
902 DoStatus(hsDisconnecting
, [Binding
.PeerIP
]);
904 FClosedGracefully
:= True;
905 DoStatus(hsDisconnected
, [Binding
.PeerIP
]);
908 if InterceptEnabled
then
910 Intercept
.Disconnect
;
914 procedure TIdTCPConnection
.OpenWriteBuffer(const AThreshhold
: Integer = -1);
916 FWriteBuffer
:= NewIdBuffer
;//TIdBuffer.Create;
917 FWriteBufferThreshhold
:= AThreshhold
;
920 procedure TIdTCPConnection
.CloseWriteBuffer
;
923 FreeAndNil(FWriteBuffer
);
926 procedure TIdTCPConnection
.FlushWriteBuffer(const AByteCount
: Integer = -1);
928 if FWriteBuffer
.Size
> 0 then
930 if (AByteCount
= -1) or (FWriteBuffer
.Size
< AByteCount
) then
932 WriteBuffer(PChar(FWriteBuffer
.Memory
)[0], FWriteBuffer
.Size
, True);
937 WriteBuffer(PChar(FWriteBuffer
.Memory
)[0], AByteCount
, True);
938 FWriteBuffer
.RemoveXBytes(AByteCount
);
943 procedure TIdTCPConnection
.ClearWriteBuffer
;
948 function TIdTCPConnection
.InputLn(const AMask
: string = ''): string;
956 if s
= BACKSPACE
then
958 if length(result
) > 0 then
960 SetLength(result
, Length(result
) - 1);
973 result
:= result
+ s
;
974 if Length(AMask
) = 0 then
986 function TIdTCPConnection
.ReadString(const ABytes
: integer): string;
988 SetLength(result
, ABytes
);
991 ReadBuffer(Result
[1], Length(Result
));
995 procedure TIdTCPConnection
.CancelWriteBuffer
;
1001 function TIdTCPConnection
.ReadSmallInt(const AConvert
: boolean = true):
1004 ReadBuffer(Result
, SizeOf(Result
));
1007 Result
:= SmallInt(GStack
.WSNToHs(Word(Result
)));
1011 procedure TIdTCPConnection
.WriteSmallInt(AValue
: SmallInt
; const AConvert
:
1016 AValue
:= SmallInt(GStack
.WSHToNs(Word(AValue
)));
1018 WriteBuffer(AValue
, SizeOf(AValue
));
1021 procedure TIdTCPConnection
.CheckForGracefulDisconnect(
1022 const ARaiseExceptionIfDisconnected
: boolean);
1024 ReadFromStack(ARaiseExceptionIfDisconnected
, 1);
1027 procedure TIdBuffer
.Clear
;
1033 procedure TIdBuffer
.RemoveXBytes(const AByteCount
: integer);
1035 if AByteCount
> Size
then
1037 // raise EIdNotEnoughDataInBuffer.Create(RSNotEnoughDataInBuffer);
1039 if AByteCount
= Size
then
1045 Move(PChar(Memory
)[AByteCount
], PChar(Memory
)[0], Size
- AByteCount
);
1046 SetSize(Size
- AByteCount
);
1050 function TIdTCPConnection
.WaitFor(const AString
: string): string;
1053 while Pos(AString
, result
) = 0 do
1055 Result
:= Result
+ CurrentReadBuffer
;
1060 function TIdTCPConnection
.ReadCardinal(const AConvert
: boolean): Cardinal;
1062 ReadBuffer(Result
, SizeOf(Result
));
1065 Result
:= GStack
.WSNToHL(Result
);
1069 procedure TIdTCPConnection
.WriteCardinal(AValue
: Cardinal; const AConvert
:
1074 AValue
:= GStack
.WSHToNl(AValue
);
1076 WriteBuffer(AValue
, SizeOf(AValue
));
1079 function TIdTCPConnection
.CheckResponse(const AResponse
: SmallInt
;
1080 const AAllowedResponses
: array of SmallInt
): SmallInt
;
1083 LResponseFound
: boolean;
1085 if High(AAllowedResponses
) > -1 then
1087 LResponseFound
:= False;
1088 for i
:= Low(AAllowedResponses
) to High(AAllowedResponses
) do
1090 if AResponse
= AAllowedResponses
[i
] then
1092 LResponseFound
:= True;
1096 if not LResponseFound
then
1098 RaiseExceptionForCmdResult
;
1101 Result
:= AResponse
;