//////////////////////// Socket and ServerSocket wrapper class header //////////////////////////////


#ifndef _WRAPPERS_H_
#define _WRAPPERS_H_


#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <signal.h>



class socketerror {  // Socket classes throw socketerror

	public:

		socketerror(const char* reason) : fStr(reason) { }
		const char* Reason() { return fStr; }

	// definition of Errors

		const static char NOTCONNECTED[] = "No network connection";
		const static char NOHOST[] = "Host not known";
		const static char NOSOCK[] = "No socket allocation permitted";
		const static char NOPROMOTE[] = "Unable to promote socket to stdio FILE";
		const static char REFUSE[] = "Connection refused";
		const static char BADWRITE[] = "Write to server failed";
		const static char BADREAD[] = "Read from server failed";
		const static char BADCLIENT[] = "connecting client error";
		const static char EOF_ERROR[]="eof, something went very wrong";
		const static char UNDEF_ERROR[]="undefined error in fread or fwrite";

	private:
	
		const char* fStr;
};


#define MAXLINE 4096


//////////////////////// ServerSocket wrapper class header //////////////////////////////
class Socket; // forward reference for ServerSocket


class ServerSocket {
// make friend of Socket to get access to newly private Socket::Accept

	public:
		
		ServerSocket(int port);

		Socket* accept() throw (socketerror);

		int CloseListener(); // for use with fork() and processes
		int getListenFD();

	private:
		
		int port;
		Socket *mysocket;  // returns modified COPIES of main instance on Accept() 

};


//////////////////////////////////  class Socket //////////////////////////


class Socket{

	public:

		friend Socket*	ServerSocket::accept();
		friend int		ServerSocket::CloseListener();
		friend ServerSocket::ServerSocket(int aport);

	// public member Functions

		Socket(const char* host, int port);
		Socket();
		
		Socket(const Socket & other);
		
		Socket& operator=(const Socket & other);
		
		int getListenFD();
		int getConnectedFD();
		int Close();
		

	// need to be re-written

		void readln(char buffer[], int maxlen) throw (socketerror);  // neil function
		void println(const char* msg) throw (socketerror);  // neil function
		
	// new functions using write and read for binary transfer with pthread data controls

		int fRead (void* buff, int size);
		int fRead (void* buff, int size, FILE* in) throw (socketerror); // usable for files 
		int fWrite(const void* buff, int size) throw (socketerror);
		int WriteFrom(FILE* in, int bytes);
		int ReadTo(FILE* out, int bytes);

	private:

		Socket(int port); // only for serversocket

	// member functions

		int setReadTimeout();
		int Accept(); // used by ServerSocket (friend) ( Don't throw , let ServerSocket do it )
		int CloseConnector();  // used by ServerSocket (friend)


	// member variables

		char* host;

		int sockfd;
		int connfd;
		int port;
		timeval to;
		int clilen;
		FILE * fpout;
		FILE * fpin;
		
		struct sockaddr_in serv_addr, cli_addr;
		struct hostent *host_ptr;
};




#endif
