roh/conf/area/
roh/game/talk/
roh/help/
roh/monsters/ocean/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.44b/
/*
 * socket.h
 *   Stuff to deal with sockets
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 * Permission to use, modify and distribute is granted via the
 *  Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
 *    http://creativecommons.org/licenses/by-nc-sa/3.0/
 *
 * 	Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */

#ifndef SOCKET_H_
#define SOCKET_H_

// C Includes
#include <zlib.h>
#include <netinet/in.h>

//class sockaddr_in;
// C++ Includes
#include <queue>
#include <string>
#include <list>

// Mud Includes

// Defines needed
#define TELOPTS
#define TELCMDS
#define NAWS TELOPT_NAWS
#define TTYPE TELOPT_TTYPE

extern long InBytes;
extern long OutBytes;

class Player;

enum telnetNegotiation {
    NEG_NONE,
    NEG_IAC,
    NEG_WILL,
    NEG_WONT,
    NEG_DO,
    NEG_DONT,

    NEG_SB,
    NEG_START_NAWS,
    NEG_SB_NAWS_COL_HIGH,
    NEG_SB_NAWS_COL_LOW,
    NEG_SB_NAWS_ROW_HIGH,
    NEG_SB_NAWS_ROW_LOW,
    NEG_END_NAWS,
    NEG_SB_TTYPE,


    NEG_UNUSED
};
namespace telnet {
	#define TELOPT_COMPRESS 85
	#define TELOPT_COMPRESS2 86
	#define TELOPT_MSSP 70
	#define TELOPT_MXP 91

	#define MSSP_VAR 1
	#define MSSP_VAL 2

	extern unsigned const char will_mxp[];   // MXP Support
	extern unsigned const char will_comp2[]; // MCCP V2 support
	extern unsigned const char will_comp1[]; // MCCP V1 support
	extern unsigned const char will_echo[];  // Echo input
	extern unsigned const char will_eor[];   // EOR After every prompt
	extern unsigned const char will_mssp[];  // MSSP Support
	extern unsigned const char sb_mssp_start[]; // Start MSSP String
	extern unsigned const char sb_mssp_end[];// End MSSP String
	extern unsigned const char do_ttype[];   // Terminal type negotation
	extern unsigned const char query_ttype[];// Begin terminal type subnegotiations
	extern unsigned const char do_naws[];    // Window size negotation NAWS

	extern unsigned const char start_mxp[];	// Start MPX string
	extern unsigned const char start_mccp[];	// Start compress
	extern unsigned const char start_mccp2[];// Start compress2

	extern unsigned const char eor_str[];


	// For MCCP
	void *zlib_alloc(void *opaque, unsigned int items, unsigned int size);
	void zlib_free(void *opaque, void *address);
}

class Socket {
	struct Host {
		bstring hostName;
		bstring ip;
	};
	struct Term {
		int rows;
		int cols;
		bstring type;
	};
	struct SockOptions {
		int			mccp;
		bool		mxp;
		bool		eor;
		bool		compressing;
	};
public:
	Socket(int pFd);
	Socket(int pFd, sockaddr_in pAddr, bool &dnsDone);
	~Socket();

	void reset();

	void sendTelnetNeg();
	void setState(int pState, int pFnParam = 1);
	void restoreState();
	void addToPlayerList();


	int write(bstring toWrite, bool pSpy = true);
	void askFor(const char *str);

	void vprint(const char *fmt, va_list ap, bool parseColor = false);

	void bprint(bstring toPrint);
	void println(bstring toPrint = "");
//	void printPrompt(bstring toPrint);
	void print(const char* format, ...);
	void printColor(const char* format, ...);

	int processInput(void);
	int processOneCommand(void);

	void reconnect(bool pauseScreen=false);
	void disconnect();
	void showLoginScreen(bool dnsDone=true);

	void flush(void); // Flush any pending output


// Telopt related
	bool handleNaws(int& colRow, unsigned char& chr, bool high);

	int processCompressed(void); // Mccp
	int startCompress(void);
	int endCompress(void);

	int sendMSSP(); // Send MSSP Variables

// End Telopt related

	int getFd(void) const;
	bool isConnected() const;
	int getState(void) const;
	const bstring& getIp(void) const;
	const bstring& getHostname(void) const;

	void checkLockOut(void);

	void setHostname(bstring pName);
	void setIp(bstring pIp);

	bool hasOutput(void) const;
	bool hasCommand(void) const;

//	void login(bstring& cmd);
//	void command(bstring& cmd);
//	void createPlayer(bstring& cmd);
	void ANSI(int color);

	long getIdle() const;
	int getMccp() const;
	bool getMxp() const;
	bool canForce() const;
	bool getEor() const;

	bstring getTermType() const;
	int getTermCols() const;
	int getTermRows() const;

	Player* getPlayer() const;
	void setPlayer(Player* ply);
	void freePlayer();
// Static Methods
	static void resolveIp(const sockaddr_in &addr, bstring& ip);


	void clearSpying();
	void clearSpiedOn();
	void setSpying(Socket *sock);
	void removeSpy(Socket *sock);
	void addSpy(Socket *sock);

// TODO - Retool so they can be moved to protected
public:
	char tempstr[4][256];

	int getParam();
	void setParam(int newParam);
protected:
	int			fd;	// File Descriptor of this socket
	Host		host;
	Term		term;
	SockOptions	opts;
	bool inPlayerList;

	int			lastState;
	int			connState;


	int			tState;
	bool		oneIAC;
	bool		watchBrokenClient;

	//std::queue<bstring> output; // Output to send
	bstring		output;
	std::queue<bstring> input;  // Processed Input buffer

	bstring		inBuf; // Input Buffer
	bstring		inLast; // Last command

	Player*		myPlayer;


// From ply extr struct
	int ansi;
	unsigned long timeout;


// Old items from IOBUF that we might keep
	char		*out_compress_buf;
	z_stream    *out_compress;

	void		(*fn)(Socket*, char*);

	char		fnparam;

	char		commands;

	Socket		*spyingOn;		// Socket we are spying on
	std::list<Socket*> spying; 	// Sockets spying on us
// TEMP
public:
	char		color;
	long		ltime;
	char		intrpt;


public:
	static const int COMPRESSED_OUTBUF_SIZE;
	static int NumSockets;
};


// Other socket related prototypes
int nonBlock(int pFd);
int restoreState(Socket* sock);


#endif /*SOCKET_H_*/