/*
 * $Id: imserver.hxx,v 4.0 2003/04/28 14:44:41 hut66au Exp $
 *
 * Imview, the portable image analysis application
 * http://www.cmis.csiro.au/Hugues.Talbot/imview
 * ----------------------------------------------------------
 *
 *  Imview is an attempt to provide an image display application
 *  suitable for professional image analysis. It was started in
 *  1997 and is mostly the result of the efforts of Hugues Talbot,
 *  Image Analysis Project, CSIRO Mathematical and Information
 *  Sciences, with help from others (see the CREDITS files for
 *  more information)
 *
 *  Imview is Copyrighted (C) 1997-2001 by Hugues Talbot and was
 *  supported in parts by the Australian Commonwealth Science and 
 *  Industry Research Organisation. Please see the COPYRIGHT file 
 *  for full details. Imview also includes the contributions of 
 *  many others. Please see the CREDITS file for full details.
 *
 *  This program 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 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 General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 * */


/*------------------------------------------------------------------------
 *
 * imserver.H
 *
 * The image server part of imview.
 *
 * Hugues Talbot	 1 Mar 2000
 *      
 *-----------------------------------------------------------------------*/

#ifndef IMSERVER_H
#define IMSERVER_H

#include "asynchat.hxx"
#include "semaphore.hxx"
#include "interpreter.hxx"
#include "machine.hxx"

#define IMPROMPT "Imview > "
#define HNDSHK   "OK\n"
#define HSLEN    3
#define PORTNB   7600

// mt is a pointer to a function taking void * as input and returning a void*
typedef void *(*mt)(void *);
// cb_func is a pointer to a function taking a void*+ulong as input and returning int.
typedef int(*cb_func)(void *, unsigned long);

void *init_server(int *);

#define IBFSIZE 8196

// A channel for binary data upload
class imview_data : public dispatcher
{
private:
    int                identifier;
    unsigned long      comm_bufsize, recv_bufsize;
    unsigned long      received, expected;
    char              *recv_buffer, *comm_buffer;
    bool               abort;
    // class variable
    static int         channels_id;
    
public:
    imview_data();
    virtual ~imview_data();
    void     handle_connect();
    void     handle_read();
    void     handle_write();
    void     handle_close();
};

// A channel has all what's needed for command communication.
class imview_channel : public async_chat
{
    string        input_buffer;
    string        cs, rs;
    int           identifier;
    list <string> commandBuffer;
    list <string> resultBuffer;
    bool          logged_in;
    Semaphore     access_command, access_result;
    
    // class variable
    static int    channels_id;

public:
    imview_channel();
    ~imview_channel();

    // commands
    void protect_command(void);
    void unprotect_command(void);
    void write_command(string &c);
    string&  read_command(void);
    bool command_isempty(void);
    
    // results.
    void protect_result(void);
    void unprotect_result(void);
    void write_result(string &r);
    string& read_result(void);
    bool result_isempty(void);

    // socket comm
    void sendResult(void);

    void collect_incoming_data (const string& data);
    void found_terminator (void);

    // the handle methods
    void handle_close (void);
};

class imview_server;

// this class only serves to open a data channel
// this is necessary because it's impossible to find out
// where an `accept' is coming from.
class datachannel_opener:public dispatcher {
private:
    list<imview_data *>    ld;      // list of data channels
    imview_server          *parent; // parent server
    int                    port_id;    // our private port.

public:
    virtual  ~datachannel_opener(void);
    void      handle_accept(void);
    void      setparent(imview_server *p) {parent = p;}
    void      setport(int v) {port_id = v;}
    int       port(void) {return port_id;}
};

typedef list<imview_channel *>::const_iterator CLI; // list iterator

class imview_server : public dispatcher
{
private:    
    list<imview_channel *> lc;          // list of command channels
    int                    port_start;  // even ports: command, odd ports: data.
    datachannel_opener     *dco;        // only one of them!
    
public:
    imview_server();
    virtual  ~imview_server();
    void      handle_accept (void);
    int       open_data_channel(string &s);
    int       close_data_channel(void);
    void      manage_results(void);
    void      manage_commands(void);
    void      setport(int p) {
	port_start = p;
    }
};

#endif //IMSERVER_H
