DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

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 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦661e833b9⟧ TextFile

    Length: 16054 (0x3eb6)
    Types: TextFile
    Names: »B«

Derivation

└─⟦bad92a95e⟧ Bits:30000535 8mm tape, Rational 1000, RPC 1_0_2
    └─ ⟦bb34fe6e2⟧ »DATA« 
        └─⟦15d8b76c6⟧ 
            └─⟦this⟧ 

TextFile

with Byte_Defs;
with Socket_System_Interface;
with System_Interface;
with Unix_Base_Types;
package body Transport is

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

    function "-" (L, R : Byte_Defs.Byte) return Byte_Defs.Byte
        renames Byte_Defs."-";
    type Connection_Info is
        record
            Connection_Establishment_Socket : Unix_Base_Types.Int := -1;
            Transmission_Socket : Unix_Base_Types.Int := -1;
            Next : Connection_Id := null;
        end record;


    Free_List : Connection_Id := null;

    function "=" (L, R : Byte_Defs.Byte_String) return Boolean
        renames Byte_Defs."=";

    function Get return Connection_Id is
        The_Connection : Connection_Id;
    begin
        if Free_List = null then
            The_Connection := new Connection_Info;
        else
            The_Connection := Free_List;
            Free_List := Free_List.Next;
        end if;
        return The_Connection;
    end Get;

    procedure Free (Connection : Connection_Id) is
    begin
        Connection.Next := Free_List;
        Free_List := Connection;
    end Free;

    procedure Start_System_Call is
    begin
        null;
    end Start_System_Call;

    function Finish_System_Call return Unix_Base_Types.Int is
        Errno : Integer := System_Interface.Error.Errno;
    begin
        return Errno;
    end Finish_System_Call;

    function Convert_Errno (Errno : Unix_Base_Types.Int)
                           return Transport_Defs.Status_Code is
    begin
        case Errno is
            when System_Interface.Error.Econnreset |
                 System_Interface.Error.Eremoterelease =>
                return Transport_Defs.Connection_Broken;
            when System_Interface.Error.Enomem =>
                return Transport_Defs.No_Free_Memory;
            when System_Interface.Error.Eacces =>
                return Transport_Defs.Access_Denied;
            when System_Interface.Error.Eprotonosupport =>
                return Transport_Defs.Protocol_Not_Supported;

            when System_Interface.Error.Eaddrinuse =>
                return Transport_Defs.Socket_In_Use;

            when System_Interface.Error.Enetunreach =>
                return Transport_Defs.Network_Unreachable;

            when System_Interface.Error.Enotconn =>
                return Transport_Defs.Not_Connected;
            when System_Interface.Error.Eshutdown =>
                return Transport_Defs.Not_Open;
            when System_Interface.Error.Etimedout =>
                return Transport_Defs.Timed_Out;
            when System_Interface.Error.Econnrefused =>
                return Transport_Defs.Connection_Refused;
            when System_Interface.Error.Ehostunreach =>
                return Transport_Defs.Host_Unreachable;
            when others =>
                return Transport_Defs.Status_Code
                          (Errno + Unix_Base_Types.Int (100));
        end case;
    end Convert_Errno;

    function Byte_String_To_Integer
                (Bs : Byte_Defs.Byte_String) return Unix_Base_Types.Int is
        Result : Unix_Base_Types.Int := 0;
        Int_Length : constant := 4;
        Normalized_Bs : Byte_Defs.Byte_String (0 .. Int_Length - 1) :=
           (others => 0);
        Negative : Boolean := False;
        Shifter : Integer := 0;
    begin
        if Bs'Length < Int_Length then
            Normalized_Bs
               ((Normalized_Bs'Last - Bs'Length) + 1 .. Normalized_Bs'Last) :=
               Bs;
        else
            Normalized_Bs := Bs ((Bs'Last - Int_Length) + 1 .. Bs'Last);
        end if;

        if Normalized_Bs (0) > Byte_Defs.Byte (2 ** 7 - 1) then
            Negative := True;
        end if;

        for I in reverse Normalized_Bs'Range loop
            if Negative then
                Normalized_Bs (I) := Byte_Defs.Byte'Last - Normalized_Bs (I);
            end if;

            Result := Result + Integer (Normalized_Bs (I)) * (2 ** Shifter);
            Shifter := Shifter + 8;
        end loop;

        if Negative then
            return -Result - 1;
        else
            return Result;
        end if;
    end Byte_String_To_Integer;

    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
        System_Call_Result : Integer;
        Lconnection : Connection_Id := Null_Connection_Id;
        Addr : 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 (Local_Socket)))),
            Sin_Addr => Socket_System_Interface.Inaddr_Any,
            Sin_Zero => (others => Ascii.Nul));
        Errno : Integer;
    begin
        Connection := Null_Connection_Id;
        Status := Transport_Defs.Ok;

        Start_System_Call;

        System_Call_Result :=
           Socket_System_Interface.Socket
              (Af => Unix_Base_Types.Int (Socket_System_Interface.Af_Inet),
               Socket_Type => Socket_System_Interface.Sock_Stream,
               Protocol => 0);

        Errno := Finish_System_Call;

        if System_Call_Result = -1 then
            Status := Convert_Errno (Errno);
            return;
        end if;

        Lconnection := Get;
        Lconnection.Connection_Establishment_Socket := System_Call_Result;

        if Byte_Defs.Byte_String (Local_Socket) /=
           Byte_Defs.Byte_String (Transport_Defs.Null_Socket_Id) then

            Start_System_Call;

            System_Call_Result :=
               Socket_System_Interface.Bind
                  (S => Unix_Base_Types.Int
                           (Lconnection.Connection_Establishment_Socket),
                   Addr => Addr,
                   Addrlen => 16);

            Errno := Finish_System_Call;

            if System_Call_Result = -1 then
                Status := Convert_Errno (Errno);
                System_Call_Result :=
                   System_Interface.File_Io.Close
                      (Fildes => Lconnection.Connection_Establishment_Socket);
                Free (Lconnection);
                return;
            end if;
        end if;

        Connection := Lconnection;
    end Open;


    procedure Close (Connection : Transport.Connection_Id) is
        Error : Unix_Base_Types.Int;
        Lconnection : Connection_Id := Connection;
    begin
        if Connection /= Null_Connection_Id then

            Error := Socket_System_Interface.Shutdown
                        (S => Connection.Transmission_Socket, How => 2);
            Error := System_Interface.File_Io.Close
                        (Connection.Transmission_Socket);

            Error := Socket_System_Interface.Shutdown
                        (S => Connection.Connection_Establishment_Socket,
                         How => 2);
            Error := System_Interface.File_Io.Close
                        (Connection.Connection_Establishment_Socket);
            Lconnection.Connection_Establishment_Socket := -1;
            Lconnection.Transmission_Socket := -1;
            Free (Lconnection);
        end if;
    end Close;


    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
        System_Call_Result : Integer;  
        Errno : Integer := System_Interface.Error.Etimedout;
        Addr : 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));

    begin
        if not Is_Open (Connection) then
            Status := Transport_Defs.Not_Open;
            return;
        end if;

        Status := Transport_Defs.Ok;

        while Errno = System_Interface.Error.Etimedout loop
            Start_System_Call;

            System_Call_Result :=
               Socket_System_Interface.Connect
                  (S => Connection.Connection_Establishment_Socket,
                   Addr => Addr,
                   Addrlen => 16);

            Errno := Finish_System_Call;
        end loop;

        if System_Call_Result = -1 then
            Status := Convert_Errno (Errno);
        else
            Connection.Transmission_Socket :=
               Connection.Connection_Establishment_Socket;
        end if;
    end Connect;


    procedure Connect (Connection : Transport.Connection_Id;
                       Status : out Transport_Defs.Status_Code;
                       Max_Wait : Duration := Duration'Last) is
        System_Call_Result : Integer;
        Errno : Integer := 0;
        Addr : Socket_System_Interface.Sockaddr;
    begin

        if not Is_Open (Connection) then
            Status := Transport_Defs.Not_Open;
            return;
        end if;

        Status := Transport_Defs.Ok;

        Start_System_Call;
        System_Call_Result :=
           Socket_System_Interface.Listen
              (S => Connection.Connection_Establishment_Socket, Backlog => 5);

        Errno := Finish_System_Call;

        if System_Call_Result = -1 then

            Status := Convert_Errno (Errno);

        else
            loop

                Start_System_Call;
                System_Call_Result :=
                   Socket_System_Interface.Saccept
                      (S => Connection.Connection_Establishment_Socket,
                       Addr => Addr,
                       Addrlen => 16);
                Errno := Finish_System_Call;

                exit when Errno /= System_Interface.Error.Eintr;
            end loop;

            if System_Call_Result = -1 then

                Status := Convert_Errno (Errno);
            else
                Connection.Transmission_Socket := System_Call_Result;
            end if;

        end if;

    end Connect;


    procedure Disconnect (Connection : Transport.Connection_Id) is
        Error : Integer;
    begin
        if Connection /= Null_Connection_Id and then
           Connection.Transmission_Socket /= -1 then
            Error := Socket_System_Interface.Shutdown
                        (S => Connection.Transmission_Socket, How => 2);

            Connection.Transmission_Socket := -1;
        end if;
    end Disconnect;


    function Is_Open (Connection : Transport.Connection_Id) return Boolean is
    begin
        return Connection /= Null_Connection_Id and then
                  Connection.Connection_Establishment_Socket /= -1;
    end Is_Open;


    function Is_Connected
                (Connection : Transport.Connection_Id) return Boolean is
    begin
        return Connection /= Null_Connection_Id and then
                  Connection.Transmission_Socket /= -1;
        --should be getpeername;
    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
        System_Call_Result : Integer := 1;
        Errno : Integer := 0;
        Bytes_Sent : Integer := 0;

        function Disconnected return Boolean is
        begin
            return System_Call_Result = 0;
        end Disconnected;

        function More_Data return Boolean is
        begin
            return Bytes_Sent < Data'Length;
        end More_Data;

        function No_Error return Boolean is
        begin
            return Errno = 0 or Errno = System_Interface.Error.Eintr;
        end No_Error;
    begin  
        Count := 0;
        Status := Transport_Defs.Ok;

        if not Is_Open (Connection) then
            Status := Transport_Defs.Not_Open;
            return;
        end if;

        if not Is_Connected (Connection) then
            Status := Transport_Defs.Not_Connected;
            return;
        end if;

        while No_Error and More_Data and not Disconnected loop

            declare
                Buffer : constant Byte_Defs.Byte_String :=
                   Data (Data'First + Bytes_Sent .. Data'Last);
            begin
                Start_System_Call;

                System_Call_Result :=
                   System_Interface.File_Io.Write
                      (Fildes => Connection.Transmission_Socket,
                       Buf => Unix_Base_Types.To_Char_Ptr (Buffer'Address),
                       Nbyte => Buffer'Length);

                Errno := Finish_System_Call;
            end;

            if System_Call_Result /= -1 then
                Bytes_Sent := Bytes_Sent + System_Call_Result;
            end if;

        end loop;

        Count := Bytes_Sent;

        if System_Call_Result = -1 then
            Status := Convert_Errno (Errno);
            return;
        end if;

        if Disconnected then
            Status := Transport_Defs.Connection_Broken;
            System_Call_Result := Socket_System_Interface.Shutdown
                                     (Connection.Transmission_Socket, 2);
            System_Call_Result := System_Interface.File_Io.Close
                                     (Connection.Transmission_Socket);
            Connection.Transmission_Socket := -1;
        end if;

    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
        System_Call_Result : Integer;
        Errno : Integer;
    begin
        Count := 0;
        Status := Transport_Defs.Ok;

        if not Is_Open (Connection) then
            Status := Transport_Defs.Not_Open;
        end if;

        if not Is_Connected (Connection) then
            Status := Transport_Defs.Not_Connected;
        end if;

        loop
            Start_System_Call;
            System_Call_Result := System_Interface.File_Io.Read
                                     (Fildes => Connection.Transmission_Socket,
                                      Buf => Unix_Base_Types.To_Char_Ptr
                                                (Data (Data'First)'Address),
                                      Nbyte => Data'Length);
            Errno := Finish_System_Call;
            exit when Errno /= System_Interface.Error.Eintr;
        end loop;

        if System_Call_Result = -1 then
            Status := Convert_Errno (Errno);
            return;
        end if;

        if System_Call_Result = 0 then
            Status := Transport_Defs.Connection_Broken;
            System_Call_Result := Socket_System_Interface.Shutdown
                                     (Connection.Transmission_Socket, 2);
            System_Call_Result := System_Interface.File_Io.Close
                                     (Connection.Transmission_Socket);
            Connection.Transmission_Socket := -1;
        else
            Count := System_Call_Result;
        end if;


    end Receive;

end Transport;