irc_conn PING/PONG code, and line_proto fixups
authorTero Marttila <terom@fixme.fi>
Sun, 01 Mar 2009 00:34:33 +0200
changeset 20 d9c4c2980a0d
parent 19 8c80580ccde9
child 21 0911d0b828d4
irc_conn PING/PONG code, and line_proto fixups
src/irc_conn.c
src/irc_conn.h
src/line_proto.c
--- a/src/irc_conn.c	Sat Feb 28 23:48:34 2009 +0200
+++ b/src/irc_conn.c	Sun Mar 01 00:34:33 2009 +0200
@@ -4,22 +4,58 @@
 #include <stdlib.h>
 #include <string.h>
 
+/*
+ * PING <server1> [ <server2> ]
+ *
+ * Send a 'PONG <server1>` reply right away.
+ */ 
+static void on_PING (struct irc_conn *conn, const struct irc_line *line)
+{
+    // just reply
+    irc_conn_PONG(conn, line->args[0]);
+}
+
+/*
+ * Our command handlers
+ */
+struct irc_cmd_handler {
+    /* The command name */
+    const char *command;
+
+    /* The handler function */
+    void (*func) (struct irc_conn *conn, const struct irc_line *line);
+
+} _cmd_handlers[] = {
+    { "PING",           on_PING             },
+    { NULL,             NULL,               },
+};
+
 void irc_conn_on_line (char *line_buf, void *arg) 
 {
+    struct irc_conn *conn = arg;
     struct irc_line line;
+    struct irc_cmd_handler *handler;
     int err;
     
     // log
     printf("<<< %s\n", line_buf);
 
     // parse
-    if ((err = irc_line_parse(&line, line_buf)))
+    if ((err = irc_line_parse(&line, line_buf))) {
         printf("!!! Invalid line: %s: %s\n", line_buf, error_name(err));
+        
+        return;
+    }
 
-    else
-        printf("\tprefix=%s, command=%s, args={%s, %s, %s, ...}\n",
-                line.prefix, line.command, line.args[0], line.args[1], line.args[2]
-        );
+    // look up appropriate handler
+    for (handler = _cmd_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);
+            break;
+        }
+    }
 }
 
 err_t irc_conn_create (struct irc_conn **conn_ptr, struct sock_stream *sock, const struct irc_conn_config *config, struct error_info *err)
@@ -64,7 +100,7 @@
 
     // send using line_proto
     // XXX: ignore output-buffering
-    return (err = line_proto_write(conn->lp, line_buf)) < 0 ? err : SUCCESS;
+    return (err = line_proto_send(conn->lp, line_buf)) < 0 ? err : SUCCESS;
 }
 
 err_t irc_conn_NICK (struct irc_conn *conn, const char *nickname)
@@ -74,7 +110,6 @@
         NULL, "NICK", { nickname, NULL }
     };
     
-    // send it
     return irc_conn_send(conn, &line);
 }
 
@@ -82,10 +117,20 @@
 {
     // USER <user> <mode> <unused> <realname>
     struct irc_line line = {
-        NULL, "USER", { username, "0", "*", realname }
+        NULL, "USER", { username, "0", "*", realname, NULL }
     };
     
-    // send it
     return irc_conn_send(conn, &line);
 }
 
+err_t irc_conn_PONG (struct irc_conn *conn, const char *target)
+{
+    // PONG <server> [ <server2> ]
+    // XXX: params are actually the wrong way around now, but nobody cares
+    struct irc_line line = {
+        NULL, "PONG", { target, NULL }
+    };
+
+    return irc_conn_send(conn, &line);
+}
+
--- a/src/irc_conn.h	Sat Feb 28 23:48:34 2009 +0200
+++ b/src/irc_conn.h	Sun Mar 01 00:34:33 2009 +0200
@@ -44,6 +44,15 @@
  */
 err_t irc_conn_send (struct irc_conn *conn, const struct irc_line *line);
 
+/**
+ * @group Simple request functions
+ *
+ * The error handling of these functions is such that the error return code is can be used or ignored as convenient,
+ * as connection-fatal errors will be handled internally.
+ *
+ * @{
+ */
+
 /*
  * Send a NICK message
  */
@@ -54,5 +63,9 @@
  */
 err_t irc_conn_USER (struct irc_conn *conn, const char *username, const char *realname);
 
+/*
+ * Send a PONG message to the given target
+ */
+err_t irc_conn_PONG (struct irc_conn *conn, const char *target);
 
 #endif /* IRC_CONN_H */
--- a/src/line_proto.c	Sat Feb 28 23:48:34 2009 +0200
+++ b/src/line_proto.c	Sun Mar 01 00:34:33 2009 +0200
@@ -95,6 +95,7 @@
 
 struct sock_stream_callbacks line_proto_sock_stream_callbacks = {
     .on_read    = &line_proto_on_read,
+    .on_write   = &line_proto_on_write,
 };
 
 err_t line_proto_create (struct line_proto **lp_ptr, struct sock_stream *sock, size_t buf_size,
@@ -121,7 +122,7 @@
             sock_stream_event_init(sock, &line_proto_sock_stream_callbacks, lp)
         ||  line_proto_schedule_events(lp, EV_READ)
     )
-        return ERROR_CODE(&lp->err);
+        JUMP_SET_ERROR_INFO(err, &lp->err);
 
     // return
     *lp_ptr = lp;
@@ -132,9 +133,13 @@
     if (lp) {
         free(lp->in_buf);
         free(lp->out_buf);
+
+        // XXX: handle sock init errors
     }
 
     free(lp);
+
+    return ERROR_CODE(err);
 }
 
 /*