DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦c167426b4⟧ Ada Source

    Length: 23552 (0x5c00)
    Types: Ada Source
    Notes: 03_class, FILE, R1k_Segment, e3_tag, package body Transport, seg_052ab5

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦this⟧ 

E3 Source Code



with Byte_Defs;
with Socket_System_Interface;
with System;
with System_Interface;
with Transport_Defs;
with Unchecked_Conversion;
with Unix_Base_Types;
with Text_Io;

use Text_Io;
package body Transport is

    Prototype_Error : exception;


    Unix_Error : constant Unix_Base_Types.Int := -1;


    type Process_Kind is (Nul, Server, Client);


    type Socket_Status_Kind is (Open, Connected, Not_Connected, Closed);
    -- For Servers:
    --   Open implies that the passive socket is Open, Bound and Listening.
    --   Connected means that the _accept call has completed and a
    --      connection with a remote (active) socket has been established.
    -- For Clients:
    --   Open implies that the local _socket call has completed successfully.
    --   Connected implies that the _connect call has completed successfully
    --      and that an active connection to the specified remote socket
    --      has been established.
    -- For both Servers and Clients:
    --   Not_Connected implies that the Connection is still open after a
    --      transmit or receive failure.  The socket should be Closed and then
    --      reopened.  You CANNOT simply reconnect a socket that is
    --      Not_Connected.
    --


    -- Private type completion
    type Connection_Info is
        record
            Kind : Process_Kind := Nul;
            Socket_Status : Socket_Status_Kind := Closed;
            Local_Socket_Descriptor : Unix_Base_Types.Int := Unix_Error;
            Tcp_Socket_Descriptor : Unix_Base_Types.Int := Unix_Error;
            Local_Sockaddr_In : Socket_System_Interface.Sockaddr_In;
            Remote_Sockaddr_In : Socket_System_Interface.Sockaddr_In;
            Next : Connection_Id := null;
        end record;


    Free_List : Connection_Id := null;


    function ">" (L, R : Byte_Defs.Byte) return Boolean renames Byte_Defs.">";

    function "-" (L, R : Byte_Defs.Byte) return Byte_Defs.Byte
        renames Byte_Defs."-";


    function "=" (Left : Transport_Defs.Status_Code;
                  Right : Transport_Defs.Status_Code)  
                 return Boolean renames Transport_Defs."=";


    function "=" (Left : Transport_Defs.Socket_Id;
                  Right : Transport_Defs.Socket_Id)  
                 return Boolean renames Transport_Defs."=";


    function To_Sockaddr_In is  
       new Unchecked_Conversion (Source => Socket_System_Interface.Sockaddr,
                                 Target => Socket_System_Interface.Sockaddr_In);


    function To_Sockaddr is  
       new Unchecked_Conversion (Source => Socket_System_Interface.Sockaddr_In,
                                 Target => Socket_System_Interface.Sockaddr);


    function To_Sockaddr_In_Ptr is  
       new Unchecked_Conversion
              (Source => System.Address,
               Target => Socket_System_Interface.Sockaddr_In_Ptr);


    function To_Sockaddr_Ptr is  
       new Unchecked_Conversion
              (Source => System.Address,
               Target => Socket_System_Interface.Sockaddr_Ptr);


    function To_Int_Ptr is  
       new Unchecked_Conversion (Source => System.Address,
                                 Target => Socket_System_Interface.Int_Ptr);


    function Get return Connection_Id is separate;

    procedure Free (Connection : Connection_Id) is separate;

    procedure Start_System_Call is separate;

    function Finish_System_Call return Unix_Base_Types.Int is separate;

    function Convert_Errno (Errno : Unix_Base_Types.Int)
                           return Transport_Defs.Status_Code is separate;


    function Byte_String_To_Integer (Bs : Byte_Defs.Byte_String)
                                    return Unix_Base_Types.Int is separate;


    procedure Open_Server (Connection : out Transport.Connection_Id;
                           Status : out Transport_Defs.Status_Code;
                           Network : in Transport_Defs.Network_Name;
                           Local_Socket : in Transport_Defs.
                                                Socket_Id) is separate;


    procedure Open_Client (Connection : out Transport.Connection_Id;
                           Status : out Transport_Defs.Status_Code;
                           Network : in Transport_Defs.
                                           Network_Name) is separate;


    --
    -- Spec level routines
    --
    procedure Open (Connection : out Transport.Connection_Id;
                    Status : out Transport_Defs.Status_Code;
                    Network : Transport_Defs.Network_Name;
                    Local_Socket : Transport_Defs.Socket_Id :=
                       Transport_Defs.Null_Socket_Id) is

        -- IT IS ASSUMED THAT Server TASK WILL BE STARTED ON A KNOWN LOCAL
        -- SOCKET.  Client TASKS WON'T CARE WHAT LOCAL_SOCKET THEY START ON
        -- AND WILL CALL OPEN WITH Local_Socket =
        -- Transport_Defs.Null_Socket_Id.
        --
        Is_Server : constant Boolean :=
           Local_Socket /= Transport_Defs.Null_Socket_Id;

    begin
        if Is_Server then
            Open_Server (Connection => Connection,
                         Status => Status,
                         Network => Network,
                         Local_Socket => Local_Socket);
        else
            Open_Client (Connection => Connection,
                         Status => Status,
                         Network => Network);
        end if;
    end Open;


    procedure Close (Connection : Transport.Connection_Id) is separate;
    procedure Connect (Connection : Transport.Connection_Id;
                       Status : out Transport_Defs.Status_Code;
                       Remote_Host : Transport_Defs.Host_Id;
                       Remote_Socket : Transport_Defs.Socket_Id;
                       Max_Wait : Duration := Duration'Last) is
        --
        Laddr_In : Socket_System_Interface.Sockaddr_In :=
           (Sin_Family => Socket_System_Interface.Af_Inet,
            Sin_Port => Unix_Base_Types.Ushort
                           (Byte_String_To_Integer
                               (Byte_Defs.Byte_String  
                                   (Transport_Defs.Normalize (Remote_Socket)))),  
            Sin_Addr => Unix_Base_Types.U_Long
                           (Byte_String_To_Integer
                               (Byte_Defs.Byte_String
                                   (Transport_Defs.Normalize (Remote_Host)))),
            Sin_Zero => (others => Ascii.Nul));

        Laddrlen : Unix_Base_Types.Int := Laddr_In'Size / System.Storage_Unit;

        Laddr_In_Ptr : Socket_System_Interface.Sockaddr_In_Ptr :=
           To_Sockaddr_In_Ptr (Laddr_In'Address);


        Temp_Connection : Connection_Id := Connection;
        System_Call_Result : Unix_Base_Types.Int;
        Errno : Unix_Base_Types.Int;


    begin
        if Temp_Connection = Null_Connection_Id or else
           Temp_Connection.Socket_Status /= Open then
            Status := Transport_Defs.Not_Open;
            return;
        elsif Temp_Connection.Socket_Status = Not_Connected then
            Status := Transport_Defs.Not_Connected;
            return;
        end if;

        Status := Transport_Defs.Ok;

        Start_System_Call;

        System_Call_Result := Socket_System_Interface.Connect
                                 (S => Temp_Connection.Local_Socket_Descriptor,
                                  Addr => Laddr_In_Ptr,
                                  Addrlen => Laddrlen);

        Errno := Finish_System_Call;

        if (System_Call_Result < 0) then
            Status := Convert_Errno (Errno => Errno);
            return;
        end if;

        Temp_Connection.Socket_Status := Connected;
        Temp_Connection.Local_Sockaddr_In := Laddr_In;


    end Connect;


    --
    -- Form a passive connection.  This connection must be formed by a
    -- Server.  It waits for a remote connection from an active Client.
    --
    procedure Connect (Connection : Transport.Connection_Id;
                       Status : out Transport_Defs.Status_Code;
                       Max_Wait : Duration := Duration'Last) is

        Temp_Connection : Connection_Id := Connection;

        Laddr : Socket_System_Interface.Sockaddr;

        Laddr_Ptr : Socket_System_Interface.Sockaddr_Ptr :=
           To_Sockaddr_Ptr (Laddr'Address);

        Laddrlen : Unix_Base_Types.Int :=
           Temp_Connection.Local_Sockaddr_In'Size / System.Storage_Unit;

        Laddrlen_Ptr : Socket_System_Interface.Int_Ptr :=
           To_Int_Ptr (Laddrlen'Address);

        Tcp_Connection : Unix_Base_Types.Int;
        Errno : Unix_Base_Types.Int;

    begin

        if Temp_Connection = Null_Connection_Id or else
           Temp_Connection.Socket_Status = Closed then
            Status := Transport_Defs.Not_Open;
            return;
        elsif Temp_Connection.Socket_Status = Not_Connected then
            Status := Transport_Defs.Not_Connected;
            return;
        end if;

        Accept_Loop:
            loop
                Status := Transport_Defs.Ok;

                Start_System_Call;

                Tcp_Connection :=  
                   Socket_System_Interface.Saccept
                      (S => Temp_Connection.Local_Socket_Descriptor,
                       Addr => Laddr_Ptr,
                       Addrlen => Laddrlen_Ptr);

                Errno := Finish_System_Call;

                if (Tcp_Connection < 0) then
                    Status := Convert_Errno (Errno => Errno);
                    if Errno /= System_Interface.Error.Eintr then
                        return;  
                    end if;  
                else
                    exit Accept_Loop;
                end if;
            end loop Accept_Loop;

        Temp_Connection.Socket_Status := Connected;
        Temp_Connection.Tcp_Socket_Descriptor := Tcp_Connection;
        Temp_Connection.Remote_Sockaddr_In := To_Sockaddr_In (Laddr_Ptr.all);

    end Connect;



    procedure Disconnect (Connection : Transport.Connection_Id) is

        Temp_Connect : Transport.Connection_Id := Connection;
        System_Call_Result : Unix_Base_Types.Int;
        File_Descriptor : Unix_Base_Types.Int;

    begin
        if Temp_Connect = Null_Connection_Id or else
           Temp_Connect.Socket_Status /= Connected then
            return;
        end if;

        if Temp_Connect.Kind = Server then  
            File_Descriptor := Temp_Connect.Tcp_Socket_Descriptor;
        else
            File_Descriptor := Temp_Connect.Local_Socket_Descriptor;
        end if;

        if Temp_Connect.Kind = Client then
            System_Call_Result :=  
               Socket_System_Interface.Shutdown
                  (S => File_Descriptor, How => 2);
        end if;

        System_Call_Result :=  
           System_Interface.File_Io.Close (Fildes => File_Descriptor);

        if System_Call_Result < 0 then
            raise Program_Error;
        else

            if Temp_Connect.Kind = Server then  
                Temp_Connect.Tcp_Socket_Descriptor := Unix_Error;
                Temp_Connect.Socket_Status := Open;
            else
                Temp_Connect.Local_Socket_Descriptor := Unix_Error;
                Temp_Connect.Socket_Status := Closed;
            end if;

        end if;
    end Disconnect;


    function Is_Open (Connection : Transport.Connection_Id) return Boolean is
    begin
        if Connection = Null_Connection_Id then
            return False;
        end if;


        case Connection.Kind is
            when Server | Client =>
                return (Connection.Socket_Status = Open) or
                          (Connection.Socket_Status = Not_Connected);
            when others =>
                return False;
        end case;
    end Is_Open;


    function Is_Connected
                (Connection : Transport.Connection_Id) return Boolean is
    begin
        if Connection = Null_Connection_Id then
            return False;
        end if;


        case Connection.Kind is
            when Server | Client =>
                return Connection.Socket_Status = Connected;
            when others =>
                return False;
        end case;
    end Is_Connected;



    procedure Transmit (Connection : Transport.Connection_Id;
                        Status : out Transport_Defs.Status_Code;
                        Data : Byte_Defs.Byte_String;
                        Count : out Natural;
                        Max_Wait : Duration := Duration'Last;
                        More : Boolean := False) is

        File_Descriptor : Unix_Base_Types.Int;
        System_Call_Result : Unix_Base_Types.Int;
        Errno : Unix_Base_Types.Int;
        Temp_Connect : Transport.Connection_Id := Connection;
        Amount_Remaining : Natural := Data'Length;
        Index : Natural := Data'First;
        Lcount : Natural := 0;

    begin

        Count := 0;

        if Temp_Connect = Null_Connection_Id then
            Status := Transport_Defs.Not_Open;
            return;
        end if;

        if Temp_Connect.Socket_Status /= Connected then
            Status := Transport_Defs.Not_Connected;
            return;
        end if;

        Status := Transport_Defs.Ok;

        if Temp_Connect.Kind = Server then  
            File_Descriptor := Temp_Connect.Tcp_Socket_Descriptor;
        else
            File_Descriptor := Temp_Connect.Local_Socket_Descriptor;
        end if;

        Transmit_Loop:
            while Amount_Remaining > 0 loop

                Start_System_Call;

                System_Call_Result :=  
                   System_Interface.File_Io.Write
                      (Fildes => File_Descriptor,
                       Buf => Unix_Base_Types.To_Char_Ptr
                                 (Data (Index)'Address),
                       Nbyte => Amount_Remaining);

                Errno := Finish_System_Call;

                if (System_Call_Result < 0) then

                    Status := Convert_Errno (Errno => Errno);

                    if Temp_Connect.Kind = Client then
                        System_Call_Result :=  
                           Socket_System_Interface.Shutdown
                              (S => File_Descriptor, How => 2);
                    end if;

                    System_Call_Result :=  
                       System_Interface.File_Io.Close
                          (Fildes => File_Descriptor);

                    if System_Call_Result < 0 then
                        raise Program_Error;
                    else

                        if Temp_Connect.Kind = Server then  
                            Temp_Connect.Tcp_Socket_Descriptor := Unix_Error;
                            Temp_Connect.Socket_Status := Not_Connected;
                        else
                            Temp_Connect.Local_Socket_Descriptor := Unix_Error;
                            Temp_Connect.Socket_Status := Closed;
                        end if;

                    end if;

                    return;

                end if;

                Lcount := Lcount + System_Call_Result;
                Amount_Remaining := Amount_Remaining - System_Call_Result;
                Index := Index + System_Call_Result;  
                Count := Lcount;

            end loop Transmit_Loop;

    end Transmit;


    procedure Receive (Connection : Transport.Connection_Id;
                       Status : out Transport_Defs.Status_Code;
                       Data : out Byte_Defs.Byte_String;
                       Count : out Natural;
                       Max_Wait : Duration := Duration'Last) is

        File_Descriptor : Unix_Base_Types.Int;
        Length : Unix_Base_Types.Int;
        System_Call_Result : Unix_Base_Types.Int;
        Errno : Unix_Base_Types.Int := System_Interface.Error.Eintr;
        Temp_Connect : Transport.Connection_Id := Connection;

    begin

        Count := 0;

        if Temp_Connect = Null_Connection_Id then
            Status := Transport_Defs.Not_Open;
            return;
        end if;

        if Temp_Connect.Socket_Status /= Connected then
            Status := Transport_Defs.Not_Connected;
            return;
        end if;

        if Temp_Connect.Kind = Server then  
            File_Descriptor := Temp_Connect.Tcp_Socket_Descriptor;
        else
            File_Descriptor := Temp_Connect.Local_Socket_Descriptor;
        end if;

        Status := Transport_Defs.Ok;

        Start_System_Call;

        Length := System_Interface.File_Io.Read
                     (Fildes => File_Descriptor,
                      Buf => Unix_Base_Types.To_Char_Ptr (Data'Address),
                      Nbyte => Data'Length);

        Errno := Finish_System_Call;

        if (Length > 0) then

            Count := Length;

        else


            if (Length < 0) then

                Status := Convert_Errno (Errno => Errno);

            elsif (Length = 0) then

                Status := Transport_Defs.Not_Connected;

            end if;

            if Temp_Connect.Kind = Client then
                System_Call_Result :=  
                   Socket_System_Interface.Shutdown
                      (S => File_Descriptor, How => 2);
            end if;

            System_Call_Result :=  
               System_Interface.File_Io.Close (Fildes => File_Descriptor);

            if System_Call_Result < 0 then
                raise Program_Error;
            else

                if Temp_Connect.Kind = Server then  
                    Temp_Connect.Tcp_Socket_Descriptor := Unix_Error;
                    Temp_Connect.Socket_Status := Not_Connected;
                else
                    Temp_Connect.Local_Socket_Descriptor := Unix_Error;
                    Temp_Connect.Socket_Status := Closed;
                end if;

            end if;

        end if;

    end Receive;
    function Network (Connection : Transport.Connection_Id)
                     return Transport_Defs.Network_Name is
    begin
        return "TCP/IP"; --[prototype]
    end Network;


    function Local_Host (Connection : Transport.Connection_Id)
                        return Transport_Defs.Host_Id is
    begin
        raise Prototype_Error; --[prototype]
        return Transport_Defs.Null_Host_Id;
    end Local_Host;


    function Local_Socket (Connection : Transport.Connection_Id)
                          return Transport_Defs.Socket_Id is

        Sid : constant Transport_Defs.Socket_Id :=
           Transport_Defs.Socket_Id'
              (Byte_Defs.Byte
                  (Integer (Connection.Local_Sockaddr_In.Sin_Port) / 256),
               Byte_Defs.Byte
                  (Integer (Connection.Local_Sockaddr_In.Sin_Port) mod 256));
    begin

        return Sid;

    end Local_Socket;


    function Remote_Host (Connection : Transport.Connection_Id)
                         return Transport_Defs.Host_Id is
    begin
        raise Prototype_Error; --[prototype]
        return Transport_Defs.Null_Host_Id;
    end Remote_Host;


    function Remote_Socket (Connection : Transport.Connection_Id)
                           return Transport_Defs.Socket_Id is
    begin
        return
           Transport_Defs.Socket_Id'
              (Byte_Defs.Byte
                  (Integer (Connection.Remote_Sockaddr_In.Sin_Port) / 256),
               Byte_Defs.Byte
                  (Integer (Connection.Remote_Sockaddr_In.Sin_Port) mod 256));
    end Remote_Socket;
end Transport;

E3 Meta Data

    nblk1=16
    nid=b
    hdr6=2a
        [0x00] rec0=21 rec1=00 rec2=01 rec3=018
        [0x01] rec0=1a rec1=00 rec2=02 rec3=058
        [0x02] rec0=1e rec1=00 rec2=03 rec3=00a
        [0x03] rec0=1c rec1=00 rec2=04 rec3=060
        [0x04] rec0=16 rec1=00 rec2=05 rec3=082
        [0x05] rec0=1a rec1=00 rec2=06 rec3=01a
        [0x06] rec0=15 rec1=00 rec2=07 rec3=034
        [0x07] rec0=1f rec1=00 rec2=08 rec3=010
        [0x08] rec0=20 rec1=00 rec2=09 rec3=01c
        [0x09] rec0=1b rec1=00 rec2=0a rec3=030
        [0x0a] rec0=20 rec1=00 rec2=16 rec3=024
        [0x0b] rec0=21 rec1=00 rec2=0c rec3=00c
        [0x0c] rec0=1f rec1=00 rec2=0d rec3=05a
        [0x0d] rec0=21 rec1=00 rec2=0e rec3=006
        [0x0e] rec0=1a rec1=00 rec2=0f rec3=058
        [0x0f] rec0=1e rec1=00 rec2=10 rec3=058
        [0x10] rec0=1d rec1=00 rec2=11 rec3=012
        [0x11] rec0=26 rec1=00 rec2=12 rec3=012
        [0x12] rec0=1e rec1=00 rec2=13 rec3=00a
        [0x13] rec0=20 rec1=00 rec2=14 rec3=010
        [0x14] rec0=07 rec1=00 rec2=15 rec3=000
        [0x15] rec0=00 rec1=04 rec2=80 rec3=016
    tail 0x21759fe9487a14f34e032 0x42a00088462060003
Free Block Chain:
  0xb: 0000  00 00 03 fc 80 05 69 66 3b 20 20 05 00 14 20 20  ┆      if;       ┆