jcs
/wallops
/amendments
/73
irc: Pass count of nicks in batch to irc_add_nick_to_channel
This lets it do a malloc of the full count of the line, rather than
having to realloc it 5 at a time.
Also implement 333 and 475 and show non-server notices properly.
jcs made amendment 73 2 months ago
--- irc.c Sun Sep 8 22:01:55 2024
+++ irc.c Mon Sep 9 16:13:58 2024
@@ -39,7 +39,7 @@ void irc_dealloc_channel(struct irc_channel *channel);
void irc_set_active_channel(struct irc_connection *conn, char *channame);
void irc_parse_names(struct irc_channel *channel, char *line);
void irc_add_nick_to_channel(struct irc_channel *channel, char *nick,
- short flags);
+ short flags, short count_hint);
void irc_remove_nick_from_channel(struct irc_channel *channel, char *nick);
bool irc_nick_is_in_channel(struct irc_channel *channel, char *nick);
void irc_change_user_nick(struct irc_channel *channel,
@@ -86,7 +86,8 @@ irc_connect(struct chatter *chatter, const char *serve
conn->channel_autojoin = xstrdup(channel);
chatter_printf(conn->chatter, conn, NULL,
- "$B***$0 Connecting to $B%s:%d$0...", conn->hostname, conn->port);
+ "$B***$0 Connecting to $B%s$0 port $B%d$0...", conn->hostname,
+ conn->port);
if ((err = _TCPCreate(&conn->send_pb, &conn->stream, (Ptr)conn->tcp_buf,
sizeof(conn->tcp_buf), nil, nil, nil, false)) != noErr) {
@@ -114,8 +115,8 @@ irc_connect(struct chatter *chatter, const char *serve
}
chatter_printf(conn->chatter, conn, NULL,
- "$B***$0 Connected to $B%s$0 (%s) port %d", conn->hostname, ip_str,
- conn->port);
+ "$B***$0 Connected to $B%s$0 (%s) port $B%d$0", conn->hostname,
+ ip_str, conn->port);
conn->state = IRC_STATE_CONNECTED;
@@ -536,7 +537,7 @@ irc_process_server(struct irc_connection *conn)
else {
channel = irc_find_channel(conn, msg.arg[0]);
if (channel)
- irc_add_nick_to_channel(channel, user->nick, 0);
+ irc_add_nick_to_channel(channel, user->nick, 0, 0);
}
chatter_printf(channel->chatter, conn, msg.arg[0],
"$B*** %s ($0%s@%s$B)$0 has joined $B%s$0",
@@ -626,14 +627,23 @@ irc_process_server(struct irc_connection *conn)
return true;
}
if (strcmp(msg.cmd, "NOTICE") == 0) {
- if (strncmp(msg.msg, "*** ", 4) == 0)
- chatter_printf(conn->chatter, conn, NULL,
- "$B***$0 $/%s",
- msg.msg + 4);
- else
- chatter_printf(conn->chatter, conn, NULL,
- "$/%s",
- msg.msg);
+ if (strchr(msg.source, '@') == NULL) {
+ /* server notice */
+ if (strncmp(msg.msg, "*** ", 4) == 0)
+ chatter_printf(conn->chatter, conn, NULL,
+ "$B***$0 $/%s",
+ msg.msg + 4);
+ else
+ chatter_printf(conn->chatter, conn, NULL,
+ "$/%s",
+ msg.msg);
+ } else {
+ /* user notice */
+ user = irc_parse_user(msg.source);
+ chatter_printf(conn->chatter, conn, user->nick,
+ "$Bnotice:[%s($0%s@%s$B)]$0$/ %s",
+ user->nick, user->username, user->hostname, msg.msg);
+ }
return true;
}
if (strcmp(msg.cmd, "PART") == 0) {
@@ -775,6 +785,9 @@ irc_process_server(struct irc_connection *conn)
return true;
case 333:
/* TOPIC creator */
+ chatter_printf(conn->chatter, conn, msg.arg[1],
+ "$B***$0 Topic set by $B%s$0",
+ msg.arg[1]);
return true;
case 338:
case 378:
@@ -842,6 +855,12 @@ irc_process_server(struct irc_connection *conn)
irc_send(conn, conn->line, len);
return true;
}
+ case 475:
+ /* can't join channel */
+ chatter_printf(conn->chatter, conn, NULL,
+ "$B***$0 Cannot join $B%s$0$/: %s",
+ msg.arg[1], msg.msg);
+ return true;
case 671:
/* WHOIS server */
chatter_printf(conn->chatter, conn, conn->current_whois,
@@ -853,7 +872,7 @@ irc_process_server(struct irc_connection *conn)
chatter_printf(conn->chatter, conn, NULL,
"$B***$0$/ %s",
msg.msg);
- break;
+ return true;
default:
goto unknown;
}
@@ -1118,11 +1137,26 @@ irc_dealloc_channel(struct irc_channel *channel)
void
irc_parse_names(struct irc_channel *channel, char *line)
{
- char *nick;
- short flags;
+ char *nick, *tline;
+ short flags, count;
- channel->parsing_nicks = true;
+ if (!channel->parsing_nicks) {
+ /* new names output, clear previous */
+ if (channel->nicks_size) {
+ memset(&channel->nicks, 0,
+ sizeof(struct irc_channel_nick) * channel->nicks_size);
+ }
+
+ channel->nnicks = 0;
+ channel->parsing_nicks = true;
+ }
+ /* get a count of nicks to pass as a hint to malloc */
+ count = 1;
+ for (tline = line; *tline != '\0'; tline++)
+ if (*tline == ' ')
+ count++;
+
for (;;) {
nick = strsep(&line, " ");
@@ -1138,7 +1172,7 @@ irc_parse_names(struct irc_channel *channel, char *lin
} else
flags = 0;
- irc_add_nick_to_channel(channel, nick, flags);
+ irc_add_nick_to_channel(channel, nick, flags, count);
if (line == NULL)
break;
@@ -1147,17 +1181,23 @@ irc_parse_names(struct irc_channel *channel, char *lin
void
irc_add_nick_to_channel(struct irc_channel *channel, char *nick,
- short flags)
+ short flags, short count_hint)
{
struct irc_channel_nick *anick, *cnick, *pnick;
short aidx, cidx, ret;
if (channel->nnicks >= channel->nicks_size) {
/* allocate a chunk at a time so we don't do this every iteration */
- channel->nicks_size += 5;
+ if (count_hint)
+ channel->nicks_size += count_hint;
+ else
+ channel->nicks_size += 5;
channel->nicks = xreallocarray(channel->nicks,
sizeof(struct irc_channel_nick),
channel->nicks_size);
+ if (channel->nicks == NULL)
+ panic("out of memory allocating for %ld nicks",
+ sizeof(struct irc_channel_nick) * channel->nicks_size);
memset(&channel->nicks[channel->nnicks], 0,
sizeof(struct irc_channel_nick) *
(channel->nicks_size - channel->nnicks));
@@ -1308,7 +1348,7 @@ irc_change_user_nick(struct irc_channel *channel, stru
}
irc_remove_nick_from_channel(channel, user->nick);
- irc_add_nick_to_channel(channel, nick, flags);
+ irc_add_nick_to_channel(channel, nick, flags, 0);
}
if (strcmp(channel->connection->nick, user->nick) == 0) {
@@ -1369,7 +1409,7 @@ irc_parse_channel_mode_change(struct irc_channel *chan
irc_remove_nick_from_channel(channel, cnick->nick);
/* cnick is probably invalid now */
- irc_add_nick_to_channel(channel, user, flags);
+ irc_add_nick_to_channel(channel, user, flags, 0);
break;
}