Index: trunk/src_3rd/libuirc/Makefile =================================================================== --- trunk/src_3rd/libuirc/Makefile (nonexistent) +++ trunk/src_3rd/libuirc/Makefile (revision 31373) @@ -0,0 +1,8 @@ +CFLAGS = -Wall -g +LDLIBS = -lporty_net libgenvector.a + +main: main.o libuirc.o + +main.o: main.c + +libuirc.o: libuirc.c libuirc.h Index: trunk/src_3rd/libuirc/libuirc.c =================================================================== --- trunk/src_3rd/libuirc/libuirc.c (nonexistent) +++ trunk/src_3rd/libuirc/libuirc.c (revision 31373) @@ -0,0 +1,385 @@ +#include "libuirc.h" +#include +#include + +#include + +static int uirc_query_alloc(uirc_t *ctx) +{ + int n; + for(n = 0; n < UIRC_MAX_QUERIES; n++) + if (ctx->query[n].type == UIRC_UNUSED) + return n; + return -1; +} + +static int uirc_query_search(uirc_t *ctx, char *name) +{ + int n; + for(n = 0; n < UIRC_MAX_QUERIES; n++) { + if ((ctx->query[n].type != UIRC_CHAN) && (ctx->query[n].type != UIRC_PRIV)) + continue; + if (strcmp(name, ctx->query[n].name) == 0) + return n; + } + return -1; +} + + +int uirc_connect(uirc_t *ctx, const char *server, int port, char *user) +{ + if (P_tcp4_connect(&ctx->sk, server, port, NULL, 0, P_net_nonblock_full) != 0) + return -1; + ctx->connecting = 1; + ctx->alive = 1; + gds_init(&ctx->ibuf); + gds_init(&ctx->obuf); + gds_append_str(&ctx->obuf, "user libuirc a b :"); + gds_append_str(&ctx->obuf, user); + gds_append_str(&ctx->obuf, "\nnick "); + gds_append_str(&ctx->obuf, ctx->nick); + gds_append(&ctx->obuf, '\n'); + + ctx->query[0].type = UIRC_SERVER; + ctx->query[0].name = NULL; + + return 0; +} + +void uirc_disconnect(uirc_t *ctx) +{ + P_net_close(ctx->sk); + ctx->alive = 0; +} + + +static uirc_event_t uirc_parse_001(uirc_t *ctx, char *arg) +{ +/*:hu.irc.libgpmi.org 001 libuirc :Welcome to the Internet Relay Network libuirc!~libuirc@78-131-56-146.static.hdsnet.hu*/ + if (ctx->on_connect != NULL) + ctx->on_connect(ctx); + return UIRC_CONNECT; +} + +#define irc_strcasecmp strcasecmp + +static uirc_event_t uirc_parse_join(uirc_t *ctx, char *nick, char *arg) +{ + int q; +/*:libuirc!~libuirc@78-131-56-146.static.hdsnet.hu JOIN :#dev*/ + + if (*arg == ':') arg++; + + q = uirc_query_search(ctx, arg); + if (irc_strcasecmp(nick, ctx->nick) == 0) { + uirc_event_t res = 0; + if (q < 0) { + q = uirc_query_alloc(ctx); + if (q < 0) { + gds_append_str(&ctx->obuf, "part "); + gds_append_str(&ctx->obuf, arg); + gds_append_str(&ctx->obuf, " :I am on too many channels already.\n"); + return 0; + } + ctx->query[q].type = UIRC_CHAN; + ctx->query[q].name = strdup(arg); + ctx->last_new_query = q; + res |= UIRC_QUERY_BEGIN; + } + + if (ctx->on_me_join != NULL) + ctx->on_me_join(ctx, q, arg); + return res | UIRC_ME_JOIN; + } + + if ((q >= 0) && (ctx->on_join != NULL)) { + ctx->on_join(ctx, nick, q, arg); + return UIRC_JOIN; + } + + return 0; +} + +#define payload(dst, src) \ +do { \ + dst = strpbrk(src, " \t"); \ + if (dst != NULL) { \ + *dst++ = '\0'; \ + if (*dst == ':') dst++; \ + } \ +} while(0) + +static uirc_event_t uirc_parse_part(uirc_t *ctx, char *nick, char *arg) +{ + char *reason; + int q; + + if (*arg == ':') arg++; + payload(reason, arg); + + q = uirc_query_search(ctx, arg); + if (q < 0) + return 0; + + if (irc_strcasecmp(nick, ctx->nick) == 0) { + if (ctx->on_me_part != NULL) + ctx->on_me_part(ctx, q, arg); + if (ctx->on_query_end != NULL) + ctx->on_query_end(ctx, q); + ctx->query[q].type = UIRC_UNUSED; + free(ctx->query[q].name); + ctx->query[q].name = NULL; + return UIRC_ME_PART | UIRC_QUERY_END; + } + + if (ctx->on_part != NULL) { + ctx->on_part(ctx, nick, q, arg, reason); + return UIRC_PART; + } + + return 0; +} + +static uirc_event_t uirc_parse_kick(uirc_t *ctx, char *nick, char *arg) +{ + char *victim, *reason; + int q; + + payload(victim, arg); + payload(reason, victim); + + q = uirc_query_search(ctx, arg); + if (q < 0) + return 0; + + if (irc_strcasecmp(victim, ctx->nick) == 0) { + if (ctx->on_me_part != NULL) + ctx->on_me_part(ctx, q, arg); + if (ctx->on_query_end != NULL) + ctx->on_query_end(ctx, q); + ctx->query[q].type = UIRC_UNUSED; + free(ctx->query[q].name); + ctx->query[q].name = NULL; + return UIRC_ME_PART | UIRC_QUERY_END; + } + + if (ctx->on_kick != NULL) { + ctx->on_kick(ctx, nick, q, arg, victim, reason); + return UIRC_KICK; + } + + return 0; +} + +static uirc_event_t uirc_parse_msg(uirc_t *ctx, char *nick, char *arg) +{ + char *text; + int q; + + if (*arg == ':') arg++; + payload(text, arg); + + q = uirc_query_search(ctx, arg); + + if (ctx->on_msg != NULL) { + ctx->on_msg(ctx, nick, q, arg, text); + return UIRC_MSG; + } + + return 0; +} + +static uirc_event_t uirc_parse_notice(uirc_t *ctx, char *nick, char *arg) +{ + char *text; + int q; + + if (*arg == ':') arg++; + payload(text, arg); + + q = uirc_query_search(ctx, arg); + + if (ctx->on_notice != NULL) { + ctx->on_notice(ctx, nick, q, arg, text); + return UIRC_NOTICE; + } + + return 0; +} + +static uirc_event_t uirc_parse_topic(uirc_t *ctx, char *nick, char *arg, int numeric) +{ + char *text; + int q; + + if (*arg == ':') arg++; + payload(text, arg); + + q = uirc_query_search(ctx, arg); + + if (ctx->on_topic != NULL) { + if (numeric) + nick = NULL; + ctx->on_topic(ctx, nick, q, arg, text); + return UIRC_TOPIC; + } + + return 0; +} + + +static uirc_event_t uirc_parse(uirc_t *ctx, char *line) +{ + char *end, *arg, *cmd, *from = line; + uirc_event_t res = 0; + +printf("line='%s'\n", line); + + if (strncmp(line, "PING", 4) == 0) { + from[1] = 'O'; + uirc_raw(ctx, line); + return 0; + } + + cmd = strpbrk(line, " \t\r\n"); + if (cmd == NULL) + return 0; + *cmd = '\0'; + cmd++; + + if (strchr(from, '@') == 0) { + if (ctx->on_got_misc != NULL) + ctx->on_got_misc(ctx, 0, cmd); + res |= UIRC_GOT_MISC; + } + + end = strchr(from, '!'); + if (end != NULL) { + if (*from == ':') + from++; + *end = 0; + } + + arg = strpbrk(cmd, " \t\r\n"); + if (arg != NULL) { + *arg = '\0'; + arg++; + } + + end = strpbrk(arg, "\r\n"); + if (end != NULL) + *end = '\0'; + + if (strcmp(cmd, "001") == 0) return res | uirc_parse_001(ctx, arg); + if (strcasecmp(cmd, "join") == 0) return res | uirc_parse_join(ctx, from, arg); + if (strcasecmp(cmd, "part") == 0) return res | uirc_parse_part(ctx, from, arg); + if (strcasecmp(cmd, "kick") == 0) return res | uirc_parse_kick(ctx, from, arg); + if (strcasecmp(cmd, "privmsg") == 0) return res | uirc_parse_msg(ctx, from, arg); + if (strcasecmp(cmd, "notice") == 0) return res | uirc_parse_notice(ctx, from, arg); + if (strcasecmp(cmd, "topic") == 0) return res | uirc_parse_topic(ctx, from, arg, 0); + if (strcasecmp(cmd, "332") == 0) return res | uirc_parse_topic(ctx, from, arg, 1); + + return res; +} + +uirc_event_t uirc_poll(uirc_t *ctx) +{ + struct P_pollfd fds[1]; + int new_data = 0; + char *nl; + uirc_event_t res = 0; + + fds[0].fd = ctx->sk; + + for(;;) { + fds[0].events = P_POLLIN; + if (ctx->obuf.used > 0) + fds[0].events |= P_POLLOUT; + + if (P_poll(fds, 1, 0) < 1) + break; + + if (fds[0].revents & P_POLLIN) { + P_size_t oused = ctx->ibuf.used; + gds_enlarge(&ctx->ibuf, ctx->ibuf.used + 600); + ctx->ibuf.used = oused; + P_size_t len = P_net_read(ctx->sk, ctx->ibuf.array + ctx->ibuf.used, 600); + if (len < 0) { + if (P_net_inprogress) + continue; + uirc_disconnect(ctx); + return res | UIRC_DISCONNECT; + } + if (len == 0) { + uirc_disconnect(ctx); + return res | UIRC_DISCONNECT; + } + if (len > 0) { + ctx->ibuf.used += len; + new_data = 1; + } + } + if ((fds[0].revents & P_POLLOUT) && (ctx->obuf.used > 0)) { + P_size_t len = P_net_write(ctx->sk, ctx->obuf.array, ctx->obuf.used); + ctx->connecting = 0; + if (len < 0) { + if (P_net_inprogress) + continue; + uirc_disconnect(ctx); + return res | UIRC_DISCONNECT; + } + if (len == 0) { + uirc_disconnect(ctx); + return res | UIRC_DISCONNECT; + } + if (len > 0) + gds_remove(&ctx->obuf, 0, len); + } + if (fds[0].revents & (~(P_POLLIN | P_POLLOUT))) { + uirc_disconnect(ctx); + return res | UIRC_DISCONNECT; + } + } + + /* call the protocol parse */ + if (!new_data) + return res; + + for(;;) { + nl = strchr(ctx->ibuf.array, '\n'); + if (nl == NULL) + break; + *nl = '\0'; + res |= uirc_parse(ctx, ctx->ibuf.array); + gds_remove(&ctx->ibuf, 0, nl - ctx->ibuf.array+1); + } + return res; +} + + +void uirc_join(uirc_t *ctx, const char *chan) +{ + +} + +void uirc_close(uirc_t *ctx, int query) +{ + +} + +void uirc_privmsg(uirc_t *ctx, const char *target, const char *msg) +{ + gds_append_str(&ctx->obuf, "PRIVMSG "); + gds_append_str(&ctx->obuf, target); + gds_append_str(&ctx->obuf, " :"); + gds_append_str(&ctx->obuf, (char *)msg); + gds_append(&ctx->obuf, '\n'); +} + +void uirc_raw(uirc_t *ctx, const char *msg) +{ + gds_append_str(&ctx->obuf, (char *)msg); + gds_append(&ctx->obuf, '\n'); +} + + Index: trunk/src_3rd/libuirc/libuirc.h =================================================================== --- trunk/src_3rd/libuirc/libuirc.h (nonexistent) +++ trunk/src_3rd/libuirc/libuirc.h (revision 31373) @@ -0,0 +1,79 @@ +#include +#include + +#define UIRC_MAX_QUERIES 16 + +typedef enum { + UIRC_UNUSED = 0, + UIRC_SERVER, + UIRC_CHAN, + UIRC_PRIV +} uirc_query_type_t; + +typedef struct { + uirc_query_type_t type; + char *name; + +#if 0 + /* channel: */ + gds_t *nicks; /* , separated list of nicknames for a channel; first char is one of @, + or space */ + char *topic; +#endif +} uirc_query_t; + +typedef enum { /* bitfield */ + UIRC_CONNECT = 0x0001, + UIRC_DISCONNECT = 0x0002, + UIRC_TOPIC = 0x0004, + UIRC_GOT_MISC = 0x0008, + UIRC_QUERY_BEGIN = 0x0010, + UIRC_QUERY_END = 0x0020, + UIRC_ME_QUIT = 0x0040, + UIRC_ME_JOIN = 0x0080, + UIRC_JOIN = 0x0100, + UIRC_ME_PART = 0x0200, + UIRC_PART = 0x0400, + UIRC_MSG = 0x0800, + UIRC_NOTICE = 0x1000, + UIRC_KICK = 0x2000, +} uirc_event_t; + +typedef struct uirc_s uirc_t; +struct uirc_s { + char *nick; + uirc_query_t query[UIRC_MAX_QUERIES]; /* query 0 is special: server "window" */ + int curr_query, last_new_query; + + void *user_data; + void (*on_connect)(uirc_t *ctx); + void (*on_disconnect)(uirc_t *ctx); + void (*on_got_misc)(uirc_t *ctx, int query_to, const char *msg); + void (*on_query_begin)(uirc_t *ctx, int query_to); + void (*on_query_end)(uirc_t *ctx, int query_to); /* called on leaving the channel for any reason */ + void (*on_me_quit)(uirc_t *ctx); + void (*on_me_join)(uirc_t *ctx, int query, char *chan); + void (*on_join)(uirc_t *ctx, char *nick, int query, char *chan); + void (*on_me_part)(uirc_t *ctx, int query, char *chan); + void (*on_part)(uirc_t *ctx, char *nick, int query, char *chan, char *reason); + void (*on_kick)(uirc_t *ctx, char *nick, int query, char *chan, char *victim, char *reason); + void (*on_msg)(uirc_t *ctx, char *from, int query, char *to, char *text); + void (*on_notice)(uirc_t *ctx, char *from, int query, char *to, char *text); + void (*on_topic)(uirc_t *ctx, char *from, int query, char *to, char *text); + + /* internal */ + P_net_socket sk; + gds_t ibuf, obuf; + int dummy[2]; + unsigned connecting:1; + unsigned alive:1; +}; + +int uirc_connect(uirc_t *ctx, const char *server, int port, char *user); +void uirc_disconnect(uirc_t *ctx); +uirc_event_t uirc_poll(uirc_t *ctx); + +void uirc_join(uirc_t *ctx, const char *chan); +void uirc_close(uirc_t *ctx, int query); +void uirc_privmsg(uirc_t *ctx, const char *target, const char *msg); +void uirc_raw(uirc_t *ctx, const char *msg); + Index: trunk/src_3rd/libuirc/main.c =================================================================== --- trunk/src_3rd/libuirc/main.c (nonexistent) +++ trunk/src_3rd/libuirc/main.c (revision 31373) @@ -0,0 +1,87 @@ +#include +#include +#include +#include "libuirc.h" + +static void on_me_part(uirc_t *ctx, int query, char *chan) +{ + printf("### left channel %s\n", chan); +} + +static void on_msg(uirc_t *ctx, char *from, int query, char *to, char *text) +{ + printf("(msg:%s) <%s> %s\n", to, from, text); +} + +static void on_notice(uirc_t *ctx, char *from, int query, char *to, char *text) +{ + printf("(msg:%s) -%s- %s\n", to, from, text); +} + + +static void on_topic(uirc_t *ctx, char *from, int query, char *to, char *text) +{ + printf("(by:%s) [%s] topic=%s\n", from, to, text); +} + +static void on_kick(uirc_t *ctx, char *nick, int query, char *chan, char *victim, char *reason) +{ + printf("(kick: %s kick %s from %s reason=%s\n", nick, victim, chan, reason); +} + + +static void read_stdin(uirc_t *ctx) +{ + struct P_pollfd fds[1]; + + fds[0].fd = 0; + fds[0].events = P_POLLIN; + + if (P_poll(fds, 1, 0) == 1) { + char line[600]; + fgets(line, sizeof(line), stdin); + if (*line == '/') { + uirc_raw(ctx, line+1); + } + else { + if (ctx->query[ctx->curr_query].name != NULL) + uirc_privmsg(ctx, ctx->query[ctx->curr_query].name, line); + } + } +} + +int main() +{ + uirc_t irc; + + memset(&irc, 0, sizeof(irc)); + irc.on_me_part = on_me_part; + irc.on_msg = on_msg; + irc.on_notice = on_notice; + irc.on_topic = on_topic; + irc.on_kick = on_kick; + + irc.nick = strdup("libuirc"); + if (uirc_connect(&irc, "10.0.0.2", 6667, "libuirc test client") != 0) { + printf("Failed to connect.\n"); + return 1; + } + + for(;irc.alive;) { + uirc_event_t ev = uirc_poll(&irc); + if (ev & UIRC_CONNECT) { + printf("joining\n"); + uirc_raw(&irc, "join :#dev"); + } + if (ev & UIRC_QUERY_BEGIN) { + irc.curr_query = irc.last_new_query; + printf("### begin query with %s\n", irc.query[irc.curr_query].name); + } + + read_stdin(&irc); + usleep(100); + } + + return 0; +} + Index: work/net/libuirc/libuirc.h =================================================================== --- work/net/libuirc/libuirc.h (revision 31372) +++ work/net/libuirc/libuirc.h (nonexistent) @@ -1,79 +0,0 @@ -#include -#include - -#define UIRC_MAX_QUERIES 16 - -typedef enum { - UIRC_UNUSED = 0, - UIRC_SERVER, - UIRC_CHAN, - UIRC_PRIV -} uirc_query_type_t; - -typedef struct { - uirc_query_type_t type; - char *name; - -#if 0 - /* channel: */ - gds_t *nicks; /* , separated list of nicknames for a channel; first char is one of @, + or space */ - char *topic; -#endif -} uirc_query_t; - -typedef enum { /* bitfield */ - UIRC_CONNECT = 0x0001, - UIRC_DISCONNECT = 0x0002, - UIRC_TOPIC = 0x0004, - UIRC_GOT_MISC = 0x0008, - UIRC_QUERY_BEGIN = 0x0010, - UIRC_QUERY_END = 0x0020, - UIRC_ME_QUIT = 0x0040, - UIRC_ME_JOIN = 0x0080, - UIRC_JOIN = 0x0100, - UIRC_ME_PART = 0x0200, - UIRC_PART = 0x0400, - UIRC_MSG = 0x0800, - UIRC_NOTICE = 0x1000, - UIRC_KICK = 0x2000, -} uirc_event_t; - -typedef struct uirc_s uirc_t; -struct uirc_s { - char *nick; - uirc_query_t query[UIRC_MAX_QUERIES]; /* query 0 is special: server "window" */ - int curr_query, last_new_query; - - void *user_data; - void (*on_connect)(uirc_t *ctx); - void (*on_disconnect)(uirc_t *ctx); - void (*on_got_misc)(uirc_t *ctx, int query_to, const char *msg); - void (*on_query_begin)(uirc_t *ctx, int query_to); - void (*on_query_end)(uirc_t *ctx, int query_to); /* called on leaving the channel for any reason */ - void (*on_me_quit)(uirc_t *ctx); - void (*on_me_join)(uirc_t *ctx, int query, char *chan); - void (*on_join)(uirc_t *ctx, char *nick, int query, char *chan); - void (*on_me_part)(uirc_t *ctx, int query, char *chan); - void (*on_part)(uirc_t *ctx, char *nick, int query, char *chan, char *reason); - void (*on_kick)(uirc_t *ctx, char *nick, int query, char *chan, char *victim, char *reason); - void (*on_msg)(uirc_t *ctx, char *from, int query, char *to, char *text); - void (*on_notice)(uirc_t *ctx, char *from, int query, char *to, char *text); - void (*on_topic)(uirc_t *ctx, char *from, int query, char *to, char *text); - - /* internal */ - P_net_socket sk; - gds_t ibuf, obuf; - int dummy[2]; - unsigned connecting:1; - unsigned alive:1; -}; - -int uirc_connect(uirc_t *ctx, const char *server, int port, char *user); -void uirc_disconnect(uirc_t *ctx); -uirc_event_t uirc_poll(uirc_t *ctx); - -void uirc_join(uirc_t *ctx, const char *chan); -void uirc_close(uirc_t *ctx, int query); -void uirc_privmsg(uirc_t *ctx, const char *target, const char *msg); -void uirc_raw(uirc_t *ctx, const char *msg); - Index: work/net/libuirc/main.c =================================================================== --- work/net/libuirc/main.c (revision 31372) +++ work/net/libuirc/main.c (nonexistent) @@ -1,87 +0,0 @@ -#include -#include -#include -#include "libuirc.h" - -static void on_me_part(uirc_t *ctx, int query, char *chan) -{ - printf("### left channel %s\n", chan); -} - -static void on_msg(uirc_t *ctx, char *from, int query, char *to, char *text) -{ - printf("(msg:%s) <%s> %s\n", to, from, text); -} - -static void on_notice(uirc_t *ctx, char *from, int query, char *to, char *text) -{ - printf("(msg:%s) -%s- %s\n", to, from, text); -} - - -static void on_topic(uirc_t *ctx, char *from, int query, char *to, char *text) -{ - printf("(by:%s) [%s] topic=%s\n", from, to, text); -} - -static void on_kick(uirc_t *ctx, char *nick, int query, char *chan, char *victim, char *reason) -{ - printf("(kick: %s kick %s from %s reason=%s\n", nick, victim, chan, reason); -} - - -static void read_stdin(uirc_t *ctx) -{ - struct P_pollfd fds[1]; - - fds[0].fd = 0; - fds[0].events = P_POLLIN; - - if (P_poll(fds, 1, 0) == 1) { - char line[600]; - fgets(line, sizeof(line), stdin); - if (*line == '/') { - uirc_raw(ctx, line+1); - } - else { - if (ctx->query[ctx->curr_query].name != NULL) - uirc_privmsg(ctx, ctx->query[ctx->curr_query].name, line); - } - } -} - -int main() -{ - uirc_t irc; - - memset(&irc, 0, sizeof(irc)); - irc.on_me_part = on_me_part; - irc.on_msg = on_msg; - irc.on_notice = on_notice; - irc.on_topic = on_topic; - irc.on_kick = on_kick; - - irc.nick = strdup("libuirc"); - if (uirc_connect(&irc, "10.0.0.2", 6667, "libuirc test client") != 0) { - printf("Failed to connect.\n"); - return 1; - } - - for(;irc.alive;) { - uirc_event_t ev = uirc_poll(&irc); - if (ev & UIRC_CONNECT) { - printf("joining\n"); - uirc_raw(&irc, "join :#dev"); - } - if (ev & UIRC_QUERY_BEGIN) { - irc.curr_query = irc.last_new_query; - printf("### begin query with %s\n", irc.query[irc.curr_query].name); - } - - read_stdin(&irc); - usleep(100); - } - - return 0; -} - Index: work/net/libuirc/libuirc.c =================================================================== --- work/net/libuirc/libuirc.c (revision 31372) +++ work/net/libuirc/libuirc.c (nonexistent) @@ -1,385 +0,0 @@ -#include "libuirc.h" -#include -#include - -#include - -static int uirc_query_alloc(uirc_t *ctx) -{ - int n; - for(n = 0; n < UIRC_MAX_QUERIES; n++) - if (ctx->query[n].type == UIRC_UNUSED) - return n; - return -1; -} - -static int uirc_query_search(uirc_t *ctx, char *name) -{ - int n; - for(n = 0; n < UIRC_MAX_QUERIES; n++) { - if ((ctx->query[n].type != UIRC_CHAN) && (ctx->query[n].type != UIRC_PRIV)) - continue; - if (strcmp(name, ctx->query[n].name) == 0) - return n; - } - return -1; -} - - -int uirc_connect(uirc_t *ctx, const char *server, int port, char *user) -{ - if (P_tcp4_connect(&ctx->sk, server, port, NULL, 0, P_net_nonblock_full) != 0) - return -1; - ctx->connecting = 1; - ctx->alive = 1; - gds_init(&ctx->ibuf); - gds_init(&ctx->obuf); - gds_append_str(&ctx->obuf, "user libuirc a b :"); - gds_append_str(&ctx->obuf, user); - gds_append_str(&ctx->obuf, "\nnick "); - gds_append_str(&ctx->obuf, ctx->nick); - gds_append(&ctx->obuf, '\n'); - - ctx->query[0].type = UIRC_SERVER; - ctx->query[0].name = NULL; - - return 0; -} - -void uirc_disconnect(uirc_t *ctx) -{ - P_net_close(ctx->sk); - ctx->alive = 0; -} - - -static uirc_event_t uirc_parse_001(uirc_t *ctx, char *arg) -{ -/*:hu.irc.libgpmi.org 001 libuirc :Welcome to the Internet Relay Network libuirc!~libuirc@78-131-56-146.static.hdsnet.hu*/ - if (ctx->on_connect != NULL) - ctx->on_connect(ctx); - return UIRC_CONNECT; -} - -#define irc_strcasecmp strcasecmp - -static uirc_event_t uirc_parse_join(uirc_t *ctx, char *nick, char *arg) -{ - int q; -/*:libuirc!~libuirc@78-131-56-146.static.hdsnet.hu JOIN :#dev*/ - - if (*arg == ':') arg++; - - q = uirc_query_search(ctx, arg); - if (irc_strcasecmp(nick, ctx->nick) == 0) { - uirc_event_t res = 0; - if (q < 0) { - q = uirc_query_alloc(ctx); - if (q < 0) { - gds_append_str(&ctx->obuf, "part "); - gds_append_str(&ctx->obuf, arg); - gds_append_str(&ctx->obuf, " :I am on too many channels already.\n"); - return 0; - } - ctx->query[q].type = UIRC_CHAN; - ctx->query[q].name = strdup(arg); - ctx->last_new_query = q; - res |= UIRC_QUERY_BEGIN; - } - - if (ctx->on_me_join != NULL) - ctx->on_me_join(ctx, q, arg); - return res | UIRC_ME_JOIN; - } - - if ((q >= 0) && (ctx->on_join != NULL)) { - ctx->on_join(ctx, nick, q, arg); - return UIRC_JOIN; - } - - return 0; -} - -#define payload(dst, src) \ -do { \ - dst = strpbrk(src, " \t"); \ - if (dst != NULL) { \ - *dst++ = '\0'; \ - if (*dst == ':') dst++; \ - } \ -} while(0) - -static uirc_event_t uirc_parse_part(uirc_t *ctx, char *nick, char *arg) -{ - char *reason; - int q; - - if (*arg == ':') arg++; - payload(reason, arg); - - q = uirc_query_search(ctx, arg); - if (q < 0) - return 0; - - if (irc_strcasecmp(nick, ctx->nick) == 0) { - if (ctx->on_me_part != NULL) - ctx->on_me_part(ctx, q, arg); - if (ctx->on_query_end != NULL) - ctx->on_query_end(ctx, q); - ctx->query[q].type = UIRC_UNUSED; - free(ctx->query[q].name); - ctx->query[q].name = NULL; - return UIRC_ME_PART | UIRC_QUERY_END; - } - - if (ctx->on_part != NULL) { - ctx->on_part(ctx, nick, q, arg, reason); - return UIRC_PART; - } - - return 0; -} - -static uirc_event_t uirc_parse_kick(uirc_t *ctx, char *nick, char *arg) -{ - char *victim, *reason; - int q; - - payload(victim, arg); - payload(reason, victim); - - q = uirc_query_search(ctx, arg); - if (q < 0) - return 0; - - if (irc_strcasecmp(victim, ctx->nick) == 0) { - if (ctx->on_me_part != NULL) - ctx->on_me_part(ctx, q, arg); - if (ctx->on_query_end != NULL) - ctx->on_query_end(ctx, q); - ctx->query[q].type = UIRC_UNUSED; - free(ctx->query[q].name); - ctx->query[q].name = NULL; - return UIRC_ME_PART | UIRC_QUERY_END; - } - - if (ctx->on_kick != NULL) { - ctx->on_kick(ctx, nick, q, arg, victim, reason); - return UIRC_KICK; - } - - return 0; -} - -static uirc_event_t uirc_parse_msg(uirc_t *ctx, char *nick, char *arg) -{ - char *text; - int q; - - if (*arg == ':') arg++; - payload(text, arg); - - q = uirc_query_search(ctx, arg); - - if (ctx->on_msg != NULL) { - ctx->on_msg(ctx, nick, q, arg, text); - return UIRC_MSG; - } - - return 0; -} - -static uirc_event_t uirc_parse_notice(uirc_t *ctx, char *nick, char *arg) -{ - char *text; - int q; - - if (*arg == ':') arg++; - payload(text, arg); - - q = uirc_query_search(ctx, arg); - - if (ctx->on_notice != NULL) { - ctx->on_notice(ctx, nick, q, arg, text); - return UIRC_NOTICE; - } - - return 0; -} - -static uirc_event_t uirc_parse_topic(uirc_t *ctx, char *nick, char *arg, int numeric) -{ - char *text; - int q; - - if (*arg == ':') arg++; - payload(text, arg); - - q = uirc_query_search(ctx, arg); - - if (ctx->on_topic != NULL) { - if (numeric) - nick = NULL; - ctx->on_topic(ctx, nick, q, arg, text); - return UIRC_TOPIC; - } - - return 0; -} - - -static uirc_event_t uirc_parse(uirc_t *ctx, char *line) -{ - char *end, *arg, *cmd, *from = line; - uirc_event_t res = 0; - -printf("line='%s'\n", line); - - if (strncmp(line, "PING", 4) == 0) { - from[1] = 'O'; - uirc_raw(ctx, line); - return 0; - } - - cmd = strpbrk(line, " \t\r\n"); - if (cmd == NULL) - return 0; - *cmd = '\0'; - cmd++; - - if (strchr(from, '@') == 0) { - if (ctx->on_got_misc != NULL) - ctx->on_got_misc(ctx, 0, cmd); - res |= UIRC_GOT_MISC; - } - - end = strchr(from, '!'); - if (end != NULL) { - if (*from == ':') - from++; - *end = 0; - } - - arg = strpbrk(cmd, " \t\r\n"); - if (arg != NULL) { - *arg = '\0'; - arg++; - } - - end = strpbrk(arg, "\r\n"); - if (end != NULL) - *end = '\0'; - - if (strcmp(cmd, "001") == 0) return res | uirc_parse_001(ctx, arg); - if (strcasecmp(cmd, "join") == 0) return res | uirc_parse_join(ctx, from, arg); - if (strcasecmp(cmd, "part") == 0) return res | uirc_parse_part(ctx, from, arg); - if (strcasecmp(cmd, "kick") == 0) return res | uirc_parse_kick(ctx, from, arg); - if (strcasecmp(cmd, "privmsg") == 0) return res | uirc_parse_msg(ctx, from, arg); - if (strcasecmp(cmd, "notice") == 0) return res | uirc_parse_notice(ctx, from, arg); - if (strcasecmp(cmd, "topic") == 0) return res | uirc_parse_topic(ctx, from, arg, 0); - if (strcasecmp(cmd, "332") == 0) return res | uirc_parse_topic(ctx, from, arg, 1); - - return res; -} - -uirc_event_t uirc_poll(uirc_t *ctx) -{ - struct P_pollfd fds[1]; - int new_data = 0; - char *nl; - uirc_event_t res = 0; - - fds[0].fd = ctx->sk; - - for(;;) { - fds[0].events = P_POLLIN; - if (ctx->obuf.used > 0) - fds[0].events |= P_POLLOUT; - - if (P_poll(fds, 1, 0) < 1) - break; - - if (fds[0].revents & P_POLLIN) { - P_size_t oused = ctx->ibuf.used; - gds_enlarge(&ctx->ibuf, ctx->ibuf.used + 600); - ctx->ibuf.used = oused; - P_size_t len = P_net_read(ctx->sk, ctx->ibuf.array + ctx->ibuf.used, 600); - if (len < 0) { - if (P_net_inprogress) - continue; - uirc_disconnect(ctx); - return res | UIRC_DISCONNECT; - } - if (len == 0) { - uirc_disconnect(ctx); - return res | UIRC_DISCONNECT; - } - if (len > 0) { - ctx->ibuf.used += len; - new_data = 1; - } - } - if ((fds[0].revents & P_POLLOUT) && (ctx->obuf.used > 0)) { - P_size_t len = P_net_write(ctx->sk, ctx->obuf.array, ctx->obuf.used); - ctx->connecting = 0; - if (len < 0) { - if (P_net_inprogress) - continue; - uirc_disconnect(ctx); - return res | UIRC_DISCONNECT; - } - if (len == 0) { - uirc_disconnect(ctx); - return res | UIRC_DISCONNECT; - } - if (len > 0) - gds_remove(&ctx->obuf, 0, len); - } - if (fds[0].revents & (~(P_POLLIN | P_POLLOUT))) { - uirc_disconnect(ctx); - return res | UIRC_DISCONNECT; - } - } - - /* call the protocol parse */ - if (!new_data) - return res; - - for(;;) { - nl = strchr(ctx->ibuf.array, '\n'); - if (nl == NULL) - break; - *nl = '\0'; - res |= uirc_parse(ctx, ctx->ibuf.array); - gds_remove(&ctx->ibuf, 0, nl - ctx->ibuf.array+1); - } - return res; -} - - -void uirc_join(uirc_t *ctx, const char *chan) -{ - -} - -void uirc_close(uirc_t *ctx, int query) -{ - -} - -void uirc_privmsg(uirc_t *ctx, const char *target, const char *msg) -{ - gds_append_str(&ctx->obuf, "PRIVMSG "); - gds_append_str(&ctx->obuf, target); - gds_append_str(&ctx->obuf, " :"); - gds_append_str(&ctx->obuf, (char *)msg); - gds_append(&ctx->obuf, '\n'); -} - -void uirc_raw(uirc_t *ctx, const char *msg) -{ - gds_append_str(&ctx->obuf, (char *)msg); - gds_append(&ctx->obuf, '\n'); -} - - Index: work/net/libuirc/Makefile =================================================================== --- work/net/libuirc/Makefile (revision 31372) +++ work/net/libuirc/Makefile (nonexistent) @@ -1,8 +0,0 @@ -CFLAGS = -Wall -g -LDLIBS = -lporty_net libgenvector.a - -main: main.o libuirc.o - -main.o: main.c - -libuirc.o: libuirc.c libuirc.h