// 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:        socks4.h
// 
// Purpose:     
// 
// Created:     7 Jan 1997   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
//
// SOCKS ver. 4 protocol entities (not that complete, though)
// 
// $Id: socks4.h,v 1.2 1997/03/03 23:20:54 jfasch Exp $
// 
// $Log: socks4.h,v $
// Revision 1.2  1997/03/03 23:20:54  jfasch
// size is 8 (u_long is 8 on DEC Alpha OSF1)
//
// Revision 1.1  1997/02/12 20:14:44  jfasch
// Initial revision
//
// 
// </file> 
#ifndef hg_utils_socks4_h
#define hg_utils_socks4_h

#include "inetaddr.h"
#include "smartptr.h"
#include "str.h"

class OBuffer ;

class SOCKS4ConnectRequest : public RefCounted {
public:
   enum { base_size = 8 } ;
public:
   SOCKS4ConnectRequest (const INETAddress&, const RString& uid) ;
   int size() const { return base_size + uid_.length() + 1 ; }
   void write (OBuffer&) const ;
private:
   INETAddress addr_ ;
   RString uid_ ;
public:
   // link time assertion
   static const char* version1 ;
} ;
static const char* SOCKS4ConnectRequest_version = SOCKS4ConnectRequest::version1 ;
SmartPtrdeclare (SOCKS4ConnectRequestPtr, SOCKS4ConnectRequest) ;

class SOCKS4ConnectReply : public RefCounted {
public:
   enum { size = 8 } ;
   enum State {
     S4C_INIT,
     S4C_VN,
     S4C_CD,
     S4C_DSTPORT0,
     S4C_DSTPORT1,
     S4C_DSTIP0,
     S4C_DSTIP1,
     S4C_DSTIP2,
     S4C_DSTIP3,
     S4C_ERROR
   } ;
   enum SOCKS4Error {
     S4CE_GRANTED,
     S4CE_REJORFAIL,
     S4CE_NOIDENTD,
     S4CE_IDENTFAIL,
     S4CE_NOTINIT,
     S4CE_NERRORS
   } ;

public:
   SOCKS4ConnectReply() ;
   SOCKS4ConnectReply (SOCKS4Error e) : state_(S4C_DSTIP3 /*i.e.,done*/), error_(e) {}

   // returns number of characters sucessfully accepted. nevertheless,
   // you have to check the state of this afterwards to determine if
   // ready/error/wantmore.
   int add (const char*, int) ;

   // false if error (this not ok() anymore). true if the char was
   // accepted. if true, my state may be "complete" or "no error and
   // want more"; user has to check this afterwards.
   bool add (char) ;

   // these apply to protocol parsing issues, not to the content of
   // the reply itself.
   bool ok() const { return state_!=S4C_ERROR; }
   bool complete() const { return state_==S4C_DSTIP3; }
   bool error() const { return !ok(); }
   State state() const { return state_; }

   // these do (the only content is an error code).
   SOCKS4Error errorCode() const { return error_; }
   const char* errorDescription() const { return errordescr_[error_]; }

   void write (OBuffer&) const ;

private:
   State state_ ;
   SOCKS4Error error_ ;
   
   static const char* errordescr_[S4CE_NERRORS] ;

public:
   // link time assertion
   static const char* version1 ;
} ;
static const char* SOCKS4ConnectReply_version = SOCKS4ConnectReply::version1 ;
SmartPtrdeclare (SOCKS4ConnectReplyPtr, SOCKS4ConnectReply) ;

#endif


