38 # include <winerror.h> 40 # include <netinet/in.h> 41 # include <arpa/inet.h> 62 #define IRC_SEND_BUF_SIZE 512 63 #define IRC_RECV_BUF_SIZE 1024 65 typedef struct irc_user_s {
70 typedef struct irc_channel_s {
78 typedef enum irc_numeric_e {
226 typedef enum irc_command_type_e {
231 typedef enum irc_nick_prefix_e {
238 typedef struct irc_command_s {
248 typedef struct irc_server_msg_s {
280 static
void Irc_Net_Send(const
char* msg,
size_t msg_len);
295 return (target[0] ==
'#' || target[0] ==
'&');
306 const char* emph = strchr(mask,
'!');
308 size_t length = emph - mask;
312 memcpy(nick, mask,
length);
332 typedef struct irc_bucket_message_s {
335 struct irc_bucket_message_s*
next;
338 typedef struct irc_bucket_s {
391 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"QUIT %s\r\n", quitmsg);
392 msg[
sizeof(msg) - 1] =
'\0';
403 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"NICK %s\r\n", nick);
404 msg[
sizeof(msg) - 1] =
'\0';
414 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"USER %s %c * :%s\r\n",
user, invisible ?
'8' :
'0',
name);
415 msg[
sizeof(msg) - 1] =
'\0';
425 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"PASS %s\r\n",
password);
426 msg[
sizeof(msg) - 1] =
'\0';
437 ? snprintf(msg,
sizeof(msg) - 1,
"JOIN %s %s\r\n", channel,
password)
438 : snprintf(msg,
sizeof(msg) - 1,
"JOIN %s\r\n", channel);
439 msg[
sizeof(msg) - 1] =
'\0';
459 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"PART %s\r\n", channel);
460 msg[
sizeof(msg) - 1] =
'\0';
467 static bool Irc_Proto_Mode (
const char* target,
const char* modes,
const char* params)
470 const int msg_len = params
471 ? snprintf(msg,
sizeof(msg) - 1,
"MODE %s %s %s\r\n", target, modes, params)
472 : snprintf(msg,
sizeof(msg) - 1,
"MODE %s %s\r\n", target, modes);
473 msg[
sizeof(msg) - 1] =
'\0';
483 const int msg_len = topic
484 ? snprintf(msg,
sizeof(msg) - 1,
"TOPIC %s :%s\r\n", channel, topic)
485 : snprintf(msg,
sizeof(msg) - 1,
"TOPIC %s\r\n", channel);
486 msg[
sizeof(msg) - 1] =
'\0';
503 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"PRIVMSG %s :%s\r\n", target, text);
504 msg[
sizeof(msg) - 1] =
'\0';
515 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"NOTICE %s :%s\r\n", target, text);
516 msg[
sizeof(msg) - 1] =
'\0';
523 static void Irc_Proto_Pong (
const char* nick,
const char* server,
const char* cookie)
526 const int msg_len = cookie
527 ? snprintf(msg,
sizeof(msg) - 1,
"PONG %s %s :%s\r\n", nick, server, cookie)
528 : snprintf(msg,
sizeof(msg) - 1,
"PONG %s %s\r\n", nick, server);
529 msg[
sizeof(msg) - 1] =
'\0';
536 static bool Irc_Proto_Kick (
const char* channel,
const char* nick,
const char* reason)
539 const int msg_len = reason
540 ? snprintf(msg,
sizeof(msg) - 1,
"KICK %s %s :%s\r\n", channel, nick, reason)
541 : snprintf(msg,
sizeof(msg) - 1,
"KICK %s %s :%s\r\n", channel, nick, nick);
542 msg[
sizeof(msg) - 1] =
'\0';
552 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"WHO %s\r\n", nick);
553 msg[
sizeof(msg) - 1] =
'\0';
563 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"WHOIS %s\r\n", nick);
564 msg[
sizeof(msg) - 1] =
'\0';
574 const int msg_len = snprintf(msg,
sizeof(msg) - 1,
"WHOWAS %s\r\n", nick);
575 msg[
sizeof(msg) - 1] =
'\0';
585 static char* last =
buf;
586 *msg_complete =
false;
593 const char*
const begin =
buf;
598 const char*
const end = strstr(begin,
"\r\n");
601 const size_t cmd_len = end + 2 - begin;
605 memmove(
buf, end + 2,
sizeof(
buf) - cmd_len);
607 *msg_complete =
true;
610 Com_Printf(
"Received invalid packet from server\n");
615 *msg_complete =
false;
629 char appendString[2048];
632 Q_vsnprintf(appendString,
sizeof(appendString), msg, ap);
646 char appendStringCut[1000];
665 const char* nick =
"", *
user =
"", *host =
"", *real_name = trailing;
670 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
693 const char* channel = strchr(params,
' ');
703 const char* nick =
"", *
user =
"", *host =
"", *real_name = trailing;
708 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
727 const char* nick =
"", *server =
"", *server_info = trailing;
732 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
748 const char* nick =
"", *account =
"";
753 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
769 const char* nick =
"", *idle =
"";
774 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
790 const char* channel =
"", *
user =
"", *host =
"", *server =
"", *nick =
"", *hg =
"";
795 for (
char* p = strtok(
buf,
" "); p; p = strtok(
nullptr,
" "), ++
i) {
871 const char* channel = strtok(
buf,
" ");
872 const char* victim = strtok(
nullptr,
" ");
903 #define IRC_CTCP_MARKER_CHR '\001' 904 #define IRC_CTCP_MARKER_STR "\001" 912 const char*
const emph = strchr(prefix,
'!');
916 memcpy(nick, prefix, emph - prefix);
926 }
else if (!strncmp(trailing + 1,
"PING", 4)) {
929 strcpy(response, trailing);
933 const time_t t = time(
nullptr);
936 response[response_len - 1] =
'\0';
939 Com_Printf(
"Irc_Client_CmdPrivmsg: Unknown ctcp command: '%s'\n", trailing);
943 char serverIPAndPort[128];
946 char*
port = strstr(serverIPAndPort,
";");
947 if (
port ==
nullptr) {
956 char* version = strstr(
port,
";");
957 if (version !=
nullptr) {
992 const size_t len = strlen(trailing) + 1;
1003 char* pos = parseBuf;
1007 space = strstr(pos,
" ");
1014 }
while (space && *pos);
1032 const char* p =
nullptr;
1096 p = strchr(msg->
params,
' ');
1175 if (!strncmp(cmd.
id.
string,
"NICK", 4))
1177 else if (!strncmp(cmd.
id.
string,
"QUIT", 4))
1179 else if (!strncmp(cmd.
id.
string,
"NOTICE", 6)) {
1182 }
else if (!strncmp(cmd.
id.
string,
"PRIVMSG", 7))
1184 else if (!strncmp(cmd.
id.
string,
"MODE", 4))
1186 else if (!strncmp(cmd.
id.
string,
"JOIN", 4))
1188 else if (!strncmp(cmd.
id.
string,
"PART", 4))
1190 else if (!strncmp(cmd.
id.
string,
"TOPIC", 5))
1192 else if (!strncmp(cmd.
id.
string,
"KILL", 4))
1194 else if (!strncmp(cmd.
id.
string,
"KICK", 4))
1196 else if (!strncmp(cmd.
id.
string,
"PING", 4))
1198 else if (!strncmp(cmd.
id.
string,
"ERROR", 5)) {
1211 const char* c = txt;
1212 const char* end = txt + txt_len;
1216 if (c < end && *c ==
':') {
1218 char* prefix = msg->
prefix;
1222 while (c < end && *c !=
'\r' && *c !=
' ') {
1230 if (c < end && *c !=
'\r') {
1232 if (c < end && *c >=
'0' && *c <=
'9') {
1235 for (
int i = 0;
i < 3; ++
i) {
1236 if (c < end && *c >=
'0' && *c <=
'9')
1244 }
else if (c < end && *c !=
'\r') {
1249 while (c < end && *c !=
'\r' && *c !=
' ') {
1258 if (c < end && *c ==
' ') {
1260 char* params = msg->
params;
1266 while (c < end && *c !=
'\r' && *c !=
':') {
1268 while (c < end && *c !=
'\r' && *c !=
' ') {
1274 if (c + 1 < end && *c ==
' ' && *(c + 1) !=
':') {
1284 if (c < end && *c ==
':') {
1289 while (c < end && *c !=
'\r') {
1311 Com_Printf(
"Irc_Proto_Enqueue: not connected\n");
1320 memcpy(
m->msg, msg, msg_len);
1321 m->msg_len = msg_len;
1325 while (*anchor) anchor = &(*anchor)->
next;
1332 Com_Printf(
"Bucket(s) full. Could not enqueue message\n");
1348 const double char_delta = (ms_delta * characterBucketRate) / 1000;
1424 UI_Popup(
_(
"Error"),
_(
"Server closed connection"));
1427 }
while (msg_complete);
1437 if (pass[0] !=
'\0')
1442 Com_Printf(
"Could not connect to the irc server %s:%s\n", server,
port);
1449 Com_Printf(
"Irc_Disconnect: not connected\n");
1490 return channel->
topic;
1525 if (!strncmp(&(
user->key[1]), nick,
sizeof(
user->key))) {
1590 if (argc >= 2 && argc <= 4) {
1632 Com_Printf(
"Joined channel: '%s'\n", channel);
1635 Com_Printf(
"Could not join channel: '%s'\n", channel);
1643 if (argc >= 2 && argc <= 3) {
1644 const char*
const channel =
Cmd_Argv(1);
1646 const char*
const channel_pass = (argc == 3) ?
Cmd_Argv(2) :
nullptr;
1657 const char*
const channel =
Cmd_Argv(1);
1681 if (msg[0] !=
'\0') {
1683 if (msg[0] ==
'"') {
1684 const size_t msg_len = strlen(msg);
1685 memcpy(cropped_msg, msg + 1, msg_len - 2);
1686 cropped_msg[msg_len - 2] =
'\0';
1703 const char*
const target =
Cmd_Argv(1);
1704 const char* msg =
Cmd_Args() + strlen(target) + 1;
1706 const size_t msg_len = strlen(msg);
1707 memcpy(cropped_msg, msg + 1, msg_len - 2);
1708 cropped_msg[msg_len - 2] =
'\0';
1721 const char*
const target =
Cmd_Argv(1);
1722 const char*
const modes =
Cmd_Argv(2);
1723 const char*
const params = argc >= 4
1724 ?
Cmd_Args() + strlen(target) + strlen(modes) + 2
1735 const char*
const channel =
Cmd_Argv(1);
1743 in += strlen(channel) + 1;
1747 const size_t out_len = strlen(out);
1748 assert(out_len >= 1);
1749 out[out_len - 1] =
'\0';
1763 #define IRC_MAX_USERLIST 512 1801 const char*
const nick =
Cmd_Argv(2);
1804 reason =
Cmd_Args() + strlen(nick) + strlen(channel) + 2;
1815 Com_Printf(
"Could not query masterserver\n");
1826 const char*
name = &(
user->key[1]);
1839 Com_Printf(
"You must be connected to a running server to invite others\n");
int NET_StreamDequeue(struct net_stream *s, char *data, int len)
const char * Cmd_Argv(int arg)
Returns a given argument.
static bool Irc_Proto_Msg(const char *target, const char *text)
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
static bool Irc_AppendToBuffer(const char *const msg,...) __attribute__((format(__printf__
Append the irc message to the buffer.
void GAME_AddChatMessage(const char *format,...)
#define Mem_AllocTypeN(type, n)
static bool Irc_Proto_Part(const char *channel)
static bool Irc_Proto_PollServerMsg(irc_server_msg_t *msg, bool *msg_complete)
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
struct net_stream * NET_Connect(const char *node, const char *service, stream_onclose_func *onclose)
Try to connect to a given host on a given port.
void UI_RegisterLinkedListText(int dataId, linkedList_t *text)
share a linked list of text with a data id
static bool Irc_Proto_Connect(const char *host, const char *port)
static void Irc_Client_CmdJoin(const char *prefix, const char *params, const char *trailing)
static char irc_userListOrdered[IRC_MAX_USERLIST][MAX_VAR]
static void Irc_Logic_RemoveChannelName(irc_channel_t *channel, const char *nick)
Removes a username from the channel username list.
void UI_RegisterText(int dataId, const char *text)
share a text with a data id
bool CL_OnBattlescape(void)
Check whether we are in a tactical mission as server or as client. But this only means that we are ab...
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
static void Irc_Client_CmdQuit(const char *prefix, const char *params, const char *trailing)
static void Irc_Logic_Disconnect(const char *reason)
#define IRC_RECV_BUF_SIZE
static void Irc_Client_Whois_f(void)
static cvar_t * irc_characterBucketBurst
static bool Irc_Proto_Disconnect(void)
static void Irc_Client_Mode_f(void)
unsigned int message_size
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
const char * UI_GetActiveWindowName(void)
Returns the name of the current window.
static void Irc_Client_CmdNick(const char *prefix, const char *params, const char *trailing)
Changes the cvar 'name' with the new name you set.
static cvar_t * irc_channel
#define IRC_CTCP_MARKER_CHR
uiNode_t * UI_GetActiveWindow(void)
Returns the current active window from the window stack or nullptr if there is none.
static cvar_t * irc_characterBucketRate
static cvar_t * irc_send_buffer
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
static cvar_t * irc_password
static void Irc_Client_CmdRplWhoisaccount(const char *params, const char *trailing)
Shared game type headers.
static void Irc_Input_Activate_f(void)
char prefix[IRC_SEND_BUF_SIZE]
static bool Irc_Net_Disconnect(void)
void NET_StreamFree(struct net_stream *s)
Call NET_StreamFree to dump the whole thing right now.
static bool Irc_Client_Join(const char *channel, const char *password)
char params[IRC_SEND_BUF_SIZE]
void Com_Printf(const char *const fmt,...)
static void Irc_Client_Who_f(void)
cvar_t * masterserver_url
static void Irc_Client_CmdRplNamreply(const char *params, const char *trailing)
static bool Irc_Proto_Enqueue(const char *msg, size_t msg_len)
static void Irc_Net_StreamClose(void)
static void Irc_Client_CmdRplWhoisuser(const char *params, const char *trailing)
static void Irc_UserClick_f(void)
Adds the username you clicked to your input buffer.
static bool Irc_Proto_Who(const char *nick)
static cvar_t * irc_messageBucketBurst
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
static void Irc_Client_Names_f(void)
static void Irc_Net_Send(const char *msg, size_t msg_len)
static void Irc_Disconnect_f(void)
static bool Irc_Proto_Whowas(const char *nick)
static bool static bool Irc_Proto_ParseServerMsg(const char *txt, size_t txt_len, irc_server_msg_t *msg)
uiNode_t * UI_PushWindow(const char *name, const char *parentName, linkedList_t *params)
Push a window onto the window stack.
static void Irc_Client_Part_f(void)
void UI_ResetData(int dataId)
Reset a shared data. Type became NONE and value became nullptr.
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
void NET_StreamEnqueue(struct net_stream *s, const char *data, int len)
Enqueue a network message into a stream.
void LIST_AddString(linkedList_t **listDest, const char *data)
Adds an string to a new or to an already existing linked list. The string is copied here...
static bool Irc_Proto_Quit(const char *quitmsg)
QGL_EXTERN GLuint GLsizei GLsizei * length
static char irc_buffer[4096]
char trailing[IRC_SEND_BUF_SIZE]
unsigned int character_size
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
static void Irc_Client_CmdRplWhowasuser(const char *params, const char *trailing)
static bool Irc_Proto_Nick(const char *nick)
static void Irc_Logic_ReadMessages(void)
static void Irc_Proto_RefillBucket(void)
static void Irc_Client_Whowas_f(void)
#define Mem_CreatePool(name)
static irc_channel_t ircChan
#define Mem_DeletePool(pool)
void UI_TextScrollEnd(const char *nodePath)
Scroll to the bottom.
union irc_command_t::@6 id
static cvar_t * irc_server
static void Irc_Connect_f(void)
static void Irc_Logic_SendMessages(void)
static void Irc_Client_PrivMsg_f(void)
static void Irc_Proto_Pong(const char *nick, const char *server, const char *cookie)
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
static void Irc_Logic_Connect(const char *server, const char *port)
static struct net_stream * irc_stream
static void Irc_Client_CmdRplEndofnames(const char *params, const char *trailing)
static irc_bucket_t irc_bucket
#define IRC_CTCP_MARKER_STR
static void Irc_GetExternalIP(const char *externalIP, void *userdata)
irc_bucket_message_t * first_msg
static bool Irc_Proto_Whois(const char *nick)
static void Irc_Client_Msg_f(void)
Send a message from menu or commandline.
static cvar_t * irc_characterBucketSize
void S_StartLocalSample(const char *s, float volume)
Plays a sample without spatialization.
static bool Irc_IsChannel(const char *target)
static void Irc_ParseName(const char *mask, char *nick, size_t size, irc_nick_prefix_t *prefix)
static const char * Irc_Logic_GetChannelTopic(const irc_channel_t *channel)
#define Mem_PoolAllocTypeN(type, n, pool)
static void Irc_Proto_DrainBucket(void)
Send all enqueued packets.
static void Irc_Logic_AddChannelName(irc_channel_t *channel, irc_nick_prefix_t prefix, const char *nick)
Adds a new username to the channel username list.
#define IRC_SEND_BUF_SIZE
static bool Irc_Proto_User(const char *user, bool invisible, const char *name)
static void Irc_Client_CmdRplWhoisidle(const char *params, const char *trailing)
static void Irc_Client_CmdPart(const char *prefix, const char *trailing)
static bool Irc_Proto_Topic(const char *channel, const char *topic)
static bool Irc_Net_Connect(const char *host, const char *port)
static void Irc_Client_CmdKill(const char *prefix, const char *params, const char *trailing)
static cvar_t * irc_defaultChannel
QGL_EXTERN GLuint GLchar GLuint * len
const char * CL_Translate(const char *t)
static cvar_t * irc_logConsole
static bool irc_connected
static cvar_t * irc_messageBucketSize
static bool Irc_Proto_Password(const char *password)
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
static void Irc_UserRightClick_f(void)
Performs a whois query for the username you clicked.
static void Irc_Client_Kick_f(void)
static void Irc_Client_Join_f(void)
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
static void Irc_Client_Topic_f(void)
void Irc_Logic_Frame(void)
void UI_PopWindow(bool all)
Pops a window from the window stack.
static cvar_t * irc_showIfNotInMenu
static const char IRC_INVITE_FOR_A_GAME[]
static cvar_t * irc_topic
int Q_StringSort(const void *string1, const void *string2)
Compare two strings.
#define Mem_AllocType(type)
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
bool HTTP_GetURL(const char *url, http_callback_t callback, void *userdata, const char *postfields)
Downloads the given url and return the data to the callback (optional)
static bool Irc_Proto_ProcessServerMsg(const irc_server_msg_t *msg)
char string[IRC_SEND_BUF_SIZE]
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Primary header for client.
static memPool_t * cl_ircSysPool
IRC client header for UFO:AI.
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
static bool Irc_Proto_Join(const char *channel, const char *password)
#define Mem_PoolAllocType(type, pool)
static void Irc_Client_CmdRplTopic(const char *params, const char *trailing)
static irc_channel_t * chan
union irc_server_msg_t::@7 id
static bool Irc_Proto_Mode(const char *target, const char *modes, const char *params)
static void Irc_Client_Invite_f(void)
static bool Irc_Proto_Kick(const char *channel, const char *nick, const char *reason)
static void Irc_Input_Deactivate_f(void)
static bool Irc_Proto_Notice(const char *target, const char *text)
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
static void Irc_Client_CmdRplWhoreply(const char *params, const char *trailing)
static void Irc_Client_CmdRplWhoisserver(const char *params, const char *trailing)
static void Irc_Client_CmdTopic(const char *prefix, const char *trailing)
const char * Cmd_Args(void)
Returns a single string containing argv(1) to argv(argc()-1)
static void Irc_Client_CmdKick(const char *prefix, const char *params, const char *trailing)
struct irc_bucket_message_s * next
void format(__printf__, 1, 2)))
static void Irc_Client_CmdMode(const char *prefix, const char *params, const char *trailing)
int CL_Milliseconds(void)
#define SND_VOLUME_DEFAULT
void UI_ExecuteConfunc(const char *fmt,...)
Executes confunc - just to identify those confuncs in the code - in this frame.
static void Irc_Client_CmdPrivmsg(const char *prefix, const char *params, const char *trailing)