-- TCPMUX - This is a trivial, incomplete, and uncompilable implementation of IETF RFC 1078, TCPMUX. -- Copyright (C) 2024 Prince Trippy . -- This program is free software: you can redistribute it and/or modify it under the terms of the -- GNU Affero General Public License version 3 as published by the Free Software Foundation. -- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without -- even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- See the GNU Affero General Public License for more details. -- You should have received a copy of the GNU Affero General Public License along with this program. -- If not, see . -- This program would require only Ada 1995 support if it could be compiled, but this is irrelevant. with Ada.Command_Line, Ada.Strings.Fixed, Ada.Strings.Maps.Constants, Ada.Characters.Latin_1; with Less_Trivial_Trie, Tedious_Control_Package; procedure TCPMUX is package TCP renames Tedious_Control_Package; package TCP.House renames Tedious_Control_Package.House; package TCP.Guest renames Tedious_Control_Package.Guest; type Node; type Link is access Node; type Service(Name : String) is record Spot : TCP.Port; end record; type Node(Here : Service) is record There : Link; end record; Longest_Service_Name : constant := 64; Line_End : constant String := Ada.Characters.Latin_1.CR & Ada.Characters.Latin_1.LF; package Trie is new Less_Trivial_Trie(Index_Type => Positive, Domain_Type => Character, Input_Type => String, Stored_Type => Link); Services : Trie.Trie; Outside : TCP.House.System_Resource(Where => 1); First : aliased Node := (Here => (Name => "HELP", Spot => 1), There => null); Final : Link := access First; begin Trie.Give(Path => First.Here.Name, Tree => Services, What => First'Access); declare I : Integer := 0; begin while I < Ada.Command_Line.Argument_Count loop declare S : String := Ada.Strings.Fixed.Translate(Source => Ada.Command_Line.Argument(I), Mapping => Ada.Strings.Maps.Constants.Upper_Case_Map); P : TCP.Port := TCP.Port'Value(Ada.Command_Line.Argument(I + 1)); L : Link := new Node'(Here => (Name => S, Port => P), There => null); begin if S'Length > Longest_Service_Name then return; end if; Trie.Give(Path => S & Line_End, Tree => Services, What => L); Final.all.There := L; Final := L; end; I := I + 2; end loop; end; loop declare Connection : TCP.Guest.System_Resource; Service_ID : String(1 .. Longest_Service_Name); Given_Size : Integer; ID_Has_Use : Boolean; Given_Link : Link; begin TCP.House.Wait(Connection); TCP.Guest.Pull(By => Connection, Data => Service_ID, Length => Given_Size); Ada.Strings.Fixed.Translate(Source => Service_ID(1 .. Given_Size), Mapping => Ada.Strings.Maps.Constants.Upper_Case_Map); Trie.Find(Path => Service_ID(1 .. Given_Size), Tree => Services, Seen => ID_Has_Use, Unto => Given_Link); if not ID_Has_Use then TCP.Guest.Push(By => Connection, Data => "-Service not found." & Line_End); else if Given_Link.all.Here.Name = "HELP" then declare L : Link := First.There; begin TCP.Guest.Push(By => Connection, Data => "+TCPMUX HELP:" & Line_End); while L /= null loop TCP.Guest.Push(By => Connection, Data => L.all.Here.Name & Line_End); L := L.all.There; end loop; end; else declare Internal_Connection : TCP.Guest.System_Resource; begin TCP.Guest.Call(By => Connection, House => (127, 0, 0, 1), At_Port => Given_Link.all.Here.Spot); TCP.Guest.Push(By => Connection, Data => "+Service follows:" & Line_End); -- The following is that missing primitive, which prevents me from finishing this. TCP.Fuse(House => Internal_Connection, Guest => Connection); exception when others => TCP.Guest.Push(By => Connection, Data => "-Service uncooperative." & Line_End); end; end if; end if; exception when others => null; end; end loop; exception when others => null; end TCPMUX; .