//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: device.h
//
//Version: $Revision: 1.13 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/19 08:46:02 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Authors:
//      Juhana Räsänen
//	Timo Kokkonen
//
//Description:
//      OVOPS++ device class. This class provides a default interface
//      to a object accessed with a file handle (file, socket, pipe etc.)
//      Device can be read and written in an asynchronous manner.
//      Note that pfDevice is an abstract base class, however, user
//      of pfDevice must implement at the very least the openDevice
//      method in her concrete device class.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//
//Licence:
//
//
//History: 
//
//

#ifndef __PF_DEVICE_H__
#define __PF_DEVICE_H__

#include <typeinfo>
#include <sys/socket.h>
#include <netinet/in.h>
#include "pf/adapter.h"
#include "pf/types.h"
#include "pf/frame.h"
#include "sf/otime.h"

//
//Class: pfDevice
//
//Description:
//    Abstract base class for file handle type devices. Provides default
//    functionality that the inherited classes may or may not redefine.
//    However, the inherited classes must define openDevice() method
//    (which is pure virtual in base class) to perform open procedure
//    specific to the type of the concrete device class.
//
//    NOTE: the openDevice call or inherited class constructor must also
//    allocate buffer for the device, because special alignment constraints
//    may be necessary for some sockets. Base class constructor does *NOT*
//    allocate buffer space.
//

class pfDevice : public pfAdapter
{
    public:
        explicit pfDevice(pfUlong bufferSize_);
        virtual ~pfDevice(void);

        // Note: openDevice is pure virtual, because it depends of the
        // type of the file descriptor used (socket, file, etc.)
//        virtual bool openDevice(void) = 0;
        virtual bool closeDevice(void);
        virtual bool readDevice(void);
        virtual bool writeDevice(pfFrame &frame_);

        virtual void setStatusRead(void);
        virtual void setStatusWrite(void);
        virtual void setStatusPolling(void);
        virtual void setStatusError(void);
        virtual void clearStatusRead(void);
        virtual void clearStatusWrite(void); 
        virtual void clearStatusPolling(void);
        virtual void clearStatusError(void);

        virtual void setAddr(const struct sockaddr_in &addr_);
        virtual const struct sockaddr_in &getAddr(void) const;

        virtual bool isPolling(void) const;

    protected:
        void setFD(int fd_);
        virtual void readCallback(void);
	virtual void writeCallback(void);
        virtual int readFromSocket(void);
	virtual int writeToSocket(char *start_);

        virtual void readAction(pfFrame &frame_, pfUlong code_) = 0;
        virtual void writeAction(pfUlong code_) = 0;

        // Method for releasing buffers. This is declared pure virtual
        // so that derived classes must implement is - and thus think
        // about buffer allocation/deallocation.
        virtual void freeBuffers(void) = 0;

        pfFrame _writeFrame;
        bool _readPending;
        bool _writePending;

        pfUlong _bufferSize;
        char *_readBuffer;
        char *_writeBuffer;
        int _readBufferLength;
        int _writeBufferLength;

        static const int NO_FD = -1;
        int _fd;

        enum Status // status bits of a device
        {
            IDLE      = 0x01,
            READ      = 0x02,
            WRITE     = 0x04,
            TIMEOUT   = 0x10,
            POLLING   = 0x20,
            ERROR     = 0x40
        };
        int _status;

        OTime _defTimeout;

    private:
	pfDevice(const pfDevice &other_);
	pfDevice &operator=(const pfDevice &other_);
};

#endif  // __PF_DEVICE_H__

