//=========================================================================
// Summary  :
// Filename : Modem.h
// Author   : haydn
// Project  :
// Revision : 1
// Created  : 2000/12/08
// Modified : 2000/12/08
//=========================================================================
// Description :  Generic Modem Interface
//=========================================================================
#ifndef _MODEMSOCKET_H
#define _MODEMSOCKET_H

#include "ModemFork.h"


///////////////////////////////////////////////////////
//  Socket compatability cruft.
#define SD_RECEIVE 0
#define SD_SEND 1
#define SD_BOTH 2

// Are we under QNX?
#ifndef _MSC_VER
// These definitions make windows Sockets look like unix Sockets.
// Okay, that is somewhat backward.
# include <sys/socket.h>
# include <errno.h>
# include <sys/select.h>
# include <ioctl.h>
# include <netinet/in.h>
# define INVALID_SOCKET  (SOCKET)(~0)
# define SOCKET_ERROR            (-1)
# define ioctlsocket ioctl
# define closesocket close

// Socket error codes
# define WSAGetLastError() errno
# define WSAEAGAIN            EAGAIN
# define WSAEFAULT            EFAULT
# define WSAEHOSTUNREACH      EHOSTUNREACH
# define WSAENOBUFS           ENOBUFS
# define WSAENOTCONN          ENOTCONN
# define WSAENOTSOCK          ENOTSOCK
# define WSAEWOULDBLOCK       EWOULDBLOCK
# define WSANOTINITIALISED    NOTINITIALISED
# define WSAEINVAL            EINVAL
# define WSAEALREADY          EALREADY
# define WSAEISCONN           EISCONN
# define WSAEINPROGRESS       EINPROGRESS


typedef int SOCKET;

# define IN_CLASSD_NSHIFT 0
//# define MAKE_IN_ADDR(A,B,C,D) (A<<IN_CLASSA_NSHIFT | B<<IN_CLASSB_NSHIFT | C<<IN_CLASSC_NSHIFT | D<<IN_CLASSD_NSHIFT)
# define MAKE_IN_ADDR(A,B,C,D) (A | B<<8 | C<<16 | D<<24)
# include <arpa/inet.h>



#else
// We are under Windows!
// These defines make a few unix symbols available.
# define MAKE_IN_ADDR(A,B,C,D) (A | B<<8 | C<<16 | D<<24)
# define WSAEAGAIN            WSAEWOULDBLOCK
#endif



///////////////////////////////////////////////////////
//  Fake Modem class, implementing modem as a socket.

class ModemSocket : public ModemFork {

 public:

    ModemSocket(const char* pcIPAddress, long approxSpeed = 0);
    virtual ~ModemSocket();

    void setPort(unsigned int port);
    void setTargetIP(const char* pcIP);

    ///////////////////////////////////////////////////////////////////
    // ModemFork OVERRIDES
    virtual int iReadFromModem(char* buffer, int iMaxLen);
    virtual int iWriteToModem(char* buffer, int iMaxLen);
    virtual int getBytesPerSecondChild();
    virtual bool bHasConnectionChild();
  
    void parseWSAError( int err );
  
 protected:
  
    ///////////////////////////////////////////////////////////////////
    // Modem OVERRIDES
    virtual int  iGetMaxTransitBytes();
    virtual int  iExpectedRoundTripDuration() const
	{ return 1; };
  

 protected:
    ///////////////////////////////////////////////////////////////////
    // initialize - sets up the socket
    virtual void initialize() ;

    virtual bool bSocketConnected() const;
  
    bool bSetupSocketConnect();
    bool bSetupSocketListen();
    bool bSetupSocket();

    SOCKET _cSocket;    // the socket we should use for our communication.
    SOCKET _lSocket; // the listening socket

    in_addr _ipAddress;
    unsigned int _cPort;
	unsigned int _lPort;
    int _keepAliveCount;
	int _fuzzyCon;
	long _approxSpeed;

    debug_t debug;
};



#endif
