File : aws-server.ads


------------------------------------------------------------------------------

--                              Ada Web Server                              --

--                                                                          --

--                         Copyright (C) 2000-2001                          --

--                                ACT-Europe                                --

--                                                                          --

--  Authors: Dmitriy Anisimkov - Pascal Obry                                --

--                                                                          --

--  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.          --

--                                                                          --

--  As a special exception, if other files instantiate generics from this   --

--  unit, or you link this unit with other files to produce an executable,  --

--  this  unit  does not  by itself cause  the resulting executable to be   --

--  covered by the GNU General Public License. This exception does not      --

--  however invalidate any other reasons why the executable file  might be  --

--  covered by the  GNU Public License.                                     --

------------------------------------------------------------------------------


--  $Id: aws-server.ads,v 1.43 2001/10/12 20:08:22 obry Exp $


with Ada.Calendar;
with Ada.Finalization;
with Ada.Strings.Unbounded;

with Sockets;

with AWS.Response;
with AWS.Hotplug;
with AWS.Config;
with AWS.Default;
with AWS.Log;

package AWS.Server is

   Def_Admin_URI   : String renames Default.Admin_URI;
   Def_Upload_Dir  : String renames Default.Upload_Directory;
   Def_Max_Connect : constant := Default.Server_Port;
   Def_Port        : constant := Default.Server_Port;

   type HTTP is limited private;
   --  A Web server.


   procedure Start
     (Web_Server                : in out HTTP;
      Callback                  : in     Response.Callback;
      Config                    : in     AWS.Config.Object);
   --  Start server using a full configuration object. With this routine it is

   --  possible to control all features of the server. A simplified version of

   --  Start is also provided below with the most common options.

   --  User_Config_Filename is a specific configuration file that will parsed

   --  after 'aws.ini', 'prognam.ini', '<servername>.ini' files.


   procedure Start
     (Web_Server                : in out HTTP;
      Name                      : in     String;
      Callback                  : in     Response.Callback;
      Max_Connection            : in     Positive          := Def_Max_Connect;
      Admin_URI                 : in     String            := Def_Admin_URI;
      Port                      : in     Positive          := Def_Port;
      Security                  : in     Boolean           := False;
      Session                   : in     Boolean           := False;
      Case_Sensitive_Parameters : in     Boolean           := True;
      Upload_Directory          : in     String            := Def_Upload_Dir);
   --  Start the Web server. It initialize the Max_Connection connections

   --  lines. Name is just a string used to identify the server. This is used

   --  for example in the administrative page. Admin_URI must be set to enable

   --  the administrative status page. Callback is the procedure to call for

   --  each resource requested. Port is the Web server port. If Security is

   --  set to True the server will use an HTTPS/SSL connection. If Session is

   --  set to True the server will be able to get a status for each client

   --  connected. A session ID is used for that, on the client side it is a

   --  cookie. Case_Sensitive_Parameters if set to False it means that the CGI

   --  parameters name will be handled without case sensitivity. Upload

   --  directory point to a directory where uploaded files will be stored.


   procedure Shutdown (Web_Server : in out HTTP);
   --  Stop the server and release all associated memory. This routine can

   --  take some time to terminate because it waits for all tasks to terminate

   --  properly before releasing the memory. The log facilities will be

   --  automatically stopped by calling Stop_Log below.


   function Config (Web_Server : in HTTP) return AWS.Config.Object;
   --  Returns configuration object for Web_Server.


   procedure Start_Log
     (Web_Server      : in out HTTP;
      Split_Mode      : in     Log.Split_Mode := Log.None;
      Filename_Prefix : in     String         := "");
   --  Activate server's logging activity. See AWS.Log.


   procedure Stop_Log (Web_Server : in out HTTP);
   --  Stop server's logging activity. See AWS.Log.


   type HTTP_Access is access all HTTP;

