musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
#ifndef MSI_H
#define MSI_H

#include "config.h"

#include <sys/types.h>
#include <netinet/in.h>
#include <time.h>

#ifndef NOCOMPRESS
#include <zlib.h>
#endif

#include "ident.h"
#include "charset.h"
#include "base.h"
#include "colour.h"
#include "commandhandler.h"

class Socket;
  
//! MSI: the Mud's telnet Stack.
namespace msi {

  enum Thingy {
    tNone    = 0,
    tNormal  = 1,
    tMono    = 2,
    tWebmake = 17,
  };

  //! a telnet stack/connection
  class player {

  private:
    void blank();
#define SMALL_BUFSIZE 500
#ifndef NOCOMPRESS
    z_stream *deflate;
    Bytef small_outbuf[SMALL_BUFSIZE];
#endif
    int esc;
    string escstr;

    int secure;
    // Did we get an MXP secure mode escape sequence?

    void datah(unsigned char data, commandhandler *);
    void tstack(unsigned char data, commandhandler *);
    void handle_naws(commandhandler *, const string &);
    void handle_ttype(commandhandler *, const string &);

    string outbuffer;

  public:
    //! The socket associated with this 
    Socket *socket;

    //! The buffer of text recieved so far on this socket.
    string buffer;

    int trunc;

    //! The cursor position within the buffer.
    int cursor;

    //! What socket is this object from?
    Thingy thingy_from;
   
    //! Whether this connection has agreed to be sent IAC EOR at the end of every prompt.
    int do_eor;
    
    //! Whether this connection is being sent MXP.
    int mxp;

    int secure_locked;
    // Is MXP secure mode locked?
    
    //! The auto-detected new line character for this connection.
    char newlinechar;

    //! The number of rows on this connection (per NAWS)
    int row;
    //! The number of columns on this connection (per NAWS)
    int col;
    
    //! 1 to indicate this isn't a telnet connection, but a webmake connection or some other internet protocol.
    int rawmode;
    
    //! The time the last IAC NOP (keepalive) packet was sent.
    time_t last_keepalive;

    //! The terminal type as identifed by TTYPE.
    string term;
    
    //! Whether the remote end is echoing at the moment or not.
    int last_noecho;
    
    //! The state the remote ends colour parser should be in.
    colstate_t colstate;
    
#ifndef NOCOMPRESS
    //! Whether the other end has agreed to compression (MCCP)
    int will_compress;
    
    //! Whether compression is actually in effect.
    int compress;
#endif
    
    //! Telnet net subnegiation in progress
    int se_mode;

    //! Telnet state
    int mode;
    
    //! Telnet subnegotiation buffer
    string se_str;
    
    //! Whether other end has agreed to telnet multiplexing.
    int mplex;
    
    //! The titlebar the other end is displaying
    string titlebar;

    //! The returned version of MXP
    string mxp_version;
        
#ifndef NOCOMPRESS
    //! the number of uncompressed bytes we've sent
    long long rawbytes;

    //! the number of bytes we've sent (before compresssion)
    long long uncbytes;
    //! the number of bytes we've sent (after compression)
    long long combytes;
#endif
        
    //! whether we are providing a line editor at our end
    int lineeditor;

    //! is it ok to send stuff to this socket?
    int nosend;

    //! do the initial telnet requests
    void ask_things();

#ifndef NOCOMPRESS
    //! turn compression on
    void compress_on();

    //! turn compression off
    void compress_off();
#endif

    //! eor
    void eor();
    
    //! echo
    void noecho(bool);

    //! create a new (empty) connection
    player();
    
  public:
    //! create a connection and latch onto the given fd
    player(int fd);

    ~player();

    //! format the string taking into account given colour preferences, and send it to the player
    void write(const char *, const colourinfo_t &);

    //! send the raw bytes given
    void rawsend(const string &);
    //! send the raw bytes given
    void rawsend(const char *data, size_t s);

    //! read data, and call methods on the commandhandler as appropriate
    int read(commandhandler *);

    string get_ip() const;
    string get_hostname() const;
    int get_port() const;

    //! send an IAC NOP packet if applicable
    void keepalive();

    //! choose which mplex subwindow to address
    void mplex_choose(int);
    //! show an mplex subwindow
    void mplex_show(int);
    //! hide an mplex subwindow
    void mplex_hide(int);
    //! set the size of an mplex subwindow
    void mplex_setsize(int, int, int);

    //! accept and create a connection
    static player *accept(fd_set *fdset);

    //! serialise the telnet state and return it
    string serialise() const;

    //! deserialise the telnet state
    void deserialise(const string &s);

    //! actually flush
    void flush();
  };

  //! set base port /port/
  void set_port(int port);

  //! open up all the ports, with base port port
  void init(int port);

  //! open ports
  void init();

  //! close all the ports.
  void done();

  //! return the current port
  int port();
}

class PersonState;

string serialise_personstate(PersonState *ps);
void deserialise_personstate(PersonState *ps, string);

#endif