Crossfire Server, Trunk
loop.cpp File Reference
#include "global.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include "image.h"
#include "newserver.h"
#include "sockproto.h"
#include "sproto.h"
+ Include dependency graph for loop.cpp:

Go to the source code of this file.

Data Structures

struct  client_cmd_mapping
 
struct  player_cmd_mapping
 

Typedefs

typedef void(* func_uint8_int_ns) (char *, int, socket_struct *)
 
typedef void(* func_uint8_int_pl) (char *, int, player *)
 

Functions

void check_all_fds ()
 
bool connection_alive (const socket_struct *socket)
 
void do_server (void)
 
bool handle_client (socket_struct *ns, player *pl)
 
static int handle_cmd (socket_struct *ns, player *pl, char *cmd, char *data, int len)
 
static int is_fd_valid (int fd)
 
static void new_connection (int listen_fd)
 
void request_info_cmd (char *buf, int len, socket_struct *ns)
 
static void send_delayed_buffers (player *pl)
 
static void send_updates (player *pl)
 
void update_players ()
 

Variables

static const struct client_cmd_mapping client_commands []
 
uint32_t last_time
 
static const struct player_cmd_mapping player_commands []
 

Detailed Description

Main client/server loops.

Date
2003-12-02

Mainly deals with initialization and higher level socket maintenance (checking for lost connections and if data has arrived.) The reading of data is handled in lowlevel.c

Definition in file loop.cpp.

Typedef Documentation

◆ func_uint8_int_ns

typedef void(* func_uint8_int_ns) (char *, int, socket_struct *)

Prototype for functions the client sends without player interaction.

Definition at line 65 of file loop.cpp.

◆ func_uint8_int_pl

typedef void(* func_uint8_int_pl) (char *, int, player *)

Prototype for functions used to handle player actions.

Definition at line 74 of file loop.cpp.

Function Documentation

◆ check_all_fds()

void check_all_fds ( )

Check all file descriptors and mark sockets with invalid ones as dead. In theory this should never need to be called because sockets (and their file descriptors) are freed when the connection is dropped, but that this error handling code was added suggests that it occasionally happens and we don't want to crash the server over this.

Only run this if select() reports EBADF to avoid fcntl()'ing all of our file descriptors every time we call select.

We can just mark the bad sockets as dead so that the next call to do_server() excludes them from select() and eventually cleans them up.

Definition at line 512 of file loop.cpp.

References Socket_Info::allocated_sockets, first_player, FREE_AND_CLEAR, init_sockets, is_fd_valid(), Ns_Dead, altar_valkyrie::pl, socket_info, and socket_struct::status.

Referenced by do_server().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ connection_alive()

bool connection_alive ( const socket_struct socket)

Check whether the given socket's connection is alive or not.

Returns
True if connection is active, false if not.

Definition at line 448 of file loop.cpp.

References BEAT_INTERVAL, socket_struct::heartbeat, socket_struct::last_tick, and tick_length().

Referenced by update_players().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ do_server()

void do_server ( void  )

This checks the sockets for input and exceptions, does the right thing.

A bit of this code is grabbed out of socket.c There are 2 lists we need to look through - init_sockets is a list

Definition at line 535 of file loop.cpp.

References Socket_Info::allocated_sockets, check_all_fds(), cst_lst, final_free_player(), first_player, free_newsocket(), get_sleep_remaining(), handle_client(), init_listening_socket(), init_sockets, jump_time(), last_time, leave(), llevError, llevInfo, LOG(), MAX, Socket_Info::max_filedescriptor, CS_Stats::max_ticktime, new_connection(), give::next, Ns_Add, Ns_Avail, Ns_Dead, altar_valkyrie::pl, save_player(), send_delayed_buffers(), send_updates(), socket_info, takeitem::status, socket_struct::status, CS_Stats::ticks, CS_Stats::ticks_overtime, Socket_Info::timeout, and CS_Stats::total_ticktime.

Referenced by server_main().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ handle_client()

bool handle_client ( socket_struct ns,
player pl 
)

