Finish server message parser and some work on the client message assembler, change few types and make some public as well

This commit is contained in:
Alex 2020-06-25 21:06:53 +02:00
parent ca4b783af4
commit b7a12816e8
Signed by: caskd
GPG Key ID: F92BA85F61F4C173
2 changed files with 87 additions and 43 deletions

View File

@ -19,26 +19,34 @@
#ifndef UIRC_INCLUDED
#define UIRC_INCLUDED
struct irc_message {
struct tags {
typedef struct uirc_tag {
char* value;
bool clientbound;
} IRC_Tag;
typedef struct name {
char* nick;
char* user;
char* host;
char* realname;
} IRC_User;
typedef struct uirc_message {
struct uirc_tags {
/* See https://ircv3.net/registry#tags for more information */
char* account;
char* batch;
char* label;
char* msgid;
char* multiline_concat; /* NOTE: Still a draft */
char* time;
IRC_Tag account;
IRC_Tag batch;
IRC_Tag label;
IRC_Tag msgid;
IRC_Tag multiline_concat;
IRC_Tag time;
IRC_Tag typing;
IRC_Tag react;
IRC_Tag reply;
} tags;
struct source {
char* nick;
char* user;
char* host;
} source;
IRC_User name;
signed short cmd;
char* args[14];
unsigned int argc;
char* args[15]; /* 0-13 + NULL */
char* msg;
};
} IRC_Message;
enum {
PASS = 10,
@ -209,7 +217,7 @@ enum {
};
extern const char* uirc_ircmd[];
int uirc_tokenize_message(struct irc_message* irc_msg, char* line);
int uirc_tokenize_message(IRC_Message* irc_msg, char* line);
int uirc_assm_mesg(char* buf, IRC_Message* mesg);
unsigned int uirc_ircmd_stoi(char* str);
int uirc_assm_mesg(char* buf, int comm, char* dest, char* msg);
#endif

View File

@ -58,7 +58,9 @@ const char* uirc_ircmd[] = {
[WALLOPS] = "WALLOPS",
[USERHOST] = "USERHOST",
[ISON] = "ISON"};
int uirc_tokenize_message(struct irc_message* irc_msg, char* line)
/* TODO: Parse client messages aswell */
int uirc_tokenize_message(IRC_Message* irc_msg, char* line)
{
char *progr, *command;
progr = line;
@ -67,21 +69,33 @@ int uirc_tokenize_message(struct irc_message* irc_msg, char* line)
char* tags;
if ((tags = strtok_r(progr + 1, " ", &progr)) != NULL) {
char *ctag = tags, *cval;
bool clientbound;
do {
clientbound = false;
if (*ctag == '+') {
ctag++;
clientbound = true;
}
if ((cval = strchr(ctag, '=')) != NULL) {
*(cval++) = '\0';
if (!strcmp(ctag, "time")) {
irc_msg->tags.time = cval;
} else if (!strcmp(ctag, "account")) {
irc_msg->tags.account = cval;
} else if (!strcmp(ctag, "batch")) {
irc_msg->tags.batch = cval;
} else if (!strcmp(ctag, "label")) {
irc_msg->tags.label = cval;
} else if (!strcmp(ctag, "msgid")) {
irc_msg->tags.msgid = cval;
} else if (!strcmp(ctag, "multiline-concat")) {
irc_msg->tags.multiline_concat = cval;
struct tagmapping {
char* name;
IRC_Tag* assg;
} tags[] = {
{.name = "time", .assg = &irc_msg->tags.time},
{.name = "account", .assg = &irc_msg->tags.account},
{.name = "batch", .assg = &irc_msg->tags.batch},
{.name = "label", .assg = &irc_msg->tags.label},
{.name = "msgid", .assg = &irc_msg->tags.msgid},
{.name = "multiline-concat", .assg = &irc_msg->tags.multiline_concat},
{.name = "typing", .assg = &irc_msg->tags.typing},
{.name = "react", .assg = &irc_msg->tags.react},
{.name = "reply", .assg = &irc_msg->tags.reply}};
for (unsigned int i = 0; i < sizeof(tags) / sizeof(struct tagmapping); i++) {
if (!strcmp(ctag, tags[i].name)) {
(*tags[i].assg).value = cval;
(*tags[i].assg).clientbound = clientbound;
}
}
if ((ctag = strchr(cval, ';')) != NULL)
*(ctag++) = '\0';
@ -93,12 +107,12 @@ int uirc_tokenize_message(struct irc_message* irc_msg, char* line)
if (*progr == ':') {
char* prefix;
if ((prefix = strtok_r(progr + 1, " ", &progr)) != NULL) {
if ((irc_msg->source.host = strchr(prefix, '@')) != NULL) {
*(irc_msg->source.host++) = '\0';
if ((irc_msg->source.user = strchr(prefix, '!')) != NULL)
*(irc_msg->source.user++) = '\0';
if ((irc_msg->name.host = strchr(prefix, '@')) != NULL) {
*(irc_msg->name.host++) = '\0';
if ((irc_msg->name.user = strchr(prefix, '!')) != NULL)
*(irc_msg->name.user++) = '\0';
}
irc_msg->source.nick = prefix; /* NOTE: This may be the server instead of a nick according to RFC2812, it is left to the library user to decide how to interpret this based on the context. */
irc_msg->name.nick = prefix; /* NOTE: This may be the server instead of a nick according to RFC2812, it is left to the library user to decide how to interpret this based on the context. */
} else
return 0;
}
@ -119,7 +133,7 @@ int uirc_tokenize_message(struct irc_message* irc_msg, char* line)
if ((irc_msg->args[i] = strtok_r(NULL, " ", &progr)) == NULL)
return 0;
}
irc_msg->argc = i;
irc_msg->args[i] = NULL;
if (*progr == ':')
++progr;
irc_msg->msg = progr;
@ -133,16 +147,38 @@ unsigned int uirc_ircmd_stoi(char* str)
}
return 0;
}
int uirc_assm_mesg(char* buf, int comm, char* dest, char* msg)
int uirc_assm_mesg(char* buf, IRC_Message* mesg)
{
if (buf == NULL)
return -2;
if (dest == NULL) {
if (sprintf(buf, "%s %s\r\n", uirc_ircmd[comm], msg) < 0)
char* pos = buf;
int cnt;
char* arg;
/* TODO: Finish this
if (mesg->tags.typing.value || mesg->tags.react.value || mesg->tags.reply.value) {
if (sprintf(pos++, "@") != 1)
return -1;
} else {
if (sprintf(buf, "%s %s %s\r\n", uirc_ircmd[comm], dest, msg) < 0)
if (sprintf(pos++, " ") != 1)
return -1;
}
return 0;
*/
if ((uirc_ircmd[mesg->cmd] != NULL) && ((cnt = sprintf(pos, "%s", uirc_ircmd[mesg->cmd])) > 0))
pos += cnt;
else
return -1;
for (unsigned int i = 0; i < 14 && mesg->args[i] != NULL; i++) {
if ((cnt = sprintf(pos, " %s", mesg->args[i])) > 0)
pos += cnt;
else
return -1;
}
if (mesg->cmd == PART || mesg->cmd == NOTICE) {
if ((cnt = sprintf(pos, " %s", mesg->msg)) > 0)
pos += cnt;
else
return -1;
}
if ((cnt = sprintf(pos, "\r\n")) != 2)
return -1;
return 1;
}