Implement stream-based reading/writing to get a more accurate slowdown

After reading N bytes from the input socket (destination host) we delay an
interval calculated to be around 56k modem speeds, then write that data to the
output socket (proxy client)
This commit is contained in:
R. Tyler Croy 2011-08-27 22:54:34 -07:00
parent a721b81665
commit 3d5bb09bb2
4 changed files with 175 additions and 5 deletions

View File

@ -3,8 +3,13 @@ private with Ada.Streams,
AWS.Client,
AWS.Headers,
AWS.Messages,
AWS.Resources,
AWS.Resources.Streams,
AWS.Response,
AWS.Status;
AWS.Status,
AWS.Translator;
with Delayed_Stream;
package body Callbacks is
use Ada.Text_IO;
@ -58,10 +63,16 @@ package body Callbacks is
-- Everything else we can slowly proxy
when others =>
declare
Buf : constant String := AWS.Response.Message_Body (Result);
Response_Stream : AWS.Resources.Streams.Stream_Access := new Delayed_Stream.Delayed;
begin
return AWS.Response.Build (Content_Type => AWS.Response.Content_Type (Result),
Message_Body => Buf,
Delayed_Stream.Create (Resource => Response_Stream.all,
Response => Result,
Size => 0,
Undefined_Size => True);
return AWS.Response.Stream (Content_Type => AWS.Response.Content_Type (Result),
Handle => Response_Stream,
Status_Code => Response_Code);
end;
end case;

109
src/delayed_stream.adb Normal file
View File

@ -0,0 +1,109 @@
private with Ada.Text_IO;
package body Delayed_Stream is
-----------
-- Close --
-----------
procedure Close (File : in out Delayed) is
begin
null;
end Close;
------------
-- Create --
------------
procedure Create
(Resource : in out AWS.Resources.Streams.Stream_Type'Class;
Response : in out AWS.Response.Data;
Size : Stream_Element_Offset;
Undefined_Size : Boolean) is
begin
Delayed (Resource).Undefined_Size := Undefined_Size;
Delayed (Resource).Size := Size;
Delayed (Resource).Offset := 0;
Delayed (Resource).Response := Response;
AWS.Response.Message_Body (Response, Delayed(Resource).Handle);
end Create;
-----------------
-- End_Of_File --
-----------------
function End_Of_File
(Resource : Delayed) return Boolean is
begin
return Resource.Offset >= Resource.Size;
end End_Of_File;
----------
-- Read --
----------
procedure Read
(Resource : in out Delayed;
Buffer : out Stream_Element_Array;
Last : out Stream_Element_Offset)
is
use Ada.Text_IO;
Buffer_Length : constant Stream_Element_Offset := Buffer'Last;
Delay_Interval : constant Float := (Float (Buffer_Length) / 7168.0);
Data_Stream : Ada.Streams.Stream_Element_Array (1 .. Buffer_Length);
Data_Last : Ada.Streams.Stream_Element_Offset;
begin
Last := Buffer'First - 1;
AWS.Resources.Read (Resource.Handle, Data_Stream, Data_Last);
-- If our input stream is empty, might as well bail now, nothing to
-- write to the output stream
if Data_Last < 0 then
return;
end if;
delay Duration (Delay_Interval);
for I in 1 .. Data_Last loop
Buffer (I) := Data_Stream (I);
Last := I;
end loop;
end Read;
-----------
-- Reset --
-----------
procedure Reset (File : in out Delayed) is
begin
null;
end Reset;
---------------
-- Set_Index --
---------------
procedure Set_Index
(File : in out Delayed;
Position : Stream_Element_Offset) is
begin
null;
end Set_Index;
----------
-- Size --
----------
function Size (File : Delayed) return Stream_Element_Offset is
begin
if File.Undefined_Size then
return AWS.Resources.Undefined_Length;
else
return File.Size;
end if;
end Size;
end Delayed_Stream;

50
src/delayed_stream.ads Normal file
View File

@ -0,0 +1,50 @@
--
--
--
with Ada.Streams,
AWS.Response,
AWS.Resources,
AWS.Resources.Streams;
package Delayed_Stream is
use Ada.Streams,
AWS.Resources;
type Delayed is new Streams.Stream_Type with private;
function End_Of_File (Resource : Delayed) return Boolean;
procedure Read
(Resource : in out Delayed;
Buffer : out Stream_Element_Array;
Last : out Stream_Element_Offset);
function Size (File : Delayed) return Stream_Element_Offset;
procedure Close (File : in out Delayed);
procedure Reset (File : in out Delayed);
procedure Set_Index
(File : in out Delayed;
Position : Stream_Element_Offset);
procedure Create
(Resource : in out AWS.Resources.Streams.Stream_Type'Class;
Response : in out AWS.Response.Data;
Size : Stream_Element_Offset;
Undefined_Size : Boolean);
private
type Delayed is new Streams.Stream_Type with record
Offset : Stream_Element_Offset;
Size : Stream_Element_Offset;
Undefined_Size : Boolean;
Response : AWS.Response.Data;
Handle : AWS.Resources.File_Type;
end record;
end Delayed_Stream;

View File

@ -20,7 +20,7 @@ begin
AWS.Server.Start (Web_Server => Server,
Name => "Dispersion Proxy",
Max_Connection => 5,
Max_Connection => 2,
Port => 8980,
Callback => Callbacks.Simple'Access);