IdSocketStream.pas 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.0 27-03-05 10:04:24 MterWoord
  18. Second import, first time the filenames weren't prefixed with Id
  19. Rev 1.0 27-03-05 09:08:58 MterWoord
  20. Created
  21. }
  22. unit IdSocketStream;
  23. interface
  24. uses
  25. System.IO, System.Net.Sockets, IdStack, System.Collections, IdGlobal;
  26. type
  27. TIdSocketStream = class(System.IO.Stream)
  28. private
  29. FInternalSocket: Socket;
  30. public
  31. function get_CanRead: Boolean; override;
  32. function get_CanSeek: Boolean; override;
  33. function get_CanWrite: Boolean; override;
  34. function get_Length: Int64; override;
  35. function get_Position: Int64; override;
  36. procedure set_Position(Value: Int64); override;
  37. { Private Declarations }
  38. public
  39. constructor Create(const AInternalSocket: Socket); reintroduce;
  40. destructor Destroy; override;
  41. procedure Close; override;
  42. function Read(ABuffer: array of byte; AOffset: Integer; ACount: Integer) : Integer; override;
  43. function ReadByte : Integer; override;
  44. function Seek(AOffset: Int64; AOrigin: SeekOrigin) : Int64; override;
  45. procedure SetLength(ALength: Int64); override;
  46. procedure Write(ABuffer: array of byte; AOffset: integer; ACount: Integer); override;
  47. procedure WriteByte(AInput: byte); override;
  48. procedure Flush; override;
  49. property CanRead: Boolean read get_CanRead;
  50. property CanWrite: Boolean read get_CanWrite;
  51. property CanSeek: Boolean read get_CanSeek;
  52. property Length: Int64 read get_Length;
  53. property Position: Int64 read get_Position write set_Position;
  54. property InternalSocket: Socket read FInternalSocket;
  55. end;
  56. implementation
  57. procedure TIdSocketStream.Close;
  58. begin
  59. inherited;
  60. end;
  61. constructor TIdSocketStream.Create(const AInternalSocket: Socket);
  62. begin
  63. inherited Create;
  64. FInternalSocket := AInternalSocket;
  65. end;
  66. function TIdSocketStream.get_Length: Int64;
  67. begin
  68. Result := 0;
  69. if FInternalSocket.Poll(1, SelectMode.SelectRead) then
  70. Result := FInternalSocket.Available;
  71. end;
  72. function TIdSocketStream.get_CanSeek: Boolean;
  73. begin
  74. Result := False;
  75. end;
  76. function TIdSocketStream.get_CanRead: Boolean;
  77. begin
  78. Result := True;
  79. end;
  80. function TIdSocketStream.get_CanWrite: Boolean;
  81. begin
  82. Result := True;
  83. end;
  84. function TIdSocketStream.get_Position: Int64;
  85. begin
  86. Result := 0;
  87. end;
  88. procedure TIdSocketStream.set_Position(Value: Int64);
  89. begin
  90. raise NotSupportedException.Create;
  91. end;
  92. procedure TIdSocketStream.Write(ABuffer: array of byte; AOffset,
  93. ACount: Integer);
  94. begin
  95. try
  96. GStack.Send(FInternalSocket, ABuffer, AOffset, ACount);
  97. except
  98. on E: Exception do
  99. begin
  100. Console.WriteLine('TIdSocketStream.Write: ' + E.ToString);
  101. raise;
  102. end;
  103. end;
  104. end;
  105. function TIdSocketStream.ReadByte: Integer;
  106. var
  107. TempBuff: array[0..1] of byte;
  108. begin
  109. Result := -1;
  110. if Length > 0 then
  111. begin
  112. if Read(TempBuff, 0, 1) <> 0 then
  113. Result := TempBuff[0];
  114. end;
  115. end;
  116. procedure TIdSocketStream.SetLength(ALength: Int64);
  117. begin
  118. raise NotSupportedException.Create;
  119. end;
  120. procedure TIdSocketStream.WriteByte(AInput: byte);
  121. begin
  122. Write([AInput], 0, 1);
  123. end;
  124. procedure TIdSocketStream.Flush;
  125. begin
  126. end;
  127. function TIdSocketStream.Seek(AOffset: Int64; AOrigin: SeekOrigin): Int64;
  128. begin
  129. raise NotSupportedException.Create;
  130. end;
  131. function TIdSocketStream.Read(ABuffer: array of byte; AOffset,
  132. ACount: Integer): Integer;
  133. var
  134. I: Integer;
  135. TempArray: ArrayList;
  136. TempBytesToRead: Integer;
  137. TempBuff: TIdBytes;
  138. BytesRead: Integer;
  139. begin
  140. try
  141. i := 0;
  142. TempArray := ArrayList.Create;
  143. while i < ACount do
  144. begin
  145. TempBytesToRead := Math.Min(50, ACount - i);
  146. TempBuff := ToBytes(System.&String.Create(#0, TempBytesToRead));
  147. if CanRead then
  148. begin
  149. BytesRead := GStack.Receive(FInternalSocket, TempBuff);
  150. if BytesRead <> 0 then
  151. begin
  152. &Array.Copy(TempBuff, 0, ABuffer, i + AOffset, BytesRead);
  153. Inc(i, BytesRead);
  154. if BytesRead <> 50 then
  155. Break;
  156. end
  157. else
  158. Break;
  159. end
  160. else
  161. Break;
  162. end;
  163. Result := i;
  164. except
  165. on E: Exception do
  166. begin
  167. Console.WriteLine('Exception "{0}". I = {1}, BytesRead = {2}, AOffset = {3}, ACount = {4}, TempBytesToRead = {5}',
  168. [E.GetType().FullName + ': ' + E.Message, I, BytesRead, AOffset, ACount, TempBytesToRead]);
  169. raise;
  170. end;
  171. end;
  172. end;
  173. destructor TIdSocketStream.Destroy;
  174. begin
  175. FInternalSocket := nil;
  176. inherited;
  177. end;
  178. end.