-- lwa_connect.adb -- -- This simple test program does the equivalent of a raw telnet. -- It connects to the specified host (first arg) and port (second arg), -- sends whatever you type on STDIN until EOF (control-d), and -- reads and outputs on STDOUT whatever gets sent back on the connection. -- -- Created in 1997 by Roy T. Fielding and Kari Nies -- with Ada.Command_Line; with Interfaces.C; with Onions.Buckets; with Onions.OS; with Onions.Instreams.File; use Onions.Instreams; use Onions.Instreams.File; with Onions.Outstreams.File; use Onions.Outstreams; use Onions.Outstreams.File; with Onions.Connections; with Onions.Sockets; with Onions.Naming; procedure Lwa_Connect is Spin : Input_Pipe; Spout : Output_Pipe; Sperr : Output_Pipe; Incoming : Input_Pipe; Outgoing : Output_Pipe; Blist : Onions.Buckets.Bucket_List; Host_Address : Onions.Naming.Address; Host_Port : Interfaces.C.unsigned_short; Location : Onions.Sockets.Host_Location; Shutdown : Boolean := False; Default_Port : constant Interfaces.C.unsigned_short := 80; begin Sperr := Open (new File_Output_Stream, Stderr); if Ada.Command_Line.Argument_Count < 1 or Ada.Command_Line.Argument_Count > 2 then Write (Sperr, "Usage: lwa_connect hostname [ port ]" & Onions.OS.New_Line); Close (Sperr); return; end if; if Ada.Command_Line.Argument_Count = 2 then Host_Port := Interfaces.C.unsigned_short (Integer'Value (Ada.Command_Line.Argument (2))); else Host_Port := Default_Port; end if; declare Host_Info : Onions.Naming.Host_Entry := Onions.Naming.Info_Of (Ada.Command_Line.Argument (1)); begin Host_Address := Host_Info.Addresses (1); end; Location := (Host_Address, Host_Port); Spout := Open (new File_Output_Stream); Spin := Open (new File_Input_Stream); Set_Max_Buffer_Blocksize (Spout, 0); -- make output stream unbuffered Write (Spout, "Connecting to " & Onions.Sockets.Image (Location) & " ... "); Onions.Connections.Connect (Location, Incoming, Outgoing); Set_Max_Buffer_Blocksize (Outgoing, 0); -- make output stream unbuffered Write (Spout, "Connected" & Onions.OS.New_Line); -- Place a 300 msec timeout on the input from stdin and -- a 700 msec timeout on the input from the socket -- so that we can shutdown both tasks when either stream closes. -- Set_Timeout (Spin, 300); Set_Timeout (Incoming, 700); -- elaborate reader tasks declare task Read_Outgoing_Task is entry Start; end Read_Outgoing_Task; task Read_Incoming_Task is entry Start; end Read_Incoming_Task; task body Read_Outgoing_Task is begin accept Start; while not Shutdown loop begin Read (Spin, Blist); Write (Outgoing, Blist); exception when Onions.Instreams.End_Error => exit; when Onions.Instreams.Timeout_Exceeded => null; when others => Shutdown := True; raise; end; end loop; Close (Outgoing); end Read_Outgoing_Task; task body Read_Incoming_Task is begin accept Start; while not Shutdown loop begin Read (Incoming, Blist); Write (Spout, Blist); exception when Onions.Instreams.End_Error => Flush (Spout); Write (Sperr, "Disconnected by host" & Onions.OS.New_Line); Shutdown := True; when Onions.Instreams.Timeout_Exceeded => null; when others => Shutdown := True; raise; end; end loop; Close (Incoming); end Read_Incoming_Task; begin Read_Outgoing_Task.Start; Read_Incoming_Task.Start; end; -- waits until after both tasks have terminated Close (Spin); Close (Spout); Close (Sperr); end Lwa_Connect;