FS2_Open
Open source remastering of the Freespace 2 engine
chat_api.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 2005. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 #include "globalincs/pstypes.h"
11 #include "network/chat_api.h"
12 
13 #ifdef SCP_UNIX
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #ifdef SCP_SOLARIS
19 #include <sys/filio.h>
20 #endif
21 #include <netinet/in.h>
22 #include <sys/select.h>
23 #include <errno.h>
24 #include <arpa/inet.h>
25 #include <netdb.h>
26 
27 #define WSAGetLastError() (errno)
28 #else
29 #include <winsock.h>
30 typedef int socklen_t;
31 #endif
32 
33 #include <stdio.h>
34 
35 
36 #define MAXCHATBUFFER 500
37 
41 char Nick_name[33];
43 int Nick_variety = 0;
44 char szChat_channel[33] = "";
46 char Chat_tracker_id[65];
51 char User_req_tracker_id[100] = ""; //These are oversized for saftey
52 char User_req_channel[100] = "";
53 char *User_list = NULL;
54 char *Chan_list = NULL;
62 
66 
67 // Unix version of snprintf always adds nul, but the windows version doesn't
68 #ifdef _WIN32
69 #define SSIZE(x) (sizeof((x))-1)
70 #else
71 #define SSIZE(x) (sizeof((x)))
72 #endif
73 
74 void ChatInit(void)
75 {
77  memset(Nick_name, 0, sizeof(Nick_name));
78  memset(Orignial_nick_name, 0, sizeof(Orignial_nick_name));
79  Nick_variety = 0;
80  memset(szChat_channel, 0, sizeof(szChat_channel));
81  memset(Input_chat_buffer, 0, sizeof(Input_chat_buffer));
82  memset(Chat_tracker_id, 0, sizeof(Chat_tracker_id));
87  memset(User_req_tracker_id, 0, sizeof(User_req_tracker_id));
88  memset(User_req_channel, 0, sizeof(User_req_channel));
89  User_list = NULL;
90  Chan_list = NULL;
91  Socket_connected = 0;
93  Joining_channel = 0;
94  Joined_channel = 0;
96  GettingUserTID = 0;
98 
99 }
100 
101 
102 // Return codes:
103 //-2 Already connected
104 //-1 Failed to connect
105 // 0 Connecting
106 // 1 Connected
107 // Call it once with the server IP address, and it will return immediately
108 // with 0. Keep calling it until it returns something other than 0
109 // note: the nickname may be changed if someone with that name already
110 // exists (Scourge1 for instance)
111 int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
112 {
113  short chat_port;
114  char chat_server[50];
115  char *p;
116  unsigned long argp = 1;
117  char signon_str[100];
118 
119  if(!Socket_connecting)
120  {
121  unsigned long iaddr;
122 
123  strncpy(Nick_name, nickname, sizeof(Nick_name)-1);
124  strncpy(Orignial_nick_name, nickname, sizeof(Orignial_nick_name)-1);
125  strncpy(Chat_tracker_id, trackerid, sizeof(Chat_tracker_id)-1);
126 
127  Firstuser = NULL;
128  Firstcommand = NULL;
131 
132  p = strchr(serveraddr,':');
133 
134  if(NULL==p)
135  {
136  return -1;
137  }
138 
139  memset(chat_server, 0, sizeof(chat_server));
140  strncpy(chat_server,serveraddr,(p-serveraddr));
141  chat_server[p-serveraddr] = '\0';
142  chat_port = (short)atoi(p+1);
143  if(0==chat_port)
144  {
145  return -1;
146  }
147 
148  Chatsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
149 
150  if(INVALID_SOCKET == Chatsock)
151  {
152  return -1;
153  }
154 
155  memset( &Chataddr, 0, sizeof(SOCKADDR_IN) );
156  Chataddr.sin_family = AF_INET;
157  Chataddr.sin_addr.s_addr = INADDR_ANY;
158  Chataddr.sin_port = 0;
159 
160  if (SOCKET_ERROR==bind(Chatsock, (SOCKADDR*)&Chataddr, sizeof (sockaddr)))
161  {
162  return -1;
163  }
164 
165  ioctlsocket(Chatsock, FIONBIO, &argp);
166 
167  // first try and resolve by name
168  iaddr = inet_addr( chat_server );
169  if ( iaddr == INADDR_NONE ) {
170  HOSTENT *he;
171  he = gethostbyname(chat_server);
172  if(!he)
173  {
174  return 0;
175  }
176  memcpy(&iaddr, he->h_addr_list[0],4);
177  }
178 
179  memcpy(&Chataddr.sin_addr.s_addr, &iaddr,4);
180 
181  Chataddr.sin_port = htons( chat_port );
182 
183  if(SOCKET_ERROR == connect(Chatsock,(SOCKADDR *)&Chataddr,sizeof(SOCKADDR_IN)))
184  {
186  {
187  Socket_connecting = 1;
188  return 0;
189  }
190  }
191  else
192  {
193  //This should never happen, connect should always return WSAEWOULDBLOCK
194  Socket_connecting = 1;
195  Socket_connected = 1;
196  return 1;
197  }
198  }
199  else
200  {
202  {
203  return 1;
204  }
205 
206  if(!Socket_connected)
207  {
208  //Do a few select to check for an error, or to see if we are writeable (connected)
209  fd_set write_fds,error_fds;
210  TIMEVAL timeout;
211 
212  timeout.tv_sec=0;
213  timeout.tv_usec=0;
214 
215  FD_ZERO(&write_fds);
216  FD_SET(Chatsock, &write_fds);
217  //Writable -- that means it's connected
218  if (select(Chatsock+1, NULL, &write_fds, NULL, &timeout) > 0)
219  {
220  // make sure that we don't have any connect() errors (since it's non-blocking)
221  int err_val = 0;
222  size_t err_val_size = sizeof(err_val);
223  getsockopt(Chatsock, SOL_SOCKET, SO_ERROR, (char*)&err_val, (socklen_t*)&err_val_size);
224 
225  if (err_val)
226  {
227  if (err_val != WSAEWOULDBLOCK)
228  {
229  return -1;
230  }
231 
232  return 0;
233  }
234 
235  Socket_connected = 1;
236  memset(signon_str, 0, sizeof(signon_str));
237  snprintf(signon_str, SSIZE(signon_str), NOX("/USER %s %s %s :%s"), NOX("user"), NOX("user"), NOX("user"), Chat_tracker_id);
238  SendChatString(signon_str, 1);
239  snprintf(signon_str, SSIZE(signon_str), NOX("/NICK %s"), Nick_name);
240  SendChatString(signon_str,1);
241  return 0;
242  //Now we are waiting for Chat_server_connected
243  }
244  FD_ZERO(&error_fds);
245  FD_SET(Chatsock,&error_fds);
246  //error -- that means it's not going to connect
247  if ( select(Chatsock+1, NULL, NULL, &error_fds, &timeout) )
248  {
249  return -1;
250  }
251 
252  return 0;
253  }
254  }
255 
256  return 0;
257 }
258 
263 {
264  if(!Socket_connected) return;
265  SendChatString(NOX("/QUIT"),1);
266  shutdown(Chatsock,2);
268  Socket_connecting = 0;
269  Socket_connected = 0;
270  Input_chat_buffer[0] = '\0';
271  if(User_list)
272  {
274  User_list = NULL;
275  }
276  if(Chan_list)
277  {
279  Chan_list = NULL;
280  }
281 
283  Joining_channel = 0;
284  Joined_channel = 0;
287  return;
288 }
289 
290 // returns NULL if no line is there to print, otherwise returns a string to
291 // print (all preformatted of course)
292 char * GetChatText()
293 {
294 
295  if(!Socket_connected) return NULL;
296 
297  //ChatGetString will do the formatting
298  return ChatGetString();
299 
300 }
301 
305 const char * SendChatString(const char *line,int raw)
306 {
307  char szCmd[200];
308  char szTarget[50];
309  if(!Socket_connected) return NULL;
310 
311  szCmd[sizeof(szCmd)-1] = '\0';
312  szTarget[sizeof(szTarget)-1] = '\0';
313 
314  if(line[0]=='/')
315  {
316 
317  //Start off by getting the command
318  strncpy(szCmd, GetWordNum(0, line+1), sizeof(szCmd)-1);
319  if(stricmp(szCmd,NOX("msg"))==0)
320  {
321  strncpy(szTarget, GetWordNum(1, line+1), sizeof(szTarget)-1);
322  snprintf(szCmd, SSIZE(szCmd), NOX("PRIVMSG %s :%s\n\r"), szTarget, line+strlen(NOX("/msg "))+strlen(szTarget)+1);
323  send(Chatsock,szCmd,strlen(szCmd),0);
324  szCmd[strlen(szCmd)-2] = '\0';
325  return ParseIRCMessage(szCmd,MSG_LOCAL);
326 
327  }
328  if(stricmp(szCmd,NOX("me"))==0)
329  {
330  snprintf(szCmd, SSIZE(szCmd), NOX("PRIVMSG %s :\001ACTION %s\001\n\r"), szChat_channel,line+strlen(NOX("/me ")));
331  send(Chatsock,szCmd,strlen(szCmd),0);
332  szCmd[strlen(szCmd)-2] = '\0';
333  return ParseIRCMessage(szCmd,MSG_LOCAL);
334 
335  }
336  if(stricmp(szCmd,NOX("xyz"))==0)
337  {
338  //Special command to send raw irc commands
339  snprintf(szCmd, SSIZE(szCmd), "%s\n\r", line+strlen(NOX("/xyz ")));
340  send(Chatsock,szCmd,strlen(szCmd),0);
341  return NULL;
342  }
343  if(stricmp(szCmd,NOX("list"))==0)
344  {
345  snprintf(szCmd, SSIZE(szCmd), "%s\n\r", line+1);
346  send(Chatsock,szCmd,strlen(szCmd),0);
347  return NULL;
348  }
349  if(raw)
350  {
351  snprintf(szCmd, SSIZE(szCmd), "%s\n\r", line+1);
352  send(Chatsock,szCmd,strlen(szCmd),0);
353  return NULL;
354  }
355  return XSTR("Unrecognized command",634);
356 
357  }
358  else
359  {
360  if(szChat_channel[0])
361  {
362  snprintf(szCmd, SSIZE(szCmd), NOX("PRIVMSG %s :%s\n\r"), szChat_channel, line);
363  send(Chatsock,szCmd,strlen(szCmd),0);
364  if(strlen(szCmd) >= 2){
365  szCmd[strlen(szCmd)-2] = '\0';
366  return ParseIRCMessage(szCmd,MSG_LOCAL);
367  }
368 
369  return NULL;
370  }
371  }
372 
373  return NULL;
374 }
375 
376 
377 // Returns a structure which contains a command and possible some data (like
378 // a user joining or leaving) if one is waiting
379 // This tells you if you need to add a user from the userlist, remove a user,
380 // etc. Also for status messages, like if you get knocked
381 // off the server for some reason.
383 {
384  if(!Socket_connected) return NULL;
385  return GetChatCommandFromQueue();
386 }
387 
388 // This function returns a list of users in the current channel, in one
389 // string, separated by spaces, terminated by a null
390 // (Spaces aren't allowed as part of a nickname)
392 {
393  int iuser_list_length = 0;;
394  if(User_list)
395  {
397  User_list = NULL;
398  }
399  if(!Socket_connected) return NULL;
400 
401  Curruser = Firstuser;
402  while(Curruser)
403  {
404  iuser_list_length += strlen(Curruser->nick_name)+1;
405  Curruser = Curruser->next;
406  }
407  Curruser = Firstuser;
408  User_list = (char *)vm_malloc(iuser_list_length+1);
409  User_list[0] = '\0';
410  while(Curruser)
411  {
412  strcat(User_list,Curruser->nick_name);
413  strcat(User_list," ");
414  Curruser = Curruser->next;
415  }
416 
417  return User_list;
418 }
419 
420 // Call this to set/join a channel. Since we can't be sure that we will be
421 // able to join that channel, check it for completion
422 // You can't be in more than one channel at a time with this API, so you
423 // leave the current channel before trying to join
424 // a new one. Because of this if the join fails, make sure you try to join
425 // another channel, or the user won't be able to chat
426 //-1 Failed to join
427 // 0 joining
428 // 1 successfully joined
430 {
431  char partstr[100];
432  if(!Socket_connected) return -1;
433 
434  partstr[sizeof(partstr)-1] = '\0';
435 
436  if(Joining_channel==1)
437  {
438  if(Joined_channel==1)
439  {
440  //We made it in!
441  Joining_channel = 0;
442  return 1;
443  }
444  else if(Joined_channel==-1)
445  {
446  //Error -- we got a message that the channel was invite only, or we were banned or something
447  Joining_channel = 0;
449  return -1;
450  }
451  }
452  else
453  {
454  if(szChat_channel[0])
455  {
456  snprintf(partstr, SSIZE(partstr), NOX("/PART %s"), szChat_channel);
457  SendChatString(partstr,1);
458  }
459  strncpy(szChat_channel, channel, sizeof(szChat_channel)-1);
460  snprintf(partstr, SSIZE(partstr), NOX("/JOIN %s"), szChat_channel);
461  SendChatString(partstr,1);
462  Joining_channel = 1;
463  Joined_channel = 0;
464  }
465 
466  return 0;
467 }
468 
469 
470 char *ChatGetString(void)
471 {
472  fd_set read_fds;
473  TIMEVAL timeout;
474  char ch[2];
475  char *p;
476  int bytesread;
477  static char return_string[MAXCHATBUFFER];
478 
479  timeout.tv_sec=0;
480  timeout.tv_usec=1;
481 
482  FD_ZERO(&read_fds);
483  FD_SET(Chatsock,&read_fds);
484  //Writable -- that means it's connected
485 #ifdef WIN32
486  while ( select(0, &read_fds, NULL, NULL, &timeout) )
487 #else
488  while ( select(Chatsock+1, &read_fds, NULL, NULL, &timeout) )
489 #endif
490  {
491  bytesread = recv(Chatsock,ch,1,0);
492  if(bytesread)
493  {
494  ch[1] = '\0';
495 
496  if((ch[0] == 0x0a)||(ch[0]==0x0d))
497  {
498  if( !strlen(Input_chat_buffer) )
499  {
500  //Blank line, ignore it
501  return NULL;
502  }
503  strncpy(return_string, Input_chat_buffer, sizeof(return_string)-1);
504  Input_chat_buffer[0] = '\0';
505 
506  p = ParseIRCMessage(return_string,MSG_REMOTE);
507 
508  return p;
509  }
512  }
513  else
514  {
515  //Select said we had read data, but 0 bytes read means disconnected
517  return NULL;
518  }
519 
520  }
521  return NULL;
522 }
523 
524 
525 char * GetWordNum(int num, const char * l_String)
526 {
527  static char strreturn[600];
528  static char ptokstr[600];
529  char seps[10] = NOX(" \n\r\t");
530  char *token,*strstart;
531 
532  strreturn[sizeof(strreturn)-1] = '\0';
533  ptokstr[sizeof(ptokstr)-1] = '\0';
534 
535  strstart = ptokstr;
536 
537  strncpy(ptokstr, l_String, sizeof(ptokstr)-1);
538 
539  token=strtok(ptokstr,seps);
540 
541  for(int i=0;i!=num;i++)
542  {
543  token=strtok(NULL,seps);
544  }
545  if(token)
546  {
547  strncpy(strreturn, token, sizeof(strreturn)-1);
548  }
549  else
550  {
551  return "";
552  }
553  //check for the ':' char....
554  if(token[0]==':')
555  {
556  //Its not pretty, but it works, return the rest of the string
557  strncpy(strreturn, l_String+((token-strstart)+1), sizeof(strreturn)-1);
558  }
559 
560  //return the appropriate response.
561  return strreturn;
562 }
563 
564 int AddChatUser(char *nickname)
565 {
566  Curruser = Firstuser;
567  while(Curruser)
568  {
569  if(stricmp(nickname,Curruser->nick_name)==0) return 0;
570  Curruser = Curruser->next;
571  }
572 
573  Curruser = Firstuser;
574  if(Firstuser==NULL)
575  {
576  Firstuser = (Chat_user *)vm_malloc(sizeof(Chat_user));
577  Assert(Firstuser);
578  strncpy(Firstuser->nick_name, nickname, sizeof(Firstuser->nick_name)-1);
579  Firstuser->next = NULL;
580  AddChatCommandToQueue(CC_USER_JOINING,nickname,strlen(nickname)+1);
581  return 1;
582  }
583  else
584  {
585  while(Curruser->next)
586  {
587  Curruser = Curruser->next;
588  }
589  Curruser->next = (Chat_user *)vm_malloc(sizeof(Chat_user));
590  Curruser = Curruser->next;
591  Assert(Curruser);
592  strncpy(Curruser->nick_name, nickname, sizeof(Curruser->nick_name)-1);
593  Curruser->next = NULL;
594  AddChatCommandToQueue(CC_USER_JOINING,nickname,strlen(nickname)+1);
595  return 1;
596  }
597 
598 }
599 
600 int RemoveChatUser(char *nickname)
601 {
602  Chat_user *prv_user = NULL;
603 
604  Curruser = Firstuser;
605  while(Curruser)
606  {
607  if(stricmp(nickname,Curruser->nick_name)==0)
608  {
609  if(prv_user)
610  {
611  prv_user->next = Curruser->next;
612 
613  }
614  else
615  {
616  Firstuser = Curruser->next;
617  }
618  AddChatCommandToQueue(CC_USER_LEAVING,Curruser->nick_name,strlen(Curruser->nick_name)+1);
619  vm_free(Curruser);
620  return 1;
621  }
622  prv_user = Curruser;
623  Curruser = Curruser->next;
624  }
625  return 0;
626 
627 }
628 
630 {
631  Chat_user *tmp_user = NULL;
632  Curruser = Firstuser;
633  while(Curruser)
634  {
635  tmp_user = Curruser->next;
636  AddChatCommandToQueue(CC_USER_LEAVING,Curruser->nick_name,strlen(Curruser->nick_name)+1);
637  vm_free(Curruser);
638  Curruser = tmp_user;
639  }
640  Firstuser = NULL;
641 }
642 
643 
644 char * ParseIRCMessage(char *Line, int iMode)
645 {
646  char szRemLine[MAXLOCALSTRING] ="";
647  char *pszTempStr;
648  char szPrefix[MAXLOCALSTRING] = "";
649  char szHackPrefix[MAXLOCALSTRING] = "";
650  char szTarget[MAXLOCALSTRING] = "";
651  char szNick[MAXLOCALSTRING] = "";
652  char szCmd[MAXLOCALSTRING] = "";
653  char szCTCPCmd[MAXLOCALSTRING] = "";
654 
655  static char szResponse[MAXLOCALSTRING] = "";
656 
657  int iPrefixLen = 0; // JAS: Get rid of optimized warning
658 
659  szRemLine[MAXLOCALSTRING-1] = '\0';
660  szPrefix[MAXLOCALSTRING-1] = '\0';
661  szHackPrefix[MAXLOCALSTRING-1] = '\0';
662  szTarget[MAXLOCALSTRING-1] = '\0';
663  szNick[MAXLOCALSTRING-1] = '\0';
664  szCmd[MAXLOCALSTRING-1] = '\0';
665  szCTCPCmd[MAXLOCALSTRING-1] = '\0';
666 
667  szResponse[MAXLOCALSTRING-1] = '\0';
668 
669  if(strlen(Line)>=MAXLOCALSTRING)
670  {
671  return NULL;
672  }
673  //Nick included....
674  if(iMode==MSG_REMOTE)
675  {
676  strncpy(szRemLine, Line, sizeof(szRemLine)-1);
677  //Start by getting the prefix
678  if(Line[0]==':')
679  {
680  //
681  pszTempStr=GetWordNum(0,Line+1);
682  strncpy(szPrefix, pszTempStr, sizeof(szPrefix)-1);
683  strncpy(szHackPrefix, pszTempStr, sizeof(szHackPrefix)-1);
684  strncpy(szRemLine, Line+1+strlen(szPrefix), sizeof(szRemLine)-1);
685  }
686  //Next, get the Nick
687  pszTempStr=strtok(szHackPrefix,"!");
688  if(pszTempStr)
689  {
690  strncpy(szNick, pszTempStr, sizeof(szNick)-1);
691  }
692  else
693  {
694  strncpy(szNick,szPrefix,31);
695  szNick[31]=0;
696  }
697  iPrefixLen=strlen(szPrefix);
698  }
699  else if(iMode==MSG_LOCAL)
700  {
701  strncpy(szRemLine, Line, sizeof(szRemLine)-1);
702  strncpy(szNick, Nick_name, sizeof(szNick)-1);
703  strncpy(szPrefix, Nick_name, sizeof(szPrefix)-1);
704  iPrefixLen=-2;
705  }
706  //Next is the command
707  pszTempStr=GetWordNum(0,szRemLine);
708  if(pszTempStr[0])
709  {
710  strncpy(szCmd, pszTempStr, sizeof(szCmd)-1);
711  }
712  else
713  {
714  //Shouldn't ever happen, but we can't be sure of what the host will send us.
715  return NULL;
716  }
717 
718  //Move the szRemLine string up
719  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+2, sizeof(szRemLine)-1);
720  //Now parse the commands!
721  if(stricmp(szCmd,NOX("PRIVMSG"))==0)
722  {
723  pszTempStr=GetWordNum(0,szRemLine);
724  strncpy(szTarget, pszTempStr, sizeof(szTarget)-1);
725  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+4, sizeof(szRemLine)-1);
726  if(szRemLine[0]==':')
727  {
728  strncpy(szCTCPCmd, GetWordNum(0,szRemLine+1), sizeof(szCTCPCmd)-1);
729  if(szCTCPCmd[strlen(szCTCPCmd)-1]==0x01) szCTCPCmd[strlen(szCTCPCmd)-1]=0x00;
730 
731  }
732  else
733  {
734  strncpy(szCTCPCmd, GetWordNum(0,szRemLine), sizeof(szCTCPCmd)-1);
735  if(szCTCPCmd[strlen(szCTCPCmd)-1]==0x01) szCTCPCmd[strlen(szCTCPCmd)-1]=0x00;
736  }
737  if(szCTCPCmd[0]==0x01)
738  {
739  //Handle ctcp message
740  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+strlen(szCTCPCmd)+6, sizeof(szRemLine)-1);
741  szRemLine[strlen(szRemLine)-1] = '\0';//null out the ending 0x01
742  if(stricmp(szCTCPCmd+1,NOX("ACTION"))==0)
743  {
744  //Posture
745  snprintf(szResponse, SSIZE(szResponse), "* %s %s", szNick, szRemLine);
746  return szResponse;
747  }
748  if(iMode==MSG_LOCAL)
749  {
750  strncpy(szHackPrefix, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+4, sizeof(szHackPrefix)-1);
751  szRemLine[strlen(szRemLine)-1] = '\0';
752  snprintf(szResponse, SSIZE(szResponse), NOX("** CTCP %s %s %s"), szTarget, szCTCPCmd+1, szRemLine);
753  return szResponse;
754  }
755  if(stricmp(szCTCPCmd+1,NOX("PING"))==0)
756  {
757  snprintf(szResponse, SSIZE(szResponse), NOX("/NOTICE %s :\001PING %s\001"), szNick, szRemLine);//Don't need the trailing \001 because szremline has it.
758  SendChatString(szResponse,1);
759  return NULL;
760  }
761  if(stricmp(szCTCPCmd+1,NOX("VERSION"))==0)
762  {
763  return NULL;
764  }
765  strncpy(szRemLine, 1 + GetWordNum(0,Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+4), sizeof(szRemLine)-1);
766  szRemLine[strlen(szRemLine)-1] = '\0';
767  snprintf(szResponse, SSIZE(szResponse), NOX("** CTCP Message from %s (%s)"), szNick, szRemLine);
768  return szResponse;
769 
770  }
771  //differentiate between channel and private
772  if(szTarget[0]=='#')
773  {
774  pszTempStr=GetWordNum(0,szRemLine);
775  snprintf(szResponse, SSIZE(szResponse), "[%s] %s", szNick, pszTempStr);
776  return szResponse;
777  }
778  else
779  {
780  if(iMode == MSG_LOCAL)
781  {
782  pszTempStr=GetWordNum(0,szRemLine);
783  snprintf(szResponse, SSIZE(szResponse), NOX("Private Message to <%s>: %s"), szNick, pszTempStr);
784  }
785  else
786  {
787  pszTempStr=GetWordNum(0,szRemLine);
788  snprintf(szResponse, SSIZE(szResponse), NOX("Private Message from <%s>: %s"), szNick, pszTempStr);
789  }
790  return szResponse;
791  }
792 
793  }
794  //don't handle any other messages locally.
795  if(iMode==MSG_LOCAL)
796  {
797  return NULL;
798  }
799 
800  if(stricmp(szCmd,NOX("NOTICE"))==0)
801  {
802 
803 
804  pszTempStr=GetWordNum(0,szRemLine);
805  strncpy(szTarget, pszTempStr, sizeof(szTarget)-1);
806  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+4, sizeof(szRemLine)-1);
807  if(szRemLine[0]==':')
808  {
809  strncpy(szCTCPCmd, GetWordNum(0,szRemLine+1), sizeof(szCTCPCmd)-1);
810  if(szCTCPCmd[strlen(szCTCPCmd)-1]==0x01) szCTCPCmd[strlen(szCTCPCmd)-1]=0x00;
811 
812  }
813  else
814  {
815  strncpy(szCTCPCmd, GetWordNum(0,szRemLine), sizeof(szCTCPCmd)-1);
816  if(szCTCPCmd[strlen(szCTCPCmd)-1]==0x01) szCTCPCmd[strlen(szCTCPCmd)-1]=0x00;
817  }
818  if(szCTCPCmd[0]==0x01)
819  {
820  //Handle ctcp message
821  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+strlen(szCTCPCmd)+6, sizeof(szRemLine)-1);
822  szRemLine[strlen(szRemLine)-1] = '\0';//null out the ending 0x01
823  if(stricmp(szCTCPCmd+1,NOX("PING"))==0)
824  {
825  return NULL;
826  }
827 
828  //Default message
829  strncpy(szRemLine, 1 + GetWordNum(0,Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+4), sizeof(szRemLine)-1);
830  szRemLine[strlen(szRemLine)-1] = '\0';
831  snprintf(szResponse, SSIZE(szResponse), XSTR("** CTCP Message from %s (%s)", 635), szNick, szRemLine);
832  return szResponse;
833 
834  }
835  snprintf(szResponse, SSIZE(szResponse), "%s", szRemLine);
836  return NULL;
837  }
838  if(stricmp(szCmd,NOX("JOIN"))==0)
839  {
840  //see if it is me!
841  if(stricmp(Nick_name,szNick)==0)
842  {
843  Joined_channel = 1;
844  if(stricmp(szChat_channel,NOX("#autoselect"))==0)
845  {
846  strncpy(szChat_channel, GetWordNum(0,szRemLine), sizeof(szChat_channel)-1);
848 
849  }
850  }
851 
852  pszTempStr=GetWordNum(0,szRemLine);
853  strncpy(szTarget, pszTempStr, sizeof(szTarget)-1);
854 
855  AddChatUser(szNick);
856  snprintf(szResponse, SSIZE(szResponse), XSTR("** %s has joined %s", 636), szNick, szTarget);
857  return NULL;//szResponse;
858  //Add them to the userlist too!
859  }
860  if(stricmp(szCmd,NOX("PART"))==0)
861  {
862  pszTempStr=GetWordNum(0,szRemLine);
863  strncpy(szTarget, pszTempStr, sizeof(szTarget)-1);
864  strncpy(szRemLine, Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+3, sizeof(szRemLine)-1);
865  //see if it is me!
866  if(stricmp(Nick_name,szNick)==0)
867  {
869  }
870 
871  RemoveChatUser(szNick);
872  return NULL;
873  //Remove them to the userlist too!
874  }
875  if(stricmp(szCmd,NOX("KICK"))==0)
876  {
877  pszTempStr=GetWordNum(0,szRemLine);
878  strncpy(szTarget, pszTempStr, sizeof(szTarget)-1);
879  pszTempStr=GetWordNum(1,szRemLine);
880  strncpy(szHackPrefix, pszTempStr, sizeof(szHackPrefix)-1);
881  pszTempStr=GetWordNum(2,szRemLine);
882  //see if it is me!
883  if(stricmp(Nick_name,GetWordNum(1,szRemLine))==0)
884  {
885  //Yup, it's me!
886  szChat_channel[0] = '\0';
889  }
890  snprintf(szResponse, SSIZE(szResponse), XSTR("*** %s has kicked %s from channel %s (%s)", 637), szNick, szHackPrefix, szTarget, pszTempStr);
891  //Remove them to the userlist too!
892  RemoveChatUser(szNick);
893  return szResponse;
894 
895  }
896  if(stricmp(szCmd,NOX("NICK"))==0)
897  {
898  //see if it is me!
899  if(stricmp(Nick_name,szNick)==0)
900  {
901  //Yup, it's me!
902  strncpy(Nick_name, GetWordNum(0,szRemLine), sizeof(Nick_name)-1);
903  }
904  char nicks[70];
905  snprintf(nicks, SSIZE(nicks), "%s %s", szNick, GetWordNum(0, szRemLine));
906  AddChatCommandToQueue(CC_NICKCHANGED,nicks,strlen(nicks)+1);
907  RemoveChatUser(szNick);
908  AddChatUser(GetWordNum(0,szRemLine));
909  snprintf(szResponse, SSIZE(szResponse), XSTR("*** %s is now known as %s", 638), szNick, GetWordNum(0, szRemLine));
910  return szResponse;
911  }
912  if(stricmp(szCmd,NOX("PING"))==0)
913  {
914  //respond with pong (GetWordNum(0,szRemLine))
915  snprintf(szResponse, SSIZE(szResponse), NOX("/PONG :%s"), GetWordNum(0, szRemLine));
916  SendChatString(szResponse,1);
917  return NULL;
918  }
919  if(stricmp(szCmd,NOX("MODE"))==0)
920  {
921  //Channel Mode info
922  return NULL;
923  }
924 
925 
926  if(stricmp(szCmd, "403")==0)
927  {
928  // ERR_NOSUCHCHANNEL - Used to indicate the given channel name is invalid.
929  Joined_channel = -1;
930  return NULL;
931  }
932 
933  if(stricmp(szCmd,"401")==0)
934  {
935  //This is whois user info, we can get their tracker info from here. -5
936  char szWhoisUser[33];
937  memset(szWhoisUser, 0, sizeof(szWhoisUser));
938  strncpy(szWhoisUser, GetWordNum(1,szRemLine), sizeof(szWhoisUser)-1);
941 
942  snprintf(szResponse, SSIZE(szResponse), XSTR("**Error: %s is not online!", 639), szWhoisUser);
943  return szResponse;
944 
945  }
946  if(stricmp(szCmd,"311")==0)
947  {
948  char szWhoisUser[33];
949  memset(szWhoisUser, 0, sizeof(szWhoisUser));
950  strncpy(szWhoisUser, GetWordNum(1,szRemLine), sizeof(szWhoisUser)-1);
951  //This is whois user info, we can get their tracker info from here. -5
952  strncpy(User_req_tracker_id, GetWordNum(5,szRemLine), sizeof(User_req_tracker_id)-1);
953  return NULL;
954  }
955  if(stricmp(szCmd,"319")==0)
956  {
957  char szWhoisUser[33];
958  memset(szWhoisUser, 0, sizeof(szWhoisUser));
959  strncpy(szWhoisUser, GetWordNum(1,szRemLine), sizeof(szWhoisUser)-1);
960  //This is whois channel info -- what channel they are on -2
961  strncpy(User_req_channel, GetWordNum(2,szRemLine), sizeof(User_req_channel)-1);
962  return NULL;
963  }
964 
965  //End of whois and we didn't get a channel means they aren't in a channel.
966  if(stricmp(szCmd,"318")==0)
967  {
968  if(!*User_req_channel)
969  {
970  User_req_channel[0] = '*';
971  }
972  }
973 
974 
975  if(stricmp(szCmd,"321")==0)
976  {
977  //start of channel list
979  GettingChannelList = 1;
980  return NULL;
981  }
982  if(stricmp(szCmd,"322")==0)
983  {
984  //channel list data
985  if(GettingChannelList == 1)
986  {
987  char channel_list_name[33];
988  char sztopic[200];
989  memset(channel_list_name, 0, sizeof(channel_list_name));
990  memset(sztopic, 0, sizeof(sztopic));
991  strncpy(sztopic, GetWordNum(3,szRemLine), sizeof(sztopic)-1);
992  strncpy(channel_list_name, GetWordNum(1,szRemLine), sizeof(channel_list_name)-1);
993  AddChannel(channel_list_name,(short)atoi(GetWordNum(2,szRemLine)),sztopic);
994  }
995  return NULL;
996  }
997  if(stricmp(szCmd,"323")==0)
998  {
999  //end of channel list
1000  GettingChannelList = 2;
1001  return NULL;
1002  }
1003  if(stricmp(szCmd,"324")==0)
1004  {
1005  //Channel Mode info
1006  return NULL;
1007  }
1008 
1009  if(stricmp(szCmd,"332")==0)
1010  {
1011  //Channel Topic, update status bar.
1012  if(stricmp(szChat_channel,szTarget)==0)
1013  {
1014  //strncpy(szChanTopic,GetWordNum(2,szRemLine),70);
1015  }
1016  //sprintf(NewMsg.Message,"*** %s has changed the topic to: %s",szNick,GetWordNum(2,szRemLine));
1017 
1018  return NULL;
1019  }
1020  if(stricmp(szCmd,NOX("TOPIC"))==0)
1021  {
1022  //Channel Topic, update status bar.
1023  if(stricmp(szChat_channel,szTarget)==0)
1024  {
1025  //strncpy(szChanTopic,GetWordNum(1,szRemLine),70);
1026  }
1027  //sprintf(NewMsg.Message,"*** %s has changed the topic to: %s",szNick,GetWordNum(1,szRemLine));
1028  return NULL;
1029  }
1030  if(stricmp(szCmd,NOX("QUIT"))==0)
1031  {
1032  //Remove the user!
1033  RemoveChatUser(szNick);
1034  return NULL;
1035  }
1036  if(stricmp(szCmd,"376")==0) //end of motd, trigger autojoin...
1037  {
1038  if (!Chat_server_connected)
1039  {
1041  }
1042 
1043  // end of motd
1044  strncpy(szResponse, PXO_CHAT_END_OF_MOTD_PREFIX, sizeof(szResponse)-1);
1045  return szResponse;
1046  }
1047  if((stricmp(szCmd,"377")==0)||
1048  (stricmp(szCmd,"372")==0))
1049  {
1050  //Stip the message, and display it.
1051  pszTempStr=GetWordNum(3,Line);
1052  snprintf(szResponse, SSIZE(szResponse), "%s%s", PXO_CHAT_MOTD_PREFIX, pszTempStr);
1053  return szResponse;
1054  }
1055  //Ignore these messages
1056  if(((stricmp(szCmd,"366")==0))||
1057  (stricmp(szCmd,"333")==0) || //Who set the topic
1058  (stricmp(szCmd,"329")==0)) //Time Channel created
1059 
1060  {
1061  return NULL;
1062  }
1063  if(stricmp(szCmd,"353")==0)
1064  {
1065 
1066  //Names in the channel.
1067  pszTempStr = GetWordNum(3,Line+iPrefixLen+strlen(szCmd)+2);
1068  strncpy(szRemLine, pszTempStr, sizeof(szRemLine)-1);
1069  pszTempStr = strtok(szRemLine," ");
1070 
1071  while(pszTempStr)
1072  {
1073  if(pszTempStr[0]=='@')
1074  {
1075  AddChatUser(pszTempStr+1);
1076  }
1077  else if(pszTempStr[0]=='+')
1078  {
1079  AddChatUser(pszTempStr+1);
1080  }
1081  else
1082  {
1083  AddChatUser(pszTempStr);
1084  }
1085  pszTempStr=strtok(NULL," ");
1086  }
1087  return NULL;
1088  }
1089  //MOTD Codes
1090  if((stricmp(szCmd,"001")==0)||
1091  (stricmp(szCmd,"002")==0)||
1092  (stricmp(szCmd,"003")==0)||
1093  (stricmp(szCmd,"004")==0)||
1094  (stricmp(szCmd,"251")==0)||
1095  (stricmp(szCmd,"254")==0)||
1096  (stricmp(szCmd,"255")==0)||
1097  (stricmp(szCmd,"265")==0)||
1098  (stricmp(szCmd,"372")==0)||
1099  (stricmp(szCmd,"375")==0)
1100  )
1101  {
1102  return NULL;
1103  // return szResponse;
1104  }
1105  if(stricmp(szCmd,"432")==0)
1106  {
1107  //Channel Mode info
1108  snprintf(szResponse, SSIZE(szResponse), "%s", XSTR("Your nickname contains invalid characters", 640));
1110  return szResponse;
1111  }
1112  if(stricmp(szCmd,"433")==0)
1113  {
1114  //Channel Mode info
1115  char new_nick[33];
1116  snprintf(new_nick, SSIZE(new_nick), "%s%d", Orignial_nick_name, Nick_variety);
1117  strncpy(Nick_name, new_nick, sizeof(Nick_name)-1);
1118  Nick_variety++;
1119  snprintf(szResponse, SSIZE(szResponse), NOX("/NICK %s"), new_nick);
1120  SendChatString(szResponse,1);
1121  return NULL;
1122  }
1123  //Default print
1124  strncpy(szResponse, Line, sizeof(szResponse)-1);
1125  return NULL;
1126 
1127 }
1128 
1129 
1130 void AddChatCommandToQueue(int command,void *data,int len)
1131 {
1132  Currcommand = Firstcommand;
1133  if(Firstcommand==NULL)
1134  {
1135  Firstcommand = (Chat_command *)vm_malloc(sizeof(Chat_command));
1136  Assert(Firstcommand);
1137  Firstcommand->next = NULL;
1138  Currcommand = Firstcommand;
1139  }
1140  else
1141  {
1142  while(Currcommand->next)
1143  {
1144  Currcommand = Currcommand->next;
1145  }
1146  Currcommand->next = (Chat_command *)vm_malloc(sizeof(Chat_command));
1147  Assert(Currcommand->next);
1148  Currcommand = Currcommand->next;
1149  }
1150  Currcommand->command = (short)command;
1151  if(len&&data) memcpy(&Currcommand->data,data,len);
1152  Currcommand->next = NULL;
1153  return;
1154 }
1155 
1157 {
1158  static Chat_command response_cmd;
1159  Chat_command *tmp_cmd;
1160  if(!Firstcommand) return NULL;
1161  Currcommand = Firstcommand;
1162  memcpy(&response_cmd,Currcommand,sizeof(Chat_command));
1163  tmp_cmd = Currcommand->next;
1164  vm_free(Firstcommand);
1165  Firstcommand = tmp_cmd;
1166  return &response_cmd;
1167 }
1168 
1170 {
1171  Chat_command *tmp_cmd;
1172  Currcommand = Firstcommand;
1173 
1174  while(Currcommand)
1175  {
1176  tmp_cmd = Currcommand->next;
1177  vm_free(Currcommand);
1178  Currcommand = tmp_cmd;
1179  }
1180  Firstcommand = NULL;
1181 }
1182 
1183 
1185 {
1186  Chat_channel *tmp_chan;
1187  Currchannel = Firstchannel;
1188 
1189  while(Currchannel)
1190  {
1191  tmp_chan = Currchannel->next;
1192  vm_free(Currchannel);
1193  Currchannel = tmp_chan;
1194  }
1195  Firstchannel = NULL;
1196 
1197 
1198 }
1199 char *GetChannelList(void)
1200 {
1201  int ichan_list_length = 0;
1202  char sznumusers[10];
1203 
1204  if(GettingChannelList != 2) return NULL;
1205  if(!Socket_connected) return NULL;
1206 
1207  if(Chan_list)
1208  {
1209  vm_free(Chan_list);
1210  Chan_list = NULL;
1211  }
1212 
1213 
1214  Currchannel = Firstchannel;
1215  while(Currchannel)
1216  {
1217  ichan_list_length += strlen(Currchannel->topic)+1+strlen(Currchannel->channel_name)+1+5;//1 for the space, and 4 for the number of users 0000-9999 + space
1218  Currchannel = Currchannel->next;
1219  }
1220  Currchannel = Firstchannel;
1221  Chan_list = (char *)vm_malloc(ichan_list_length+1);
1222  memset(Chan_list, 0, ichan_list_length+1);
1223  while(Currchannel)
1224  {
1225  strcat(Chan_list,"$");
1226  strcat(Chan_list,Currchannel->channel_name);
1227  strcat(Chan_list," ");
1228  sprintf(sznumusers,"%d ",Currchannel->users);
1229  strcat(Chan_list,sznumusers);
1230  strcat(Chan_list,Currchannel->topic);//fgets
1231  strcat(Chan_list," ");
1232  Currchannel = Currchannel->next;
1233  }
1234  FlushChannelList();
1235  GettingChannelList = 0;
1236  return Chan_list;
1237 }
1238 
1239 void AddChannel(char *channel,unsigned short numusers,char *topic)
1240 {
1241  Currchannel = Firstchannel;
1242  if(Firstchannel==NULL)
1243  {
1244  Firstchannel = (Chat_channel *)vm_malloc(sizeof(Chat_channel));
1245  Assert(Firstchannel);
1246  strncpy(Firstchannel->channel_name, channel, sizeof(Firstchannel->channel_name)-1);
1247  strncpy(Firstchannel->topic, topic, sizeof(Firstchannel->topic)-1);
1248  Firstchannel->users = numusers;
1249  Firstchannel->next = NULL;
1250  Currchannel = Firstchannel;
1251  }
1252  else
1253  {
1254  while(Currchannel->next)
1255  {
1256  Currchannel = Currchannel->next;
1257  }
1258  Currchannel->next = (Chat_channel *)vm_malloc(sizeof(Chat_channel));
1259  Assert(Currchannel->next);
1260  Currchannel = Currchannel->next;
1261  strncpy(Currchannel->channel_name, channel, sizeof(Currchannel->channel_name)-1);
1262  strncpy(Currchannel->topic, topic, sizeof(Currchannel->topic)-1);
1263  Currchannel->users = numusers;
1264  }
1265  Currchannel->next = NULL;
1266  return;
1267 }
1268 
1269 
1270 char *GetTrackerIdByUser(char *nickname)
1271 {
1272  char szWhoisCmd[100];
1273 
1274 
1275  if(GettingUserTID)
1276  {
1278  {
1280  GettingUserTID = 0;
1281  return (char *)-1;
1282  }
1283 
1284  if(*User_req_tracker_id)
1285  {
1286  GettingUserTID = 0;
1287  return User_req_tracker_id;
1288  }
1289  }
1290  else
1291  {
1292  strncpy(Getting_user_tracker_info_for, nickname, sizeof(Getting_user_tracker_info_for)-1);
1293  snprintf(szWhoisCmd, SSIZE(szWhoisCmd), NOX("/WHOIS %s"), nickname);
1294  User_req_tracker_id[0] = '\0';
1295  SendChatString(szWhoisCmd,1);
1296  GettingUserTID = 1;
1297  }
1298  return NULL;
1299 }
1300 
1301 char *GetChannelByUser(char *nickname)
1302 {
1303  char szWhoisCmd[100];
1304 
1305  if(GettingUserChannel)
1306  {
1308  {
1310  GettingUserChannel = 0;
1311  return (char *)-1;
1312  }
1313  if(*User_req_channel)
1314  {
1315  GettingUserChannel = 0;
1316  return User_req_channel;
1317  }
1318  }
1319  else
1320  {
1321  strncpy(Getting_user_channel_info_for, nickname, sizeof(Getting_user_channel_info_for)-1);
1322  User_req_channel[0] = '\0';
1323  snprintf(szWhoisCmd, SSIZE(szWhoisCmd), NOX("/WHOIS %s"), nickname);
1324  SendChatString(szWhoisCmd,1);
1325  GettingUserChannel = 1;
1326  }
1327  return NULL;
1328 }
int GettingUserChannel
Definition: chat_api.cpp:61
Chat_command * Currcommand
Definition: chat_api.cpp:64
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
char Input_chat_buffer[MAXCHATBUFFER]
Definition: chat_api.cpp:45
#define MAXCHATBUFFER
Definition: chat_api.cpp:36
#define WSAEWOULDBLOCK
Definition: config.h:131
#define CC_DISCONNECTED
Definition: chat_api.h:25
Chat_channel * Firstchannel
Definition: chat_api.cpp:65
char szChat_channel[33]
Definition: chat_api.cpp:44
int Joined_channel
Definition: chat_api.cpp:58
int Getting_user_tracker_error
Definition: chat_api.cpp:50
int RemoveChatUser(char *nickname)
Definition: chat_api.cpp:600
Assert(pm!=NULL)
#define SOCKADDR_IN
Definition: config.h:124
#define SOCKADDR
Definition: config.h:123
#define MSG_REMOTE
Definition: chat_api.h:31
char * GetWordNum(int num, const char *l_String)
Definition: chat_api.cpp:525
char * ChatGetString(void)
Definition: chat_api.cpp:470
#define WSAGetLastError()
Definition: cftp.cpp:29
#define SOCKET_ERROR
Definition: config.h:138
char Nick_name[33]
Definition: chat_api.cpp:41
char * GetChatText()
Definition: chat_api.cpp:292
#define INVALID_SOCKET
Definition: psnet2.h:53
#define CC_YOURCHANNEL
Definition: chat_api.h:28
Chat_user * Curruser
Definition: chat_api.cpp:63
void FlushChatCommandQueue(void)
Definition: chat_api.cpp:1169
char Chat_tracker_id[65]
Definition: chat_api.cpp:46
#define CC_USER_JOINING
Definition: chat_api.h:23
int Joining_channel
Definition: chat_api.cpp:57
#define HOSTENT
Definition: config.h:126
_Chat_command * next
Definition: chat_api.h:50
int GettingUserTID
Definition: chat_api.cpp:60
void RemoveAllChatUsers(void)
Definition: chat_api.cpp:629
void AddChannel(char *channel, unsigned short numusers, char *topic)
Definition: chat_api.cpp:1239
#define PXO_CHAT_END_OF_MOTD_PREFIX
Definition: chat_api.h:20
SOCKADDR_IN Chataddr
Definition: chat_api.cpp:39
char * User_list
Definition: chat_api.cpp:53
char * GetChatUserList()
Definition: chat_api.cpp:391
int socklen_t
Definition: chat_api.cpp:30
char * GetChannelByUser(char *nickname)
Definition: chat_api.cpp:1301
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void FlushChannelList(void)
Definition: chat_api.cpp:1184
void DisconnectFromChatServer()
Definition: chat_api.cpp:262
void ChatInit(void)
Definition: chat_api.cpp:74
#define SOCKET
Definition: config.h:122
char nick_name[33]
Definition: chat_api.h:35
char * Chan_list
Definition: chat_api.cpp:54
timeval TIMEVAL
Definition: config.h:216
const char * SendChatString(const char *line, int raw)
Definition: chat_api.cpp:305
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
GLbitfield GLuint64 timeout
Definition: Glext.h:6725
Chat_command * Firstcommand
Definition: chat_api.cpp:64
#define NOX(s)
Definition: pstypes.h:473
#define CC_KICKED
Definition: chat_api.h:26
#define vm_malloc(size)
Definition: pstypes.h:547
Chat_user * Firstuser
Definition: chat_api.cpp:63
char Getting_user_channel_info_for[33]
Definition: chat_api.cpp:47
Chat_channel * Currchannel
Definition: chat_api.cpp:65
char User_req_tracker_id[100]
Definition: chat_api.cpp:51
char * GetChannelList(void)
Definition: chat_api.cpp:1199
#define PXO_CHAT_MOTD_PREFIX
Definition: chat_api.h:19
int Chat_server_connected
Definition: chat_api.cpp:56
GLuint GLuint num
Definition: Glext.h:9089
#define closesocket(x)
Definition: config.h:128
int GettingChannelList
Definition: chat_api.cpp:59
#define strcat_s(...)
Definition: safe_strings.h:68
char Orignial_nick_name[33]
Definition: chat_api.cpp:42
int Nick_variety
Definition: chat_api.cpp:43
_Chat_user * next
Definition: chat_api.h:36
unsigned short users
Definition: chat_api.h:41
int Socket_connecting
Definition: chat_api.cpp:40
#define ioctlsocket(x, y, z)
Definition: config.h:139
GLfloat GLfloat p
Definition: Glext.h:8373
_Chat_channel * next
Definition: chat_api.h:43
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
#define CC_USER_LEAVING
Definition: chat_api.h:24
#define MSG_LOCAL
Definition: chat_api.h:32
#define CC_NICKCHANGED
Definition: chat_api.h:27
int Socket_connected
Definition: chat_api.cpp:55
char data[100]
Definition: chat_api.h:49
char User_req_channel[100]
Definition: chat_api.cpp:52
GLenum GLsizei len
Definition: Glext.h:6283
int SetNewChatChannel(char *channel)
Definition: chat_api.cpp:429
Chat_command * GetChatCommandFromQueue(void)
Definition: chat_api.cpp:1156
char topic[100]
Definition: chat_api.h:42
char channel_name[33]
Definition: chat_api.h:40
SOCKET Chatsock
Definition: chat_api.cpp:38
int socklen_t
Definition: tcp_socket.cpp:39
int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
Definition: chat_api.cpp:111
#define stricmp(s1, s2)
Definition: config.h:271
char Getting_user_tracker_info_for[33]
Definition: chat_api.cpp:48
int Getting_user_channel_error
Definition: chat_api.cpp:49
short command
Definition: chat_api.h:48
void AddChatCommandToQueue(int command, void *data, int len)
Definition: chat_api.cpp:1130
int AddChatUser(char *nickname)
Definition: chat_api.cpp:564
#define strcpy_s(...)
Definition: safe_strings.h:67
#define SSIZE(x)
Definition: chat_api.cpp:71
char * GetTrackerIdByUser(char *nickname)
Definition: chat_api.cpp:1270
char * ParseIRCMessage(char *Line, int iMode)
Definition: chat_api.cpp:644
Chat_command * GetChatCommand()
Definition: chat_api.cpp:382
#define MAXLOCALSTRING
Definition: chat_api.h:30