Handle commands from a client. This function should only be called when the socket is readable. If an error occurs, the socket status will be set to Ns_Dead; it is up to the caller to clean it up.

Parameters
nsSocket sending the command
plPlayer associated with this socket, or NULL
Returns
If the main loop should continue processing this client.

Definition at line 257 of file loop.cpp.

References SockList::buf, navar-midane_time::data, socket_struct::faces_sent, socket_struct::fd, handle_cmd(), socket_struct::inbuf, socket_struct::last_tick, SockList::len, Ns_Dead, altar_valkyrie::pl, SockList_NullTerminate(), SockList_ReadPacket(), SockList_ResetRead(), ST_PLAYING, takeitem::status, and socket_struct::status.

Referenced by do_server().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ handle_cmd()

static int handle_cmd ( socket_struct ns,
player pl,
char *  cmd,
char *  data,
int  len 
)
static

Handle a command, either directly sent by the client, or sent for a player's action.

Parameters
nssocket sending the command, must not be NULL.
plplayer associated to the socket, may be NULL.
cmdcommand name.
dataadditional data, can be NULL.
lenlength of data.
Returns
1 if cmd is a command sent for a player's action, 0 else.

Definition at line 209 of file loop.cpp.

References client_commands, client_cmd_mapping::cmdname, player_cmd_mapping::cmdname, client_cmd_mapping::cmdproc, player_cmd_mapping::cmdproc, navar-midane_time::data, player_cmd_mapping::flag, socket_struct::host, llevDebug, LOG(), altar_valkyrie::pl, player_commands, and ST_PLAYING.

Referenced by handle_client().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_fd_valid()

static int is_fd_valid ( int  fd)
static

Checks if file descriptor is valid.

Parameters
fdfile descriptor to check.
Returns
1 if fd is valid, 0 else.

Definition at line 362 of file loop.cpp.

Referenced by check_all_fds().

+ Here is the caller graph for this function:

◆ new_connection()

static void new_connection ( int  listen_fd)
static

Handle a new connection from a client.

Parameters
listen_fdfile descriptor the request came from.

Definition at line 374 of file loop.cpp.

References altar_valkyrie::accept(), Socket_Info::allocated_sockets, buf, checkbanned(), socket_struct::faces_sent, socket_struct::faces_sent_len, fatal(), socket_struct::fd, get_faces_count(), init_connection(), init_sockets, log_login::ip, socket_struct::listen, llevDebug, llevError, llevInfo, LOG(), MAX_BUF, Ns_Avail, OUT_OF_MEMORY, SEE_LAST_ERROR, socket_info, socklen_t, takeitem::status, and socket_struct::status.

Referenced by do_server().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ request_info_cmd()

void request_info_cmd ( char *  buf,
int  len,
socket_struct ns 
)

request_info_cmd is sort of a meta command. There is some specific request of information, but we call other functions to provide that information.

Parameters
bufbuffer containing the information requested.
lenlength of buf, ignored.
nssocket to write data to.

Definition at line 136 of file loop.cpp.

References buf, socket_struct::host, knowledge_send_info(), llevDebug, LOG(), roll-o-matic::params, send_class_info(), send_class_list(), send_exp_table(), send_file(), send_image_info(), send_image_sums(), send_map_info(), send_new_char_info(), send_race_info(), send_race_list(), send_skill_extra(), send_skill_info(), send_spell_paths(), Send_With_Handling(), SockList_AddString(), SockList_Init(), and SockList_Term().

+ Here is the call graph for this function:

◆ send_delayed_buffers()

static void send_delayed_buffers ( player pl)
static

Send all delayed buffers for a player.

Parameters
plplayer to send buffers for.

Definition at line 466 of file loop.cpp.

References buf, altar_valkyrie::pl, and Send_With_Handling().

Referenced by do_server().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ send_updates()

static void send_updates ( player pl)
static

Send updated stats, map, look, and inventory to the player.

Definition at line 476 of file loop.cpp.

References draw_client_map(), esrv_draw_look(), esrv_send_inventory(), esrv_update_item(), esrv_update_stats(), llevError, LOG(), altar_valkyrie::pl, UPD_WEIGHT, and WEIGHT.

