roh/conf.old/area/
roh/config/code/python/
roh/config/game/area/
roh/config/game/signs/
roh/help/dmhelp/
roh/help/help/
roh/log/
roh/log/staff/
roh/monsters/ocean/
roh/objects/misc/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.47e/
/*
 * 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-2012 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
#define ATCP TELOPT_ATCP
#define MSDP TELOPT_MSDP
#define CHARSET TELOPT_CHARSET

extern long InBytes;
extern long UnCompressedBytes;
extern long OutBytes;

class Player;
class ReportedMsdpVariable;

namespace telnet {
	#define TELOPT_CHARSET 		42
	#define TELOPT_MSDP         69
	#define TELOPT_MSSP         70
	#define TELOPT_COMPRESS 	85
	#define TELOPT_COMPRESS2 	86
	#define TELOPT_MSP 			90
	#define TELOPT_MXP 			91
	#define TELOPT_ATCP         200

	#define SEND				1
	#define ACCEPTED            2
	#define REJECTED            3

	#define MSSP_VAR 			1
	#define MSSP_VAL 			2

	#define MSDP_VAR            1
	#define MSDP_VAL            2
	#define MSDP_TABLE_OPEN     3
	#define MSDP_TABLE_CLOSE    4
	#define MSDP_ARRAY_OPEN     5
	#define MSDP_ARRAY_CLOSE    6
	#define MAX_MSDP_SIZE       100

	#define UNICODE_MALE		9794
	#define UNICODE_FEMALE		9792
	#define UNICODE_NEUTER		9791

    #define MXP_BEG             "\x03"
    #define CH_MXP_BEG          '\x03'
    #define MXP_END             "\x04"
    #define CH_MXP_END          '\x04'
    #define MXP_AMP             "\x06"
    #define CH_MXP_AMP          '\x06'

    #define MXP_SECURE_OPEN "\033[1z"
    #define MXP_LOCK_CLOSE "\033[7z"


	extern unsigned const char will_msdp[];		// Mud Server Data Protocol support
	extern unsigned const char wont_msdp[];		// Stop MSDP support

	extern unsigned const char do_atcp[];		// ATCP support
	extern unsigned const char wont_atcp[];		// Stop ATCP support

	extern unsigned const char will_mxp[];   	// MXP Support
	extern unsigned const char start_mxp[];		// Start MPX string

	extern unsigned const char will_comp2[]; 	// MCCP V2 support
	extern unsigned const char will_comp1[]; 	// MCCP V1 support
	extern unsigned const char start_mccp[]; 	// Start compress
	extern unsigned const char start_mccp2[];	// Start compress2

	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 do_charset[];    // Window size negotation NAWS
    extern unsigned const char charset_utf8[];	// Negotiate UTF-8


	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 {
	friend class Server;
	struct Host {
		bstring hostName;
		bstring ip;
	};
	struct Term {
		int rows;
		int cols;
		bstring type;
		bstring lastType;
		bstring version;
	};
	struct SockOptions {
		bool		    dumb; // Dumb client, don't do telnet negotiations
		int             color;
		bool            xterm256;
		int			    mccp;
		bool		    mxp;
		bool            mxpClientSecure;
		unsigned char   lastColor;
		bool		    msdp;
		bool 		    atcp;
		bool		    eor;
		bool		    msp;
		bool		    compressing;
		bool		    naws;
		bool		    charset;
		bool		    UTF8;
	};
public:
	// Static Methods
	static void resolveIp(const sockaddr_in &addr, bstring& ip);
	static bstring stripTelnet(bstring& inStr, int& newLen);

public:
	Socket(int pFd);
	Socket(int pFd, sockaddr_in pAddr, bool &dnsDone);
	~Socket();

	void cleanUp();
	void reset();

	void startTelnetNeg();
	void continueTelnetNeg(bool queryTType);
	void setState(int pState, int pFnParam = 1);
	void restoreState();
	void addToPlayerList();

	void finishLogin();


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

	void vprint(const char *fmt, va_list ap);

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

	bstring parseForOutput(bstring& outBuf);
	bstring getColorCode(const unsigned char ch);

	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


	int startCompress(bool silent = false);
	int endCompress();

	int sendMSSP(); // Send MSSP Variables

	bool saveTelopts(xmlNodePtr rootNode);
	bool loadTelopts(xmlNodePtr rootNode);

// 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 getMxpClientSecure() const;
	bool getMsdp() const;
	bool getAtcp() const;
	bool canForce() const;
	bool getEor() const;
	bool isDumbClient() const;
	bool getMsp() const;
	bool getNaws() const;
	bool getCharset() const;
	bool getUtf8() const;

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

    void setColorOpt(int opt);

	Player* getPlayer() const;
	void setPlayer(Player* ply);
	void freePlayer();



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

	// MXP Support
	void clearMxpClientSecure();
	void defineMxp();

	// MSDP Support Functions
	void msdpSendPair(bstring variable, bstring value);
	void msdpSendList(bstring variable, bstring value);
	void msdpClearReporting();

protected:
	// Telopt related
	bool negotiate(unsigned char ch);
	//bool subNegotiate(unsigned char ch);
	bool handleNaws(int& colRow, unsigned char& chr, bool high);
	int processCompressed(void); // Mccp

	bool parseMXPSecure();

	// MSDP Support Functions
	bool parseMsdp();
	bool processMsdpVarVal(bstring& variable, bstring& value);
	bool parseAtcp();
	bool msdpSend(bstring value);
	bool msdpSend(ReportedMsdpVariable* reportedVar);
	bool msdpList(bstring& value);
	bool msdpReport(bstring& value);
	bool msdpReset(bstring& value);
	bool msdpUnReport(bstring& value);

	ReportedMsdpVariable *getReportedMsdpVariable(bstring& value);
	bool isReporting(bstring& value);
	//const char MsdpCommandList[] = "LIST REPORT RESET SEND UNREPORT";

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

	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;

	bstring		output;
	bstring		processed_output;	// Output that has been processed but not fully sent (in the case of EWOULDBLOCK for example)

	std::queue<bstring> input;		// Processed Input buffer

	// IAC buffer, we make it a vector so it will handle NUL bytes and other characters
	// and still report the correct size()/length()
	std::vector<unsigned char>	cmdInBuf;
	bstring		inBuf;				// Input Buffer
	bstring		inLast;				// Last command

	Player*		myPlayer;


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

// For MCCP
	char		*out_compress_buf;
	z_stream    *out_compress;

// Old items from IOBUF that we might keep

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

	char		fnparam;

	char		commands;

	Socket		*spyingOn;		// Socket we are spying on
	std::list<Socket*> spying; 	// Sockets spying on us

	std::map<bstring, ReportedMsdpVariable*> msdpReporting;
// TEMP
public:
	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_*/