/*
  File: network.hh
  
  Description:
  This file contains all network functions to be used with the mpeg2player. This
  is a temporary solution. The complete AtmSocket API should be used for this
  in order to use configuration/testing facilities. Hopefully we can do that im
  June/July 1996
  
  This file has been re-organized big time to cover a more generic range of
  options not necesdarilly related to the mpeg2player.

  class Socket           // Abstract class
    class SocketFile     // Socket to file
    class SocketTcp      // TCP stream socket
    class SocketUdp      // UDP datagram socket - NOT TESTED
    class SocketAtmSpans // ATM Fore Spans signalling socket
    class SocketAtmPvc   // ATM Fore PVC socket

  class SocketMulti      // Socket accepts call from TCP, UDP, ATM spans, or PVC

  Created: April 1996, Alex Theo de Jong, NIST
*/

#ifndef __network_hh_ 
#define __network_hh_

// Network
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/fcntl.h>

#ifdef FORE_ATM

// Fore API

#include <fore_atm/fore_atm_user.h>
#define ATMDEVICE  "/dev/fa0"
#endif


// Abstract class

class Socket {
  friend class SocketMulti;
 protected:
  int socketfd; 
  // variables for recv
  unsigned char* bfr;
  int bytes, read_bytes;
 public:
  Socket(){ socketfd=0; }
  virtual ~Socket(){}
  virtual int accept() = 0;
  virtual int recv(unsigned char* data, int size) = 0;
  virtual int send(unsigned char* data, int size) = 0;
  virtual int close() = 0;
};


class SocketFile : public Socket {
  String filename;
 public:
  SocketFile(const char* filename=0);
  ~SocketFile();
  int accept(){ return (socketfd>0); }
  int recv(unsigned char* data, int size);
  int send(unsigned char*, int){ return -1; }
  int close();
};


class SocketTcp : public Socket {
  int fd;
 public:
  SocketTcp(unsigned int asap, unsigned int pdu_size=0);
  ~SocketTcp();
  int accept();
  int recv(unsigned char* data, int size);
  int send(unsigned char* data, int size){
    return ::write(fd, data, size);
  }
  int close();
};


class SocketUdp : public Socket {
  sockaddr_in cli_addr;
  sockaddr* pcli_addr;
  int cli_len;
  int fd;
 public:
  SocketUdp(unsigned int asap, unsigned int pdu_size=0);
  ~SocketUdp();
  int accept();
  int recv(unsigned char* data, int size);
  int send(unsigned char* data, int size){
    return ::sendto(fd, (char*) data, size, 0, pcli_addr, cli_len);
  }
  int close();
};

#ifdef FORE_ATM


class SocketAtmSpans : public Socket {
  unsigned int asap;
  Aal_type aal_type;
  Atm_qos qos;
  Atm_dataflow dataflow;
  Atm_endpoint atm_endpoint;
  int fd;
 public:
  SocketAtmSpans(unsigned int sap);
  ~SocketAtmSpans();
  int accept();
  int recv(unsigned char* data, int size);
  int send(unsigned char* data, int size){
    return ::atm_send(fd, (caddr_t) data, size);
  }
  int close();
};


class SocketAtmPvc : public Socket {
  Aal_type aal_type;
  Atm_dataflow dataflow;
  Vpvc vpvc;
  int fd;
 public:
  SocketAtmPvc(unsigned int vci, unsigned int vpi=0);
  ~SocketAtmPvc();
  int accept();
  int recv(unsigned char* data, int size);
  int send(unsigned char* data, int size){
    return ::atm_sendto(fd, (caddr_t) data, size, vpvc);
  }
  int close();
};

#endif // FORE_ATM

// Multi socket that accepts the first available connection;
// either TCP, UDP, ATM SPANS or ATM PVC

#define SOCKETMULTI_MAX   10

class SocketMulti {
  Socket** sockets;
  Socket* socket;
  int count; // number of sockets
 public:
  SocketMulti(const char* filename);
  SocketMulti(unsigned int asap, int pdu_size, unsigned int vci=60, unsigned int vpi=0);
  ~SocketMulti();
  int accept();
  int recv(unsigned char* data, int size){ return socket->recv(data, size); }
  int send(unsigned char* data, int size){ return socket->send(data, size); }
  int close(){ return socket->close(); }
};

#endif // __network_hh_

