--- a/src/irc_conn.c Thu Mar 12 18:08:27 2009 +0200
+++ b/src/irc_conn.c Thu Mar 12 18:11:44 2009 +0200
@@ -1,47 +1,109 @@
#include "irc_conn.h"
#include "irc_cmd.h"
+#include "irc_nm.h"
#include "log.h"
#include <stdlib.h>
#include <string.h>
-/*
- * "Welcome to the Internet Relay Network <nick>!<user>@<host>"
+/**
+ * @group Forward-declerations
+ * @{
*/
-static void on_RPL_WELCOME (struct irc_conn *conn, const struct irc_line *line, void *arg)
+
+/**
+ * Handle an event-based error on this IRC connection.
+ */
+static void irc_conn_handle_error (struct irc_conn *conn, struct error_info *err);
+
+/**
+ * Update irc_conn.nickname
+ */
+static err_t irc_conn_set_nickname (struct irc_conn *conn, const char *nickname)
{
- (void) line;
- (void) arg;
+ struct error_info err;
+
+ // strdup
+ if ((conn->nickname = strdup(nickname)) == NULL) {
+ SET_ERROR(&err, ERR_STRDUP);
+
+ // notify
+ irc_conn_handle_error(conn, &err);
+
+ return ERROR_CODE(&err);
+ }
+
+ // ok
+ return SUCCESS;
+}
+
+// @}
+
+/**
+ * 001 <nick> :Welcome to the Internet Relay Network <nick>!<user>@<host>
+ */
+static void on_RPL_WELCOME (const struct irc_line *line, void *arg)
+{
+ struct irc_conn *conn = arg;
// update state
conn->registering = false;
conn->registered = true;
+
+ // set our real nickname from the message target
+ if (irc_conn_set_nickname(conn, line->args[0]))
+ return;
// trigger callback
if (conn->callbacks.on_registered)
conn->callbacks.on_registered(conn, conn->cb_arg);
}
-/*
+/**
* PING <server1> [ <server2> ]
*
* Send a 'PONG <server1>` reply right away.
*/
-static void on_PING (struct irc_conn *conn, const struct irc_line *line, void *arg)
+static void on_PING (const struct irc_line *line, void *arg)
{
- (void) arg;
+ struct irc_conn *conn = arg;
// just reply
irc_conn_PONG(conn, line->args[0]);
}
-/*
+/**
+ * NICK <nickname>
+ *
+ * If the prefix is us, then update our nickname
+ */
+static void on_NICK (const struct irc_line *line, void *arg)
+{
+ struct irc_conn *conn = arg;
+ char nickname[IRC_NICK_MAX];
+
+ // parse nickname, ignoring errors
+ if (irc_prefix_parse_nick(line->prefix, nickname)) {
+ log_warn("invalid prefix: %s", line->prefix);
+ return;
+ }
+
+ // ignore if it's not us
+ if (irc_cmp_nick(nickname, conn->nickname))
+ return;
+
+ // update our nickname
+ irc_conn_set_nickname(conn, nickname);
+}
+
+/**
* Our command handlers
*/
-struct irc_cmd_handler _cmd_handlers[] = {
- { IRC_RPL_WELCOME, on_RPL_WELCOME },
- { "PING", on_PING },
- { NULL, NULL, },
+static struct irc_cmd_handler _cmd_handlers[] = {
+ { IRC_RPL_WELCOME, &on_RPL_WELCOME },
+ { "PING", &on_PING },
+ { "NICK", &on_NICK },
+ { NULL, NULL, },
};
/**
@@ -51,8 +113,6 @@
{
struct irc_conn *conn = arg;
struct irc_line line;
- struct irc_cmd_chain *chain;
- struct irc_cmd_handler *handler;
int err;
// log
@@ -63,21 +123,9 @@
log_warn("invalid line: %s: %s\n", line_buf, error_name(err));
return;
}
-
- // run each handler chain
- STAILQ_FOREACH(chain, &conn->handlers, node) {
- // look up appropriate handler
- for (handler = chain->handlers; handler->command; handler++) {
- // the command is alpha-only, so normal case-insensitive cmp is fine
- if (strcasecmp(handler->command, line.command) == 0) {
- // invoke the func
- handler->func(conn, &line, chain->arg);
- // ...only one per chain
- break;
- }
- }
- }
+ // invoke command handlers
+ irc_cmd_invoke(&conn->handlers, &line);
}
/**
@@ -89,8 +137,9 @@
// log
log_err_info(err, "line_proto error");
-
- // XXX: notify user
+
+ // 'handle'
+ irc_conn_handle_error(conn, err);
}
static struct line_proto_callbacks _lp_callbacks = {
@@ -98,6 +147,11 @@
.on_error = &irc_conn_on_error,
};
+static void irc_conn_handle_error (struct irc_conn *conn, struct error_info *err)
+{
+ // XXX: notify user callback
+}
+
err_t irc_conn_create (struct irc_conn **conn_ptr, struct sock_stream *sock, const struct irc_conn_callbacks *callbacks,
void *cb_arg, struct error_info *err)
{
@@ -112,10 +166,10 @@
conn->cb_arg = cb_arg;
// initialize command handlers
- STAILQ_INIT(&conn->handlers);
+ irc_cmd_init(&conn->handlers);
// add the core handlers
- if ((ERROR_CODE(err) = irc_conn_register_handler_chain(conn, _cmd_handlers, NULL)))
+ if ((ERROR_CODE(err) = irc_conn_add_cmd_handlers(conn, _cmd_handlers, conn)))
goto error;
// create the line_proto, with our on_line handler
@@ -136,44 +190,21 @@
void irc_conn_destroy (struct irc_conn *conn)
{
- struct irc_cmd_chain *next = STAILQ_FIRST(&conn->handlers);
-
// release the line_proto
if (conn->lp)
line_proto_release(conn->lp);
-
- // clean up any handler chains
- while (next) {
- struct irc_cmd_chain *node = next;
-
- // update next
- next = STAILQ_NEXT(node, node);
-
- // free
- free(node);
- }
+
+ // free the command handlers
+ irc_cmd_free(&conn->handlers);
// free the irc_conn itself
free(conn);
}
-err_t irc_conn_register_handler_chain (struct irc_conn *conn, struct irc_cmd_handler *handlers, void *arg)
+err_t irc_conn_add_cmd_handlers (struct irc_conn *conn, struct irc_cmd_handler *handlers, void *arg)
{
- struct irc_cmd_chain *item;
-
- // allocate the chain item
- if ((item = calloc(1, sizeof(*item))) == NULL)
- return ERR_CALLOC;
-
- // store
- item->handlers = handlers;
- item->arg = arg;
-
- // append
- STAILQ_INSERT_TAIL(&conn->handlers, item, node);
-
- // ok
- return SUCCESS;
+ // use the irc_cmd stuff
+ return irc_cmd_add(&conn->handlers, handlers, arg);
}
err_t irc_conn_register (struct irc_conn *conn, const struct irc_conn_register_info *info)