/*=====================================================================*/
/*    serrano/prgm/project/bigloo/runtime/Jlib/server_socket.java      */
/*    -------------------------------------------------------------    */
/*    Author      :  Manuel Serrano                                    */
/*    Creation    :  Tue Dec  5 10:53:03 2000                          */
/*    Last change :  Sat Jul 14 06:53:01 2001 (serrano)                */
/*    Copyright   :  2000-01 Manuel Serrano                            */
/*    -------------------------------------------------------------    */
/*    The Server Socket implementation for the JVM back-end.           */
/*=====================================================================*/
using System;
using System.Net;
using System.Net.Sockets;

namespace bigloo 
{
  /*---------------------------------------------------------------------*/
  /*    SOCKET ...                                                       */
  /*---------------------------------------------------------------------*/
  public sealed class server_socket: socket 
  {
    /*--- private fields ---------------------------------------------------*/
    private readonly Socket _server_socket;
    private Socket client_socket;
    private bool blocking;

    /*--- constructors ----------------------------------------------------*/
    public server_socket( int  port )
      : base() 
    {
      try
      {
        _server_socket= new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
        _server_socket.Bind( new IPEndPoint( 0, port ) );
        _server_socket.Listen( 10 );
      } 
      catch (Exception e)
      {
        socket_error( "make-server-socket",
                      "cannot create socket (" + e.Message + ")",
                      new bint( port ) );
      }
    }

    private server_socket( server_socket  templ )
      : base()
    {
      _server_socket= templ._server_socket;
      client_socket= templ.client_socket;
      blocking= templ.blocking;
    }

    /*--- public methods --------------------------------------------------*/
    public override Object HOSTNAME()
    {
      if (client_socket != null)
        return foreign.getbytes( Dns.GetHostByAddress( ((IPEndPoint)client_socket.RemoteEndPoint).Address ).HostName );
      else
        return bigloo.foreign.BFALSE;
    }

    public override Object HOSTIP()
    {
      if (client_socket != null)
        return foreign.getbytes( ((IPEndPoint)client_socket.RemoteEndPoint).Address.ToString() );
      else
        return bigloo.foreign.BFALSE;
    }

    public override byte[] local_addr()
    {
      return foreign.getbytes( ((IPEndPoint)_server_socket.LocalEndPoint).Address.ToString() );
    }

    public Object accept_connection( bool  blocking )
    {
      client_socket= _server_socket.Accept();
      this.blocking= blocking;
      set_socket_io_ports( client_socket, blocking );
      return bigloo.foreign.BUNSPEC;
    }

    public client_socket accept( bool  blocking,
                                 bool  errp )
    {
      Socket       accepted_socket= _server_socket.Accept();

      return new client_socket( accepted_socket, blocking );
  }

    public override socket socket_dup()
    {
      return new server_socket( this );
    }

    public override Object shutdown( bool  close_socket )
    {
      if (client_socket != null)
        try
        {
          client_socket.Shutdown( SocketShutdown.Both );
        }
        catch (Exception)
        {
        }

      if (close_socket)
        close();

      return bigloo.foreign.BUNSPEC;
    }

    public override Object close()
    {
      // !!!!! On fait pas de shutdown ?????
      _server_socket.Close();
      down= true;
      return bigloo.foreign.BUNSPEC;
    }

    public override int PORT()
    {
      return ((IPEndPoint)_server_socket.LocalEndPoint).Port;
    }

    public override void write( output_port  p )
    {
      p.write( "#<socket:localhost" + "." + PORT() + ">" );
    }
  }
}
