1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
/*
* Atom-4 network server
* Header file
*
* $Id: server.h,v 1.12 2003/04/15 20:39:28 hsteoh Exp hsteoh $
* --------------------------------------------------------------------------
* PROTOCOL
*
* Please see protocol.txt.
*/
#ifndef SERVER_H
#define SERVER_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "event.h"
#include "game.h"
#include "net.h"
#define MAX_CLIENTS 12 // NOTE: must be < FD_SETSIZE
#define SERVER_BACKLOG 2 // socket backlog limit
class server; // forward decl
class clientconn : public netconn {
friend class server;
server *serv; // [R]
int id; // client ID as registered in *serv
char *hostname; // [O]
netparser parser; // packet parser
enum state_t { // connection state
HANDSHAKE=1, // initial handshake
CONNECTED=3, // connected
DISCONN=10 // to be disconnected
} connstate;
int playnum; // 1 or 2 if playing, 0 if watching
// Protocol dispatch table
static struct dispatch {
const char *packet_type;
void (clientconn::*handler)();
} dispatch_tbl[];
// Dispatch functions
void p_name();
void p_requ();
void p_move();
void p_rsgn();
void p_chat();
void p_next();
void p_play();
void p_watch();
void p_quit();
void p_who();
// Convenience functions
void fatal_error(const char *fmt, ...);
void not_implemented();
int next_number(); // parse next word in parser as number
// Processors for incoming packets
void handshake();
void enter_connected_state(); // initial stuff to be done when client
// first enters connected state
void connected_state();
// Base class pure virtuals
void process_packet(char *packet);
void disconnected();
public:
// ([O])
clientconn(server *s, int cid, int sock, char *hostname, eventloop *loop,
int sendlimit);
~clientconn();
void send_board(board4 *b);
int plnum() { return playnum; }
void round_over();
};
class server {
public:
enum opt_t { // can be OR'd together
LOCAL_ONLY=1, // listen only on loopback address
ALLOW_OBSERVERS=2 // allow clients to connect to watch,
// but not play. (TBD)
};
private:
eventloop *loop; // [R]
int options; // technically, many OR'd opt_t's
inline int opt(opt_t flag) { return options & flag; }
// Network-specific stuff
int port; // listen port
int sock; // listen sock
struct sockaddr_in sockname; // socket address
class serversock : public eventhandler {
server *serv; // server object
public:
serversock(server *s) : serv(s) {}
void read_ready(eventloop *src, int fd);
void write_ready(eventloop *src, int fd);
} listener;
// Client disconnector
class disconnector : public timerhandler {
server *serv;
int cid;
public:
disconnector(server *s, int client_id) : timerhandler(DYNAMIC), serv(s),
cid(client_id) {}
void tick(eventloop *src, timeval t);
};
fd_set csocks; // client sockets
int csocks_max; // max fd's in csocks
clientconn *clients[MAX_CLIENTS]; // [O]
// Game-specific stuff
atom4 *game; // [R] game engine
clientconn *players[NUM_PLAYERS]; // [R]
int create_servsock(int port, struct sockaddr_in *sockname, int backlog);
int new_client();
void broadcast(const char *fmt, ...); // broadcast message to all clients
void reset_players();
public:
server(atom4 *engine, eventloop *loop, int port, int options);
~server();
void disconnect_client(int cid);
// Requests for global information
void send_names(int cid);
// Game flow functions
// - need_players() returns non-zero if there are still slots available for
// joining the current game
// - assign_player() assigns the client to a player number if available, and
// returns the player number; otherwise returns 0 (watcher).
// - move() makes a move. The following codes are returned:
// 1 Move successful
// 0 Illegal move
// -1 Game not started yet
// -2 Not the player's turn to move
int need_players(); // are there still playing slots left?
int assign_player(int cid);
int move(int player, int x, int y);
board4 *get_board() { return game->get_board(); }
};
#endif // SERVER_H
|