40# include <netinet/in.h>
41# include <arpa/inet.h>
62#define IRC_SEND_BUF_SIZE 512
63#define IRC_RECV_BUF_SIZE 1024
65typedef struct irc_user_s {
70typedef struct irc_channel_s {
78typedef enum irc_numeric_e {
226typedef enum irc_command_type_e {
231typedef enum irc_nick_prefix_e {
238typedef struct irc_command_s {
248typedef struct irc_server_msg_s {
280static
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);
332typedef struct irc_bucket_message_s {
335 struct irc_bucket_message_s*
next;
338typedef 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';
467static 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';
523static 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';
536static 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) {
976 }
else if (strstr(trailing,
irc_nick->string)) {
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");
1316 if (
irc_bucket.message_size + 1 <= messageBucketSize &&
irc_bucket.character_size + msg_len <= characterBucketSize) {
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");
1347 const int ms_delta = ms -
irc_bucket.last_refill;
1348 const double char_delta = (ms_delta * characterBucketRate) / 1000;
1349 const double char_new =
irc_bucket.character_token + char_delta;
1351 irc_bucket.character_token = std::min(char_new, characterBucketSize);
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
1775 for (
i = 0;
i <
chan->users;
i++) {
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");
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...
void GAME_AddChatMessage(const char *format,...)
Shared game type headers.
static bool Irc_Proto_Nick(const char *nick)
static void Irc_Client_CmdKill(const char *prefix, const char *params, const char *trailing)
static bool Irc_Proto_Mode(const char *target, const char *modes, const char *params)
static void Irc_Client_CmdRplTopic(const char *params, const char *trailing)
static void Irc_Client_Invite_f(void)
static bool Irc_AppendToBuffer(const char *const msg,...) __attribute__((format(__printf__
Append the irc message to the buffer.
static cvar_t * irc_messageBucketSize
static void Irc_Client_CmdRplWhowasuser(const char *params, const char *trailing)
static void Irc_Logic_Disconnect(const char *reason)
static cvar_t * irc_channel
#define IRC_SEND_BUF_SIZE
static void Irc_Proto_DrainBucket(void)
Send all enqueued packets.
static void Irc_Connect_f(void)
static void Irc_Client_CmdPrivmsg(const char *prefix, const char *params, const char *trailing)
static cvar_t * irc_defaultChannel
static void Irc_GetExternalIP(const char *externalIP, void *userdata)
static void Irc_Proto_RefillBucket(void)
static void Irc_Logic_Connect(const char *server, const char *port)
static void Irc_Net_StreamClose(void)
static void Irc_Logic_ReadMessages(void)
static cvar_t * irc_characterBucketSize
static void Irc_UserRightClick_f(void)
Performs a whois query for the username you clicked.
static cvar_t * irc_password
static bool Irc_Net_Connect(const char *host, const char *port)
static bool Irc_Proto_Quit(const char *quitmsg)
static bool Irc_Proto_Disconnect(void)
static bool Irc_Proto_ProcessServerMsg(const irc_server_msg_t *msg)
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 void Irc_Client_Whowas_f(void)
static cvar_t * irc_topic
static bool Irc_IsChannel(const char *target)
static void Irc_Client_CmdRplWhoisuser(const char *params, const char *trailing)
static void Irc_Client_CmdRplWhoreply(const char *params, const char *trailing)
static bool irc_connected
static void Irc_Client_Mode_f(void)
static bool Irc_Proto_Password(const char *password)
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.
static const char IRC_INVITE_FOR_A_GAME[]
static irc_bucket_t irc_bucket
static void Irc_Client_CmdRplWhoisidle(const char *params, const char *trailing)
static void Irc_Client_Who_f(void)
static bool Irc_Proto_Notice(const char *target, const char *text)
static bool Irc_Client_Join(const char *channel, const char *password)
static void Irc_ParseName(const char *mask, char *nick, size_t size, irc_nick_prefix_t *prefix)
static char irc_userListOrdered[IRC_MAX_USERLIST][MAX_VAR]
static bool Irc_Proto_Msg(const char *target, const char *text)
#define IRC_CTCP_MARKER_CHR
static irc_channel_t ircChan
static cvar_t * irc_logConsole
static cvar_t * irc_send_buffer
static cvar_t * irc_characterBucketBurst
static void Irc_Proto_Pong(const char *nick, const char *server, const char *cookie)
static cvar_t * irc_showIfNotInMenu
static void Irc_Client_CmdRplWhoisaccount(const char *params, const char *trailing)
static void Irc_Client_Names_f(void)
static const char * Irc_Logic_GetChannelTopic(const irc_channel_t *channel)
static bool static bool Irc_Proto_ParseServerMsg(const char *txt, size_t txt_len, irc_server_msg_t *msg)
static memPool_t * cl_ircSysPool
static void Irc_Client_CmdRplEndofnames(const char *params, const char *trailing)
static irc_channel_t * chan
static void Irc_Client_CmdJoin(const char *prefix, const char *params, const char *trailing)
#define IRC_CTCP_MARKER_STR
#define IRC_RECV_BUF_SIZE
static void Irc_Logic_SendMessages(void)
static bool Irc_Proto_Join(const char *channel, const char *password)
static cvar_t * irc_messageBucketBurst
static bool Irc_Proto_Kick(const char *channel, const char *nick, const char *reason)
static void Irc_Net_Send(const char *msg, size_t msg_len)
static bool Irc_Proto_Connect(const char *host, const char *port)
static void Irc_Client_CmdRplWhoisserver(const char *params, const char *trailing)
static bool Irc_Proto_User(const char *user, bool invisible, const char *name)
static bool Irc_Proto_Part(const char *channel)
static struct net_stream * irc_stream
static void Irc_Client_CmdKick(const char *prefix, const char *params, const char *trailing)
static cvar_t * irc_characterBucketRate
static void Irc_Client_CmdPart(const char *prefix, const char *trailing)
static void Irc_Client_Kick_f(void)
static void Irc_Client_PrivMsg_f(void)
static void Irc_Client_CmdTopic(const char *prefix, const char *trailing)
static bool Irc_Proto_Enqueue(const char *msg, size_t msg_len)
static void Irc_Client_Topic_f(void)
static void Irc_Input_Activate_f(void)
void Irc_Logic_Frame(void)
static void Irc_Client_Join_f(void)
static void Irc_UserClick_f(void)
Adds the username you clicked to your input buffer.
static void Irc_Client_CmdMode(const char *prefix, const char *params, const char *trailing)
static void Irc_Logic_RemoveChannelName(irc_channel_t *channel, const char *nick)
Removes a username from the channel username list.
static void Irc_Client_Part_f(void)
static bool Irc_Proto_PollServerMsg(irc_server_msg_t *msg, bool *msg_complete)
static void Irc_Client_Whois_f(void)
static bool Irc_Proto_Topic(const char *channel, const char *topic)
static bool Irc_Proto_Who(const char *nick)
static bool Irc_Proto_Whois(const char *nick)
static void Irc_Input_Deactivate_f(void)
static cvar_t * irc_server
static void Irc_Disconnect_f(void)
static bool Irc_Proto_Whowas(const char *nick)
static void Irc_Client_Msg_f(void)
Send a message from menu or commandline.
static bool Irc_Net_Disconnect(void)
static void Irc_Client_CmdQuit(const char *prefix, const char *params, const char *trailing)
static char irc_buffer[4096]
static void Irc_Client_CmdRplNamreply(const char *params, const char *trailing)
IRC client header for UFO:AI.
const char * CL_Translate(const char *t)
int CL_Milliseconds(void)
Primary header for client.
const char * Cmd_Argv(int arg)
Returns a given argument.
const char * Cmd_Args(void)
Returns a single string containing argv(1) to argv(argc()-1).
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
void Cmd_AddCommand(const char *cmdName, xcommand_t function, const char *desc)
Add a new command to the script interface.
void Cbuf_AddText(const char *format,...)
Adds command text at the end of the buffer.
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
void Com_Printf(const char *const fmt,...)
cvar_t * masterserver_url
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
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).
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.
#define Mem_DeletePool(pool)
#define Mem_PoolAllocTypeN(type, n, pool)
#define Mem_CreatePool(name)
#define Mem_AllocTypeN(type, n)
#define Mem_AllocType(type)
#define Mem_PoolAllocType(type, pool)
void NET_StreamEnqueue(struct net_stream *s, const char *data, int len)
Enqueue a network message into a stream.
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.
int NET_StreamDequeue(struct net_stream *s, char *data, int len)
void NET_StreamFree(struct net_stream *s)
Call NET_StreamFree to dump the whole thing right now.
void format(__printf__, 1, 2)))
QGL_EXTERN GLuint GLchar GLuint * len
QGL_EXTERN GLuint GLsizei GLsizei * length
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
void S_StartLocalSample(const char *s, float volume)
Plays a sample without spatialization.
#define SND_VOLUME_DEFAULT
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
int Q_StringSort(const void *string1, const void *string2)
Compare two strings.
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
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...
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
struct irc_bucket_message_s * next
irc_bucket_message_t * first_msg
unsigned int character_size
unsigned int message_size
union irc_command_t::@066033050175334023300264044126211266013240245205 id
union irc_server_msg_t::@212327376166243107002225173133222274261315230343 id
char params[IRC_SEND_BUF_SIZE]
char prefix[IRC_SEND_BUF_SIZE]
char trailing[IRC_SEND_BUF_SIZE]
char string[IRC_SEND_BUF_SIZE]
void UI_ResetData(int dataId)
Reset a shared data. Type became NONE and value became nullptr.
void UI_RegisterText(int dataId, const char *text)
share a text with a data id
void UI_RegisterLinkedListText(int dataId, linkedList_t *text)
share a linked list of text with a data id
void UI_ExecuteConfunc(const char *fmt,...)
Executes confunc - just to identify those confuncs in the code - in this frame.
void UI_TextScrollEnd(const char *nodePath)
Scroll to the bottom.
uiNode_t * UI_PushWindow(const char *name, const char *parentName, linkedList_t *params)
Push a window onto the window stack.
void UI_PopWindow(bool all)
Pops a window from the window stack.
uiNode_t * UI_GetActiveWindow(void)
Returns the current active window from the window stack or nullptr if there is none.
const char * UI_GetActiveWindowName(void)
Returns the name of the current window.