------------------------------------------------------------------------------
--                                  Log4Ada                                 --
--                                                                          --
--                            Copyright (C) 2007                            --
--                              X. Grave CNRS                               --
--                                                                          --
--  This library is free software; you can redistribute it and/or modify    --
--  it under the terms of the GNU General Public License as published by    --
--  the Free Software Foundation; either version 2 of the License, or (at   --
--  your option) any later version.                                         --
--                                                                          --
--  This library 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       --
--  General Public License for more details.                                --
--                                                                          --
--  You should have received a copy of the GNU General Public License       --
--  along with this library; if not, write to the Free Software Foundation, --
--  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.          --
--                                                                          --
with Ada.Unchecked_Conversion;
with Ada.Streams;
with Ada.Strings.Unbounded;

with Ada.Exceptions;

package body Log4ada.Socket_Utilities is

   ----------------------
   -- Open_Server_Link --
   ----------------------

   Local_Socket : GNAT.Sockets.Socket_Type;

   Host_Memory : Ada.Strings.Unbounded.Unbounded_String :=
     Ada.Strings.Unbounded.Null_Unbounded_String;
   Port_Memory : GNAT.Sockets.Port_Type := 0;
   Socket_Error_Raised : Boolean := False;

   procedure Open_Server_Link
     (Host : String;
      Port : GNAT.Sockets.Port_Type)
   is
      use GNAT.Sockets;
      Address  : GNAT.Sockets.Sock_Addr_Type;
      use type Ada.Strings.Unbounded.Unbounded_String;
   begin
      if Host_Memory = Ada.Strings.Unbounded.Null_Unbounded_String then
         Host_Memory := Ada.Strings.Unbounded.To_Unbounded_String (Host);
         Port_Memory := Port;
      end if;
      Address.Addr := GNAT.Sockets.Addresses
        (GNAT.Sockets.Get_Host_By_Name
         (Ada.Strings.Unbounded.To_String (Host_Memory)), 1);
      Address.Port := Port_Memory;
      GNAT.Sockets.Create_Socket (Local_Socket);
      GNAT.Sockets.Set_Socket_Option (Local_Socket,
                                      GNAT.Sockets.Socket_Level,
                                      (GNAT.Sockets.Reuse_Address, True));
      GNAT.Sockets.Connect_Socket (Local_Socket, Address);
   exception
      when GNAT.Sockets.Host_Error | GNAT.Sockets.Socket_Error =>
         Socket_Error_Raised := True;
         GNAT.Sockets.Close_Socket (Local_Socket);
      when E : others =>
         Ada.Text_IO.Put ("log4ada socket utilities DBG : open server link=>");
         Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Name (E));
         raise;
   end Open_Server_Link;

   function Get_Link return GNAT.Sockets.Socket_Type is
   begin
      return Local_Socket;
   end Get_Link;

   ---------
   -- Put --
   ---------

   procedure Put
     (Socket : in GNAT.Sockets.Socket_Type;
      S : String)
   is
      use type Ada.Streams.Stream_Element_Offset;
      First : Ada.Streams.Stream_Element_Offset;
      Index : Ada.Streams.Stream_Element_Offset;
      Max : Ada.Streams.Stream_Element_Offset;
      use GNAT.Sockets;
   begin
      if S = "" then
         return;
      end if;
      if Socket_Error_Raised then
         Socket_Error_Raised := False;
         Open_Server_Link (Ada.Strings.Unbounded.To_String (Host_Memory),
                           Port_Memory);
         if Socket_Error_Raised then
            return;
         end if;
      end if;
      declare
         subtype Local_String is String (S'First .. S'Last);
         subtype Local_Stream_Array is Ada.Streams.Stream_Element_Array
           (Ada.Streams.Stream_Element_Offset
            (S'First) .. Ada.Streams.Stream_Element_Offset (S'Last));
         function To_Stream is new Ada.Unchecked_Conversion
           (Local_String, Local_Stream_Array);
         Data : constant Local_Stream_Array := To_Stream (S);
      begin
         First := Data'First;
         Index := First - 1;
         Max := Data'Last;
         Send_Socket (Socket, Data (First .. Max), Index);
      exception
         when GNAT.Sockets.Socket_Error =>
            Socket_Error_Raised := True;
            Close_Socket (Socket);
         when E : others =>
            Ada.Text_IO.Put_Line ("log4ada socket utilities DBG : put=>" &
                                    Ada.Exceptions.Exception_Name (E));
            raise;
      end;
   end Put;

   --------------
   -- New_Line --
   --------------

   procedure New_Line
     (Socket : in GNAT.Sockets.Socket_Type;
      Spacing : in Ada.Text_IO.Positive_Count := 1)
   is
   begin
      for I in 1 .. Spacing loop
         Put (Socket, (1 => ASCII.LF));
      end loop;
   end New_Line;

end Log4ada.Socket_Utilities;