Referenced by do_server(), and update_players().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_players()

void update_players ( )

Send updates to players. Called once per tick.

Definition at line 681 of file loop.cpp.

References connection_alive(), first_player, llevDebug, LOG(), give::next, altar_valkyrie::pl, send_tick(), send_updates(), and ST_PLAYING.

Referenced by server_main().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ client_commands

const struct client_cmd_mapping client_commands[]
static
Initial value:
= {
{ "addme", add_me_cmd },
{ "askface", send_face_cmd },
{ "beat", NULL },
{ "requestinfo", request_info_cmd },
{ "setup", set_up_cmd },
{ "version", version_cmd },
{ "asksmooth", ask_smooth_cmd },
{ "accountlogin", account_login_cmd },
{ "accountnew", account_new_cmd },
{ "accountaddplayer", account_add_player_cmd },
{ "accountplay", account_play_cmd },
{ "accountpw", account_password },
{ "createplayer", create_player_cmd },
{ NULL, NULL }
}

Commands sent directly by client, when connecting or when needed.

Definition at line 111 of file loop.cpp.

Referenced by handle_cmd().

◆ last_time

uint32_t last_time

Definition at line 50 of file time.cpp.

Referenced by do_server(), and log_time().

◆ player_commands

const struct player_cmd_mapping player_commands[]
static
Initial value:
= {
{ "examine", examine_cmd, 1 },
{ "apply", apply_cmd, 1 },
{ "move", move_cmd, 1 },
{ "reply", reply_cmd, 0 },
{ "lookat", look_at_cmd, 1 },
{ "inscribe", inscribe_scroll_cmd, 0 },
{ NULL, NULL, 0 }
}

Dispatch tables for the server.

CmdMapping is the dispatch table for the server, used in handle_client, which gets called when the client has input. All commands called here use the same parameter form (char *data, int len, int clientnum. We do implicit casts, because the data that is being passed is unsigned (pretty much needs to be for binary data), however, most of these treat it only as strings, so it makes things easier to cast it here instead of a bunch of times in the function itself. flag is 1 if the player must be in the playing state to issue the command, 0 if they can issue it at any time. Commands sent by the client reacting to player's actions.

Definition at line 97 of file loop.cpp.

Referenced by handle_cmd().

request_info_cmd
void request_info_cmd(char *buf, int len, socket_struct *ns)
Definition: loop.cpp:136
reply_cmd
void reply_cmd(char *buf, int len, player *pl)
Definition: request.cpp:589
mark_item_cmd
void mark_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.cpp:767
account_password
void account_password(char *buf, int len, socket_struct *ns)
Definition: request.cpp:3053
account_login_cmd
void account_login_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2186
look_at_cmd
void look_at_cmd(char *buf, int len, player *pl)
Definition: item.cpp:869
ask_smooth_cmd
void ask_smooth_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:503
account_add_player_cmd
void account_add_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2399
create_player_cmd
void create_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2633
new_player_cmd
void new_player_cmd(uint8_t *buf, int len, player *pl)
Definition: request.cpp:527
account_play_cmd
void account_play_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2528
move_cmd
void move_cmd(char *buf, int len, player *pl)
Definition: request.cpp:708
version_cmd
void version_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:651
inscribe_scroll_cmd
void inscribe_scroll_cmd(char *buf, int len, player *pl)
Definition: item.cpp:964
examine_cmd
void examine_cmd(char *buf, int len, player *pl)
Definition: item.cpp:646
account_new_cmd
void account_new_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2285
lock_item_cmd
void lock_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.cpp:708
set_up_cmd
void set_up_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:143
add_me_cmd
void add_me_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:415
apply_cmd
void apply_cmd(char *buf, int len, player *pl)
Definition: item.cpp:668
func_uint8_int_pl
void(* func_uint8_int_pl)(char *, int, player *)
Definition: loop.cpp:74
send_face_cmd
void send_face_cmd(char *buff, int len, socket_struct *ns)
Definition: image.cpp:45