// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1996
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        tif.h
// 
// Purpose:     
// 
// Created:     3 Jan 1997   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// $Id: tif.h,v 1.3 1997/02/24 10:18:42 jfasch Exp $
// 
// $Log: tif.h,v $
// Revision 1.3  1997/02/24 10:18:42  jfasch
// timeout added to TIOINETRequest
//
// Revision 1.2  1997/02/12 23:13:11  jfasch
// moved from HgDcCommon
//
// Revision 1.1  1997/02/04 13:48:16  jfasch
// Initial revision
//
// 
// </file> 
#ifndef hg_dispatch_tioinetfact_h
#define hg_dispatch_tioinetfact_h

#include "tio.h"
#include "tioinetattr.h"

#include <hyperg/utils/inetaddr.h>

class TIOINETResponse ;
class TIOINETResponsePtr ;
class TIOINETRequest ;
class TIOINETRequestPtr ;

class TIOINETFactoryUser {
public:
   virtual void tioInetResponse (const TIOINETResponsePtr&) = 0 ;
} ; 

class TIOINETFactory : public RefCounted {
public:
   enum Error {
     TIFOK,
     TIFNEXT,
     TIFNOCONN,
     TIFNOADDR,
     // to be extended
     TIFNERRORS
   } ;

public:
   virtual ~TIOINETFactory() {}

   virtual void start() = 0 ;
   virtual void stop() = 0 ;

   virtual TIOINETResponsePtr connect (const TIOINETRequestPtr&) = 0 ;

protected:
   // set the worker of the request to be me (I am a friend of him).
   void set_worker_(const TIOINETRequestPtr&) ;

private:
   // this is called by my friends, the requests, only, since they are
   // the entities to be cancelled by a user. calls the abstract
   // protected do_cancel_() in turn.
   friend class TIOINETRequest ;
   void cancel_(const TIOINETRequest* r) { do_cancel_(r); }
protected:
   virtual void do_cancel_(const TIOINETRequest*) = 0 ;

protected:
   TIOINETFactory() {}
   // copy verboten
   TIOINETFactory (const TIOINETFactory&) {}
   TIOINETFactory& operator = (const TIOINETFactory&) { return *this; }
public:
   static const char* version1 ;
} ;
static const char* TIOINETFactory_version = TIOINETFactory :: version1 ;
SmartPtrdeclare (TIOINETFactoryPtr, TIOINETFactory) ;

class TIOINETRequest : public RefCounted {
public:
   TIOINETRequest (const INETAddress&, TIOINETFactoryUser*) ;
   TIOINETRequest (const INETAddress&, long timeout, TIOINETFactoryUser*) ;
   void cancel (const TIOINETFactoryUser*) ;

   const INETAddress& address() const { return addr_; }
   long timeout() const { return timeout_; }
   const TIOINETFactoryUser* user() const { return user_; }
   TIOINETFactoryUser* getUser() const { return user_; }
   const TIOINETFactory* worker() const { return worker_; }
   int id() const { return id_; }

private:
   // when a factory gets me to handle me, it registers itself. this
   // enables me to be cancelled (i.e., to tell the factory that is
   // working me to cancel me when I am cancelled).
   friend class TIOINETFactory ;
   void set_worker_(TIOINETFactory*) ;

private:
   // serial # 
   int id_ ;
   static int last_id_ ;

   // the address which a factory is supposed to connect to.
   const INETAddress addr_ ;
   // the timeout applied to a connect call. <= 0 means: no timeout.
   long timeout_ ;
   // presumably equal to the issuer of this (nil if the request (me)
   // should be fulfilled blockingly).
   TIOINETFactoryUser* user_ ;
   // the one that is working me. set by the factories along the way
   // through the object jungle.
   TIOINETFactory* worker_ ;
public:
   static const char* version2 ;
} ;
static const char* TIOINETRequest_version = TIOINETRequest::version2 ;
SmartPtrdeclare (TIOINETRequestPtr, TIOINETRequest) ;

class TIOINETResponse : public RefCounted {
public:
   TIOINETResponse (const TIOINETRequest*, const TransparentIOPtr&, const TIOINETAttributes&) ;
   TIOINETResponse (const TIOINETRequest*, TIOINETFactory::Error) ;

   const TransparentIOPtr& io() const { return io_; }
   const TIOINETAttributes& attributes() const { return attr_; }
   TIOINETFactory::Error error() const { return error_; }

   // see below for the meaning
   const TIOINETRequest* request() const { return request_; }
   
private:
   const TransparentIOPtr io_ ;
   const TIOINETAttributes attr_ ;
   TIOINETFactory::Error error_ ;

   // you get this as a kind of reference number. this is the request
   // to which I belong. 
   const TIOINETRequest* request_ ;

public:
   static const char* version1 ;
} ; 
static const char* TIOINETResponse_version = TIOINETResponse::version1 ;
SmartPtrdeclare (TIOINETResponsePtr, TIOINETResponse) ;

#endif
