2015-03-24 03:12:35 -07:00
|
|
|
/*
|
|
|
|
* irc.c: IRC connection and parser
|
|
|
|
* xbot: Just another IRC bot
|
|
|
|
*
|
|
|
|
* Written by Aaron Blakely <aaron@ephasic.org>
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "irc.h"
|
|
|
|
#include "util.h"
|
2015-03-24 10:48:11 -07:00
|
|
|
#include "events.h"
|
2015-03-24 03:12:35 -07:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
2024-02-12 23:22:10 -08:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#define FDOPEN _fdopen
|
|
|
|
#define SETBUF setbuf
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
2015-03-24 03:12:35 -07:00
|
|
|
#include <netdb.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <sys/socket.h>
|
2024-02-12 23:22:10 -08:00
|
|
|
#define FDOPEN fdopen
|
|
|
|
#define SETBUF setbuf
|
|
|
|
#endif
|
2015-03-24 03:12:35 -07:00
|
|
|
|
|
|
|
void irc_connect(struct irc_conn *bot)
|
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
WSADATA wsaData;
|
|
|
|
struct sockaddr_in server;
|
2015-03-24 03:12:35 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
|
|
|
eprint("WSAStartup failed.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2015-03-24 03:12:35 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
bot->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
|
if (bot->srv_fd == INVALID_SOCKET)
|
2015-03-24 03:12:35 -07:00
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
eprint("Error creating socket: %d\n", WSAGetLastError());
|
|
|
|
WSACleanup();
|
|
|
|
|
|
|
|
return;
|
2015-03-24 03:12:35 -07:00
|
|
|
}
|
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
memset(&server, 0, sizeof(server));
|
|
|
|
server.sin_family = AF_INET;
|
|
|
|
server.sin_addr.s_addr = inet_addr(bot->host);
|
|
|
|
server.sin_port = htons(atoi(bot->port));
|
2015-03-24 03:12:35 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
if (connect(bot->srv_fd, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
|
|
|
|
{
|
|
|
|
eprint("Failed to connect to IRC server: %d\n", WSAGetLastError());
|
2015-03-24 03:12:35 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
closesocket(bot->srv_fd);
|
|
|
|
WSACleanup();
|
2015-03-24 03:12:35 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
return;
|
2015-03-24 03:12:35 -07:00
|
|
|
}
|
2024-02-12 23:22:10 -08:00
|
|
|
#else
|
|
|
|
int srv_fd;
|
|
|
|
struct addrinfo hints;
|
|
|
|
struct addrinfo *res, *r;
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof hints);
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
|
|
|
|
if (getaddrinfo(bot->host, bot->port, &hints, &res) != 0)
|
|
|
|
{
|
|
|
|
eprint("Error: Cannot resolve hostname '%s':", bot->host);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (r = res; r; r->ai_next)
|
|
|
|
{
|
|
|
|
if ((srv_fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connect(srv_fd, r->ai_addr, r->ai_addrlen) == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(srv_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo(res);
|
|
|
|
if (!r)
|
|
|
|
{
|
|
|
|
eprint("Error: Cannot connect to host '%s'\n", bot->host);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Connected!\n");
|
|
|
|
bot->srv_fd = FDOPEN(srv_fd, "r+");
|
|
|
|
#endif
|
2015-03-24 03:12:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void irc_auth(struct irc_conn *bot)
|
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
irc_raw(bot, "NICK %s", bot->nick);
|
|
|
|
irc_raw(bot, "USER %s \" %s :xbot (v0.1) - developed by @Dark_Aaron", bot->nick, bot->host);
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
fflush(bot->srv_fd);
|
|
|
|
SETBUF(bot->srv_fd, NULL);
|
|
|
|
#endif
|
2015-03-24 03:12:35 -07:00
|
|
|
}
|
|
|
|
|
2015-03-26 16:20:59 -07:00
|
|
|
void irc_notice(struct irc_conn *bot, char *to, char *fmt, ...)
|
2015-03-24 10:48:11 -07:00
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
char msg_[4096];
|
|
|
|
va_list ap;
|
2015-03-26 16:20:59 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(msg_, sizeof msg_, fmt, ap);
|
|
|
|
va_end(ap);
|
2015-03-26 16:20:59 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
irc_raw(bot, "NOTICE %s :%s", to, msg_);
|
2015-03-24 10:48:11 -07:00
|
|
|
}
|
|
|
|
|
2015-03-27 08:44:40 -07:00
|
|
|
void irc_privmsg(struct irc_conn *bot, char *to, char *fmt, ...)
|
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
char msg_[4096];
|
|
|
|
va_list ap;
|
2015-03-27 08:44:40 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(msg_, sizeof msg_, fmt, ap);
|
|
|
|
va_end(ap);
|
2015-03-27 08:44:40 -07:00
|
|
|
|
2024-02-12 23:22:10 -08:00
|
|
|
irc_raw(bot, "PRIVMSG %s :%s", to, msg_);
|
2015-03-27 08:44:40 -07:00
|
|
|
}
|
|
|
|
|
2015-03-24 03:12:35 -07:00
|
|
|
void irc_raw(struct irc_conn *bot, char *fmt, ...)
|
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
va_list ap;
|
|
|
|
char outbuf[4096];
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(bot->out, sizeof bot->out, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
send(bot->srv_fd, outbuf, strlen(outbuf), 0);
|
|
|
|
#else
|
|
|
|
fprintf(bot->srv_fd, "%s\r\n", bot->out);
|
|
|
|
#endif
|
2015-03-24 03:12:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void irc_parse_raw(struct irc_conn *bot, char *raw)
|
|
|
|
{
|
2024-02-12 23:22:10 -08:00
|
|
|
char *user, *par, *text;
|
|
|
|
user = bot->host;
|
|
|
|
|
|
|
|
if (!raw || !*raw)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (raw[0] == ':')
|
|
|
|
{
|
|
|
|
user = raw + 1;
|
|
|
|
raw = skip(user, ' ');
|
|
|
|
|
|
|
|
if (raw[0] == '\0')
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
skip(user, '!');
|
|
|
|
}
|
|
|
|
|
|
|
|
skip(raw, '\r');
|
|
|
|
par = skip(raw, ' ');
|
|
|
|
text = skip(par, ':');
|
|
|
|
trim(par);
|
|
|
|
|
|
|
|
if (!strcmp("PONG", raw))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp("PRIVMSG", raw))
|
|
|
|
{
|
|
|
|
if (!strcmp(par, bot->nick))
|
|
|
|
{
|
|
|
|
handle_self_privmsg(bot, user, text);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
handle_chan_privmsg(bot, user, par, text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!strcmp("JOIN", raw))
|
|
|
|
{
|
|
|
|
handle_join(bot, user, par);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp("PING", raw))
|
|
|
|
{
|
|
|
|
irc_raw(bot, "PONG %s", text);
|
|
|
|
}
|
|
|
|
else if (!strcmp("001", raw))
|
|
|
|
{
|
|
|
|
handle_connected(bot, text);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp("NICK", raw) && !strcmp(user, bot->nick))
|
|
|
|
{
|
|
|
|
strlcpy(bot->nick, text, sizeof bot->nick);
|
|
|
|
}
|
|
|
|
}
|
2016-02-21 20:40:41 -08:00
|
|
|
}
|