File: server.h

package info (click to toggle)
atom4 4.1-6
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 656 kB
  • ctags: 947
  • sloc: cpp: 4,461; makefile: 54; sh: 21; perl: 6
file content (162 lines) | stat: -rw-r--r-- 4,234 bytes parent folder | download | duplicates (2)
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