Rename struct connection' to struct client'

It is shorter and makes more sense.  Also replaced "conn" with "c"
to keep it even more concise, and thus clearer.
This commit is contained in:
Přemysl Eric Janouch 2014-07-14 20:54:47 +02:00
parent cc4ca46cc3
commit b0cf09fb4c

View File

@ -219,11 +219,10 @@ enum
IRC_USER_MODE_RX_SERVER_NOTICES = (1 << 4)
};
// TODO: rename to client?
struct connection
struct client
{
struct connection *next; ///< The next link in a chain
struct connection *prev; ///< The previous link in a chain
struct client *next; ///< The next link in a chain
struct client *prev; ///< The previous link in a chain
struct server_context *ctx; ///< Server context
@ -249,7 +248,7 @@ struct connection
};
static void
connection_init (struct connection *self)
client_init (struct client *self)
{
memset (self, 0, sizeof *self);
@ -259,7 +258,7 @@ connection_init (struct connection *self)
}
static void
connection_free (struct connection *self)
client_free (struct client *self)
{
if (!soft_assert (self->socket_fd == -1))
xclose (self->socket_fd);
@ -351,11 +350,11 @@ struct server_context
struct str_map config; ///< Server configuration
int listen_fd; ///< Listening socket FD
struct connection *clients; ///< Client connections
struct client *clients; ///< Clients
SSL_CTX *ssl_ctx; ///< SSL context
char *server_name; ///< Our server name
struct str_map users; ///< Maps nicknames to connections
struct str_map users; ///< Maps nicknames to clients
struct str_map channels; ///< Maps channel names to data
struct str_map handlers; ///< Message handlers
@ -405,11 +404,11 @@ server_context_free (struct server_context *self)
SSL_CTX_free (self->ssl_ctx);
// TODO: terminate the connections properly before this is called
struct connection *link, *tmp;
struct client *link, *tmp;
for (link = self->clients; link; link = tmp)
{
tmp = link->next;
connection_free (link);
client_free (link);
free (link);
}
@ -436,40 +435,40 @@ enum
};
static void
connection_kill (struct connection *conn, const char *reason)
client_kill (struct client *c, const char *reason)
{
// TODO: multicast a QUIT message with `reason' || "Client exited"
(void) reason;
// TODO: do further cleanup if the client has successfully registered etc.
struct server_context *ctx = conn->ctx;
ssize_t i = poller_find_by_fd (&ctx->poller, conn->socket_fd);
struct server_context *ctx = c->ctx;
ssize_t i = poller_find_by_fd (&ctx->poller, c->socket_fd);
if (i != -1)
poller_remove_at_index (&ctx->poller, i);
xclose (conn->socket_fd);
conn->socket_fd = -1;
connection_free (conn);
LIST_UNLINK (ctx->clients, conn);
free (conn);
xclose (c->socket_fd);
c->socket_fd = -1;
client_free (c);
LIST_UNLINK (ctx->clients, c);
free (c);
}
static void
irc_send_str (struct connection *conn, const struct str *s)
irc_send_str (struct client *c, const struct str *s)
{
// TODO: kill the connection above some "SendQ" threshold (careful!)
str_append_data (&conn->write_buffer, s->str,
str_append_data (&c->write_buffer, s->str,
s->len > IRC_MAX_MESSAGE_LENGTH ? IRC_MAX_MESSAGE_LENGTH : s->len);
str_append (&conn->write_buffer, "\r\n");
str_append (&c->write_buffer, "\r\n");
}
static void irc_send (struct connection *conn,
static void irc_send (struct client *c,
const char *format, ...) ATTRIBUTE_PRINTF (2, 3);
static void
irc_send (struct connection *conn, const char *format, ...)
irc_send (struct client *c, const char *format, ...)
{
struct str tmp;
str_init (&tmp);
@ -479,7 +478,7 @@ irc_send (struct connection *conn, const char *format, ...)
str_append_vprintf (&tmp, format, ap);
va_end (ap);
irc_send_str (conn, &tmp);
irc_send_str (c, &tmp);
str_free (&tmp);
}
@ -541,7 +540,7 @@ static const char *g_default_replies[] =
// XXX: this way we cannot typecheck the arguments, so we must be careful
static void
irc_send_reply (struct connection *conn, int id, ...)
irc_send_reply (struct client *c, int id, ...)
{
struct str tmp;
str_init (&tmp);
@ -549,115 +548,112 @@ irc_send_reply (struct connection *conn, int id, ...)
va_list ap;
va_start (ap, id);
str_append_printf (&tmp, ":%s %03d %s ",
conn->ctx->server_name, id, conn->nickname ? conn->nickname : "");
c->ctx->server_name, id, c->nickname ? c->nickname : "");
str_append_vprintf (&tmp,
irc_get_text (conn->ctx, id, g_default_replies[id]), ap);
irc_get_text (c->ctx, id, g_default_replies[id]), ap);
va_end (ap);
irc_send_str (conn, &tmp);
irc_send_str (c, &tmp);
str_free (&tmp);
}
static void
irc_send_motd (struct connection *conn)
irc_send_motd (struct client *c)
{
struct server_context *ctx = conn->ctx;
struct server_context *ctx = c->ctx;
if (!ctx->motd.len)
{
irc_send_reply (conn, IRC_ERR_NOMOTD);
irc_send_reply (c, IRC_ERR_NOMOTD);
return;
}
irc_send_reply (conn, IRC_RPL_MOTDSTART, ctx->server_name);
irc_send_reply (c, IRC_RPL_MOTDSTART, ctx->server_name);
for (size_t i = 0; i < ctx->motd.len; i++)
irc_send_reply (conn, IRC_RPL_MOTD, ctx->motd.vector[i]);
irc_send_reply (conn, IRC_RPL_ENDOFMOTD);
irc_send_reply (c, IRC_RPL_MOTD, ctx->motd.vector[i]);
irc_send_reply (c, IRC_RPL_ENDOFMOTD);
}
static void
irc_try_finish_registration (struct connection *conn)
irc_try_finish_registration (struct client *c)
{
if (!conn->nickname || !conn->username || !conn->realname)
if (!c->nickname || !c->username || !c->realname)
return;
conn->registered = true;
irc_send_reply (conn, IRC_RPL_WELCOME,
conn->nickname, conn->username, conn->hostname);
c->registered = true;
irc_send_reply (c, IRC_RPL_WELCOME, c->nickname, c->username, c->hostname);
irc_send_reply (conn, IRC_RPL_YOURHOST,
conn->ctx->server_name, PROGRAM_VERSION);
irc_send_reply (c, IRC_RPL_YOURHOST, c->ctx->server_name, PROGRAM_VERSION);
// The purpose of this message eludes me
irc_send_reply (conn, IRC_RPL_CREATED, __DATE__);
irc_send_reply (conn, IRC_RPL_MYINFO,
conn->ctx->server_name, PROGRAM_VERSION,
irc_send_reply (c, IRC_RPL_CREATED, __DATE__);
irc_send_reply (c, IRC_RPL_MYINFO, c->ctx->server_name, PROGRAM_VERSION,
IRC_SUPPORTED_USER_MODES, IRC_SUPPORTED_CHAN_MODES);
// Although not strictly required, bots often need this to work
irc_send_motd (conn);
irc_send_motd (c);
}
static void
irc_handle_pass (const struct irc_message *msg, struct connection *conn)
irc_handle_pass (const struct irc_message *msg, struct client *c)
{
if (conn->registered)
irc_send_reply (conn, IRC_ERR_ALREADYREGISTERED);
if (c->registered)
irc_send_reply (c, IRC_ERR_ALREADYREGISTERED);
else if (msg->params.len < 1)
irc_send_reply (conn, IRC_ERR_NEEDMOREPARAMS, msg->command);
irc_send_reply (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
// We have SSL client certificates for this purpose; ignoring
}
static void
irc_handle_nick (const struct irc_message *msg, struct connection *conn)
irc_handle_nick (const struct irc_message *msg, struct client *c)
{
struct server_context *ctx = conn->ctx;
struct server_context *ctx = c->ctx;
if (conn->registered)
if (c->registered)
{
irc_send_reply (conn, IRC_ERR_ALREADYREGISTERED);
irc_send_reply (c, IRC_ERR_ALREADYREGISTERED);
return;
}
if (msg->params.len < 1)
{
irc_send_reply (conn, IRC_ERR_NONICKNAMEGIVEN);
irc_send_reply (c, IRC_ERR_NONICKNAMEGIVEN);
return;
}
const char *nickname = msg->params.vector[0];
if (irc_validate_nickname (nickname) != VALIDATION_OK)
{
irc_send_reply (conn, IRC_ERR_ERRONEOUSNICKNAME, nickname);
irc_send_reply (c, IRC_ERR_ERRONEOUSNICKNAME, nickname);
return;
}
if (str_map_find (&ctx->users, nickname))
{
irc_send_reply (conn, IRC_ERR_NICKNAMEINUSE, nickname);
irc_send_reply (c, IRC_ERR_NICKNAMEINUSE, nickname);
return;
}
if (conn->nickname)
if (c->nickname)
{
str_map_set (&ctx->users, conn->nickname, NULL);
free (conn->nickname);
str_map_set (&ctx->users, c->nickname, NULL);
free (c->nickname);
}
// Allocate the nickname
conn->nickname = xstrdup (nickname);
str_map_set (&ctx->users, nickname, conn);
c->nickname = xstrdup (nickname);
str_map_set (&ctx->users, nickname, c);
irc_try_finish_registration (conn);
irc_try_finish_registration (c);
}
static void
irc_handle_user (const struct irc_message *msg, struct connection *conn)
irc_handle_user (const struct irc_message *msg, struct client *c)
{
if (conn->registered)
if (c->registered)
{
irc_send_reply (conn, IRC_ERR_ALREADYREGISTERED);
irc_send_reply (c, IRC_ERR_ALREADYREGISTERED);
return;
}
if (msg->params.len < 4)
{
irc_send_reply (conn, IRC_ERR_NEEDMOREPARAMS, msg->command);
irc_send_reply (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
return;
}
@ -669,30 +665,30 @@ irc_handle_user (const struct irc_message *msg, struct connection *conn)
if (!irc_is_valid_user (username))
username = "xxx";
free (conn->username);
conn->username = xstrdup (username);
free (conn->realname);
conn->realname = xstrdup (realname);
free (c->username);
c->username = xstrdup (username);
free (c->realname);
c->realname = xstrdup (realname);
unsigned long m;
if (xstrtoul (&m, mode, 10))
{
if (m & 4) conn->mode |= IRC_USER_MODE_RX_WALLOPS;
if (m & 8) conn->mode |= IRC_USER_MODE_INVISIBLE;
if (m & 4) c->mode |= IRC_USER_MODE_RX_WALLOPS;
if (m & 8) c->mode |= IRC_USER_MODE_INVISIBLE;
}
irc_try_finish_registration (conn);
irc_try_finish_registration (c);
}
static void
irc_handle_ping (const struct irc_message *msg, struct connection *conn)
irc_handle_ping (const struct irc_message *msg, struct client *c)
{
// XXX: the RFC is pretty incomprehensible about the exact usage
if (msg->params.len < 1)
irc_send_reply (conn, IRC_ERR_NOORIGIN);
irc_send_reply (c, IRC_ERR_NOORIGIN);
else
irc_send (conn, ":%s PONG :%s",
conn->ctx->server_name, msg->params.vector[0]);
irc_send (c, ":%s PONG :%s",
c->ctx->server_name, msg->params.vector[0]);
}
// -----------------------------------------------------------------------------
@ -701,7 +697,7 @@ struct irc_command
{
const char *name;
bool requires_registration;
void (*handler) (const struct irc_message *, struct connection *);
void (*handler) (const struct irc_message *, struct client *);
};
static void
@ -730,44 +726,44 @@ irc_process_message (const struct irc_message *msg,
(void) raw;
// XXX: we may want to discard everything following a QUIT etc.
// We can set a flag within the connection object.
// We can set a flag within the client object.
// TODO: see RFC 2812 :!
struct connection *conn = user_data;
struct irc_command *cmd = str_map_find (&conn->ctx->handlers, msg->command);
struct client *c = user_data;
struct irc_command *cmd = str_map_find (&c->ctx->handlers, msg->command);
if (!cmd)
irc_send_reply (conn, IRC_ERR_UNKNOWNCOMMAND,
irc_send_reply (c, IRC_ERR_UNKNOWNCOMMAND,
"%s: Unknown command", msg->command);
else if (cmd->requires_registration && !conn->registered)
irc_send_reply (conn, IRC_ERR_NOTREGISTERED);
else if (cmd->requires_registration && !c->registered)
irc_send_reply (c, IRC_ERR_NOTREGISTERED);
else
cmd->handler (msg, conn);
cmd->handler (msg, c);
}
// --- Network I/O -------------------------------------------------------------
static bool
irc_try_read (struct connection *conn)
irc_try_read (struct client *c)
{
struct str *buf = &conn->read_buffer;
struct str *buf = &c->read_buffer;
ssize_t n_read;
while (true)
{
str_ensure_space (buf, 512);
n_read = recv (conn->socket_fd, buf->str + buf->len,
n_read = recv (c->socket_fd, buf->str + buf->len,
buf->alloc - buf->len - 1 /* null byte */, 0);
if (n_read > 0)
{
buf->str[buf->len += n_read] = '\0';
// TODO: discard characters above the 512 character limit
irc_process_buffer (buf, irc_process_message, conn);
irc_process_buffer (buf, irc_process_message, c);
continue;
}
if (n_read == 0)
{
connection_kill (conn, NULL);
client_kill (c, NULL);
return false;
}
@ -777,60 +773,60 @@ irc_try_read (struct connection *conn)
continue;
print_debug ("%s: %s: %s", __func__, "recv", strerror (errno));
connection_kill (conn, strerror (errno));
client_kill (c, strerror (errno));
return false;
}
}
static bool
irc_try_read_ssl (struct connection *conn)
irc_try_read_ssl (struct client *c)
{
if (conn->ssl_tx_want_rx)
if (c->ssl_tx_want_rx)
return true;
struct str *buf = &conn->read_buffer;
conn->ssl_rx_want_tx = false;
struct str *buf = &c->read_buffer;
c->ssl_rx_want_tx = false;
while (true)
{
str_ensure_space (buf, 512);
int n_read = SSL_read (conn->ssl, buf->str + buf->len,
int n_read = SSL_read (c->ssl, buf->str + buf->len,
buf->alloc - buf->len - 1 /* null byte */);
const char *error_info = NULL;
switch (xssl_get_error (conn->ssl, n_read, &error_info))
switch (xssl_get_error (c->ssl, n_read, &error_info))
{
case SSL_ERROR_NONE:
buf->str[buf->len += n_read] = '\0';
// TODO: discard characters above the 512 character limit
irc_process_buffer (buf, irc_process_message, conn);
irc_process_buffer (buf, irc_process_message, c);
continue;
case SSL_ERROR_ZERO_RETURN:
connection_kill (conn, NULL);
client_kill (c, NULL);
return false;
case SSL_ERROR_WANT_READ:
return true;
case SSL_ERROR_WANT_WRITE:
conn->ssl_rx_want_tx = true;
c->ssl_rx_want_tx = true;
return true;
case XSSL_ERROR_TRY_AGAIN:
continue;
default:
print_debug ("%s: %s: %s", __func__, "SSL_read", error_info);
connection_kill (conn, error_info);
client_kill (c, error_info);
return false;
}
}
}
static bool
irc_try_write (struct connection *conn)
irc_try_write (struct client *c)
{
struct str *buf = &conn->write_buffer;
struct str *buf = &c->write_buffer;
ssize_t n_written;
while (buf->len)
{
n_written = send (conn->socket_fd, buf->str, buf->len, 0);
n_written = send (c->socket_fd, buf->str, buf->len, 0);
if (n_written >= 0)
{
str_remove_slice (buf, 0, n_written);
@ -843,43 +839,43 @@ irc_try_write (struct connection *conn)
continue;
print_debug ("%s: %s: %s", __func__, "send", strerror (errno));
connection_kill (conn, strerror (errno));
client_kill (c, strerror (errno));
return false;
}
return true;
}
static bool
irc_try_write_ssl (struct connection *conn)
irc_try_write_ssl (struct client *c)
{
if (conn->ssl_rx_want_tx)
if (c->ssl_rx_want_tx)
return true;
struct str *buf = &conn->write_buffer;
conn->ssl_tx_want_rx = false;
struct str *buf = &c->write_buffer;
c->ssl_tx_want_rx = false;
while (buf->len)
{
int n_written = SSL_write (conn->ssl, buf->str, buf->len);
int n_written = SSL_write (c->ssl, buf->str, buf->len);
const char *error_info = NULL;
switch (xssl_get_error (conn->ssl, n_written, &error_info))
switch (xssl_get_error (c->ssl, n_written, &error_info))
{
case SSL_ERROR_NONE:
str_remove_slice (buf, 0, n_written);
continue;
case SSL_ERROR_ZERO_RETURN:
connection_kill (conn, NULL);
client_kill (c, NULL);
return false;
case SSL_ERROR_WANT_WRITE:
return true;
case SSL_ERROR_WANT_READ:
conn->ssl_tx_want_rx = true;
c->ssl_tx_want_rx = true;
return true;
case XSSL_ERROR_TRY_AGAIN:
continue;
default:
print_debug ("%s: %s: %s", __func__, "SSL_write", error_info);
connection_kill (conn, error_info);
client_kill (c, error_info);
return false;
}
}
@ -887,7 +883,7 @@ irc_try_write_ssl (struct connection *conn)
}
static bool
irc_autodetect_ssl (struct connection *conn)
irc_autodetect_ssl (struct client *c)
{
// Trivial SSL/TLS autodetection. The first block of data returned by
// recv() must be at least three bytes long for this to work reliably,
@ -903,7 +899,7 @@ irc_autodetect_ssl (struct connection *conn)
char buf[3];
start:
switch (recv (conn->socket_fd, buf, sizeof buf, MSG_PEEK))
switch (recv (c->socket_fd, buf, sizeof buf, MSG_PEEK))
{
case 3:
if ((buf[0] & 0x80) && buf[2] == 1)
@ -926,81 +922,81 @@ start:
}
static bool
connection_initialize_ssl (struct connection *conn)
client_initialize_ssl (struct client *c)
{
// SSL support not enabled
if (!conn->ctx->ssl_ctx)
if (!c->ctx->ssl_ctx)
return false;
conn->ssl = SSL_new (conn->ctx->ssl_ctx);
if (!conn->ssl)
c->ssl = SSL_new (c->ctx->ssl_ctx);
if (!c->ssl)
goto error_ssl_1;
if (!SSL_set_fd (conn->ssl, conn->socket_fd))
if (!SSL_set_fd (c->ssl, c->socket_fd))
goto error_ssl_2;
SSL_set_accept_state (conn->ssl);
SSL_set_accept_state (c->ssl);
return true;
error_ssl_2:
SSL_free (conn->ssl);
conn->ssl = NULL;
SSL_free (c->ssl);
c->ssl = NULL;
error_ssl_1:
// XXX: these error strings are really nasty; also there could be
// multiple errors on the OpenSSL stack.
print_debug ("%s: %s: %s", "could not initialize SSL",
conn->hostname, ERR_error_string (ERR_get_error (), NULL));
c->hostname, ERR_error_string (ERR_get_error (), NULL));
return false;
}
static void
on_irc_client_ready (const struct pollfd *pfd, void *user_data)
{
struct connection *conn = user_data;
if (!conn->initialized)
struct client *c = user_data;
if (!c->initialized)
{
hard_assert (pfd->events == POLLIN);
if (irc_autodetect_ssl (conn) && !connection_initialize_ssl (conn))
if (irc_autodetect_ssl (c) && !client_initialize_ssl (c))
{
connection_kill (conn, NULL);
client_kill (c, NULL);
return;
}
conn->initialized = true;
c->initialized = true;
}
int new_events = 0;
if (conn->ssl)
if (c->ssl)
{
// Reads may want to write, writes may want to read, poll() may
// return unexpected things in `revents'... let's try both
if (!irc_try_read_ssl (conn) || !irc_try_write_ssl (conn))
if (!irc_try_read_ssl (c) || !irc_try_write_ssl (c))
return;
new_events |= POLLIN;
if (conn->write_buffer.len || conn->ssl_rx_want_tx)
if (c->write_buffer.len || c->ssl_rx_want_tx)
new_events |= POLLOUT;
// While we're waiting for an opposite event, we ignore the original
if (conn->ssl_rx_want_tx) new_events &= ~POLLIN;
if (conn->ssl_tx_want_rx) new_events &= ~POLLOUT;
if (c->ssl_rx_want_tx) new_events &= ~POLLIN;
if (c->ssl_tx_want_rx) new_events &= ~POLLOUT;
}
else
{
if (!irc_try_read (conn) || !irc_try_write (conn))
if (!irc_try_read (c) || !irc_try_write (c))
return;
new_events |= POLLIN;
if (conn->write_buffer.len)
if (c->write_buffer.len)
new_events |= POLLOUT;
}
hard_assert (new_events != 0);
if (pfd->events != new_events)
poller_set (&conn->ctx->poller, conn->socket_fd, new_events,
(poller_dispatcher_func) on_irc_client_ready, conn);
poller_set (&c->ctx->poller, c->socket_fd, new_events,
(poller_dispatcher_func) on_irc_client_ready, c);
}
static void
on_irc_connection_available (const struct pollfd *pfd, void *user_data)
on_irc_client_available (const struct pollfd *pfd, void *user_data)
{
(void) pfd;
struct server_context *ctx = user_data;
@ -1038,16 +1034,16 @@ on_irc_connection_available (const struct pollfd *pfd, void *user_data)
print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
print_debug ("accepted connection from %s:%s", host, port);
struct connection *conn = xmalloc (sizeof *conn);
connection_init (conn);
conn->socket_fd = fd;
conn->hostname = xstrdup (host);
LIST_PREPEND (ctx->clients, conn);
struct client *c = xmalloc (sizeof *c);
client_init (c);
c->socket_fd = fd;
c->hostname = xstrdup (host);
LIST_PREPEND (ctx->clients, c);
// TODO: set a timeout on the socket, something like 3 minutes, then we
// should terminate the connection.
poller_set (&ctx->poller, conn->socket_fd, POLLIN,
(poller_dispatcher_func) on_irc_client_ready, conn);
poller_set (&ctx->poller, c->socket_fd, POLLIN,
(poller_dispatcher_func) on_irc_client_ready, c);
}
}
@ -1279,7 +1275,7 @@ irc_listen (struct server_context *ctx, struct error **e)
ctx->listen_fd = sockfd;
poller_set (&ctx->poller, ctx->listen_fd, POLLIN,
(poller_dispatcher_func) on_irc_connection_available, ctx);
(poller_dispatcher_func) on_irc_client_available, ctx);
print_status ("listening at %s:%s", real_host, real_port);
return true;