return 1;
return 0;
}
-int parsePacket(struct client_data *client) {
+int irc_parse_line(struct client_data *client, char *p, char *end) {
char *source = NULL;
char *command = NULL;
char *args[16] = {0};
int argc = 0;
{
- char *p = client->rbuf;
{ // remove \r
- char *end = (char *)memchr(p, '\n', client->rlen);
+ if (!end)
+ end = strchr(p, '\n');
if (end > p && end[-1] == '\r')
*--end = '\n';
if (memchr(p, '\0', end-p)) {
}
}
fprintf(stderr, "\n");
- return processPacket(client, source, command, argc, args);
+ return irc_process_line(client, source, command, argc, args);
}
static void cont_webirc(struct client_data *client, int res) {
if (!(client->umode & UMODE_SECURE) || res != 0) {
newUser(client);
}
}
-int processPacket(struct client_data *client, char *source, char *command, int argc, char *args[]) {
+int irc_process_line(struct client_data *client, char *source, char *command, int argc, char *args[]) {
(void)source;
databuf.clear();
if(strcmp(command, "") == 0) {
#define is_registered(cl) ((cl)->regstate == REG_REGISTERED)
void sendbuf_monitor(const char *nick, int cookie, int positive, int negative);
const char *format_umodes(struct client_data *cl);
-int parsePacket(struct client_data *client);
-int processPacket(struct client_data *client, char *source, char *command, int argc, char *args[]);
+int irc_parse_line(struct client_data *client, char *p, char *end);
+int irc_process_line(struct client_data *client, char *source, char *command, int argc, char *args[]);
void newUser(struct client_data *client);
void sendLUSERS(struct client_data *client);
void sendMOTD(struct client_data *client);
if (!fake->hostname)
abortf("strdup fail (hostname)\n");
strcpy_lit(fake->rbuf, "NICK :root\r\n");
- fake->rlen = strlen(fake->rbuf);
- parsePacket(fake);
+ irc_parse_line(fake, fake->rbuf, 0);
strcpy_lit(fake->rbuf, "USER root 0 * :Patchouli Knowledge\r\n");
- fake->rlen = strlen(fake->rbuf);
- parsePacket(fake);
+ irc_parse_line(fake, fake->rbuf, 0);
while (fgets(fake->rbuf, sizeof(fake->rbuf), f)) {
+ char *p = fake->rbuf;
int len = strlen(fake->rbuf);
if (!len || fake->rbuf[len-1] != '\n')
break;
unsigned long faketime;
- if (sscanf(fake->rbuf, "$%lu", &faketime)) {
+ if (sscanf(p, "$%lu", &faketime)) {
set_time((time_t)faketime);
- char *p = strchr(fake->rbuf, ' ');
+ p = strchr(fake->rbuf, ' ');
if (!p)
continue;
len -= ++p - fake->rbuf;
memmove(fake->rbuf, p, len);
}
- if (fake->rbuf[0] == ':') {
- char *sp = strchr(fake->rbuf, ' ');
- char *bang = strchr(fake->rbuf, '!');
+ if (*p == ':') {
+ char *sp = strchr(p, ' ');
+ char *bang = strchr(p, '!');
if (sp && bang && bang < sp) {
- int nlen = bang - fake->rbuf - 1;
- if (memcmp(&fake->rbuf[1], fake->nick, nlen) != 0) {
+ int nlen = bang - p - 1;
+ if (memcmp(&p[1], fake->nick, nlen) != 0) {
char *nnick = (char *)malloc(nlen+1);
if (!nnick)
abortf("malloc fail (fake->nick)\n");
- memcpy(nnick, &fake->rbuf[1], nlen);
+ memcpy(nnick, &p[1], nlen);
nnick[nlen] = '\0';
free(fake->nick);
fake->nick = nnick;
}
}
}
- fake->rlen = len;
- parsePacket(fake);
+ irc_parse_line(fake, p, 0);
}
strcpy_lit(fake->rbuf, "QUIT :bye\r\n");
- fake->rlen = strlen(fake->rbuf);
- parsePacket(fake);
+ irc_parse_line(fake, fake->rbuf, 0);
set_time(0);
fclose(f);
}
break;
case SOCKTYPE_CLIENT: {
struct client_data *cl = (struct client_data *)ev.assoc;
- /* NOTE: recvProc can kill the client, so writing should be done first. */
+ /* NOTE: read_proc can kill the client, so writing should be done first. */
if ((cl->want_read_for_write && isr) || (cl->want_write_for_write && isw))
sendClient(cl, 0, 0);
if (cl->want_write_for_read ? isw : isr)
- recvProc(cl);
+ read_proc(cl);
break;
}
case SOCKTYPE_DYING: {
delete cl;
}
-void recvProc(struct client_data *cl) {
- ssize_t bytesRead;
- char *x;
- int packetReturn;
+void read_proc(struct client_data *cl)
+{
+ constexpr int rcap = sizeof(cl->rbuf);
cl->want_write_for_read = 0;
for (;;) {
- if(cl->rlen == sizeof(cl->rbuf)) { killConnection(cl, 0); return; }
+ if(cl->rlen == rcap) {
+ killConnection(cl, 0);
+ return;
+ }
+ ssize_t nread;
#if HAVE_LIBTLS
if (cl->cctx) {
- bytesRead = tls_read(cl->cctx, cl->rbuf + cl->rlen, sizeof(cl->rbuf) - cl->rlen);
- switch (bytesRead) {
- // Disconnect
- case 0:
- killConnection(cl, 0);
- return;
- // Error
- case -1:
- fprintf(stderr, "tls_read: %s\n", tls_error(cl->cctx));
- killConnection(cl, 0);
- return;
- case TLS_WANT_POLLIN:
- update_poll_reg(cl);
- return;
- case TLS_WANT_POLLOUT:
- cl->want_write_for_read = 1;
- update_poll_reg(cl);
- return;
+ nread = tls_read(cl->cctx, cl->rbuf + cl->rlen, rcap - cl->rlen);
+ if (nread == TLS_WANT_POLLIN) {
+ update_poll_reg(cl);
+ return;
+ } else if (nread == TLS_WANT_POLLOUT) {
+ cl->want_write_for_read = 1;
+ update_poll_reg(cl);
+ return;
+ } else if (nread == -1) {
+ fprintf(stderr, "tls_read: %s\n", tls_error(cl->cctx));
+ killConnection(cl, 0);
+ return;
}
}
else
#endif
{
- bytesRead = recv(cl->fd, cl->rbuf + cl->rlen,sizeof(cl->rbuf) - cl->rlen, 0);
- switch(bytesRead){
- // Disconnect
- case 0:
+ nread = recv(cl->fd, cl->rbuf + cl->rlen, rcap - cl->rlen, 0);
+ if (nread == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ update_poll_reg(cl);
+ } else {
+ perror("recv");
killConnection(cl, 0);
- return;
- // Error
- case -1:
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- perror("recv");
- killConnection(cl, 0);
- } else {
- update_poll_reg(cl);
- }
- return;
+ }
+ return;
}
}
- cl->rlen += bytesRead;
- while(1){
- x = (char *)memchr(cl->rbuf, '\n', cl->rlen);
- if(!x) break;
- packetReturn = parsePacket(cl);
- // Client QUIT
- if (packetReturn == 1)
+ if (nread == 0) {
+ killConnection(cl, 0);
+ return;
+ }
+ cl->rlen += nread;
+ for (;;) {
+ char *p = (char *)memchr(cl->rbuf, '\n', cl->rlen);
+ if (!p)
+ break;
+ if (irc_parse_line(cl, cl->rbuf, p) == 1)
return;
+ p++;
+ memmove(cl->rbuf, p, cl->rbuf + cl->rlen - p);
+ cl->rlen -= p - cl->rbuf;
if (cl->write_error) {
update_poll_reg(cl);
return;
}
- memmove(cl->rbuf, x+1, cl->rbuf + cl->rlen-(x+1));
- cl->rlen -= x+1 - cl->rbuf;
}
}
}
void log_client(struct client_data *cl, const char *format, ...);
void killConnection(struct client_data *client, int byChoice);
void killConnectionPart2(struct client_data *cl);
-void recvProc(struct client_data *cl);
+void read_proc(struct client_data *cl);
void sendClient(struct client_data *cl, const char *buf, size_t len);
#endif