private

   type Slot_Phase is
     (Closed,

      Aborted,
      --  After socket shutdown


      Wait_For_Client,
      --  We can abort keep-alive connection in this stage


      Client_Header,
      --  We can abort keep-alive connection when client header

      --  takes too much time


      Client_Data,
      --  We should think about it. Maybe we should not trust the clients

      --  who are spending too much server time in sending data


      Server_Response,
      --  We are trusting ourselves but client may be too slow purposely in

      --  receiving data and we should disconnect him.


      Server_Processing
      --  While in the User's Callback procedure.

     );

   subtype Abortable_Phase is Slot_Phase
     range Wait_For_Client .. Server_Response;

   subtype Data_Phase is Abortable_Phase
     range Client_Data .. Server_Response;

   --  This is Force timeouts and timeouts for Line_Cleaner task.


   type Timeout_Mode is (Cleaner, Force);

   type Timeouts_Array is array (Timeout_Mode, Abortable_Phase) of Duration;

   type Data_Timeouts_Array is array (Data_Phase) of Duration;

   type Socket_Access is access all Sockets.Socket_FD'Class;

   type Slot is record
      Sock                  : Socket_Access := null;
      Socket_Taken          : Boolean := False;
      Peername              : Ada.Strings.Unbounded.Unbounded_String;
      Phase                 : Slot_Phase := Closed;
      Phase_Time_Stamp      : Ada.Calendar.Time := Ada.Calendar.Clock;
      Data_Time_Stamp       : Ada.Calendar.Time;
      Slot_Activity_Counter : Natural := 0;
      Activity_Counter      : Natural := 0;
   end record;

   --  Abortable is set to true when the line can be aborted by closing the

   --  associated socket. Phase_Time_Stamp is the last time when Phase of line

   --  has been changed. The line in Abortable state and with oldest

   --  Phase_Time_Stamp could be closed.

   --  Also a line is closed after Keep_Open_Duration seconds of inactivity.


   type Slot_Set is array (Positive range <>) of Slot;

   package CNF renames AWS.Config;

   -----------

   -- Slots --

   -----------


   protected type Slots (N : Positive) is

      procedure Set_Peername (Index : in Positive; Peername : in String);
      --  Set the Peername for the associated socket.


      procedure Mark_Phase (Index : in Positive; Phase : Slot_Phase);
      --  Set Activity_Time_Stamp which is the last time where the line number

      --  Index as been used.


      procedure Socket_Taken (Index : in Positive);
      --  Used to mark slot associated socket has "taken" by some foreign code.

      --  The server must not close this socket on releasing the slot. It is

      --  used when passing socket to the server push part for example. In the

      --  future it could be used for other functionality over the same

      --  socket, changing HTTP to other protocol for example.


      procedure Mark_Data_Time_Stamp (Index : in Positive);
      --  Mark timestamp for receive or send chunk of data.


      function Is_Abortable
        (Index : in Positive;
         Mode  : in Timeout_Mode)
        return Boolean;
      --  Return True when slot can be aborted.


      procedure Abort_On_Timeout (Mode : in Timeout_Mode; Done : out Boolean);
      --  Abort slots if timeout exceeded.

      --  Set Done to True in case of abortion.


      function Free_Slots return Natural;
      --  Returns number of free slots.


      procedure Get (FD : in Socket_Access; Index : in Positive);
      --  Mark slot at position Index to be used. This slot will be associated

      --  with the socket FD. Phase set to Client_Header.


      procedure Shutdown (Index : in Positive);
      --  Break all communications over the slot.

      --  Slot phase is set to Aborted.


      procedure Release  (Index : in Positive);
      --  Release slot number Index. Slot phase is set to Closed.


      function Free return Boolean;
      --  Returns True if there is some free slots available.


      function Get (Index : in Positive) return Slot;
      --  Returns Slot data.


      function Get_Peername (Index : in Positive) return String;
      --  Returns the peername for socket at position Index.


      procedure Increment_Slot_Activity_Counter (Index : in Positive);
      --  Add 1 to the slot activity. This is the total number of request

      --  handled by the slot.


      procedure Set_Timeouts
        (Phase_Timeouts : in Timeouts_Array;
         Data_Timeouts  : in Data_Timeouts_Array);
      --  Setup timeouts for slots before starting


   private

      Timeouts      : Timeouts_Array;
      Data_Timeouts : Data_Timeouts_Array;

      Set   : Slot_Set (1 .. N);
      Count : Natural := N;

   end Slots;

   type Slots_Access is access Slots;

   ----------

   -- Line --

   ----------


   task type Line is
      entry Start (Server : in HTTP; Index : in Positive);
   end Line;

   type Line_Set is array (Positive range <>) of Line;

   type Line_Set_Access is access Line_Set;

   ------------------

   -- Line_Cleaner --

   ------------------


   task type Line_Cleaner (Server : HTTP_Access) is
     entry Force;
   end Line_Cleaner;

   type Line_Cleaner_Access is access Line_Cleaner;
   --  run through the slots and see if some of them could be closed.


   use Ada.Strings.Unbounded;

   type HTTP is new Ada.Finalization.Limited_Controlled with record
      Self            : HTTP_Access := HTTP'Unchecked_Access;
      --  Point to the record.


      Start_Time      : Ada.Calendar.Time;
      --  Date and Time when server was started.


      Shutdown        : Boolean     := False;
      --  True when shutdown has been requested.


      Sock            : Sockets.Socket_FD;
      --  This is the server socket for incoming connection.


      Cleaner         : Line_Cleaner_Access;
      --  Task in charge of cleaning slots status. It checks from time to time

      --  is the slots is still in used and closed it if possible.


      Properties      : CNF.Object := CNF.Get_Current;
      --  All server properties controled by the configuration file.


      Log             : AWS.Log.Object;
      --  Loggin support.


      CB              : Response.Callback;
      --  User's callback procedure.


      Filters         : Hotplug.Filter_Set;
      --  Hotplug filters are recorded here.


      Lines           : Line_Set_Access;
      --  The tasks doing the job.


      Slots           : Slots_Access;
      --  Information about each tasks above. This is a protected object to

      --  support concurrency.

   end record;

   procedure Finalize (Web_Server : in out HTTP);

end AWS.Server;