]>
jfr.im git - irc/gameservirc.git/blob - gameserv/tcpclient.cpp
2 * This file is provided for use with the unix-socket-faq. It is public
3 * domain, and may be copied freely. There is no copyright on it. The
4 * original work was by Vic Metcalfe (vic@brutus.tlug.org), and any
5 * modifications made to that work were made with the understanding that
6 * the finished work would be in the public domain.
8 * If you have found a bug, please pass it on to me at the above address
9 * acknowledging that there will be no copyright on your work.
11 * The most recent version of this file, and the unix-socket-faq can be
12 * found at http://www.interlog.com/~vic/sock-faq/.
27 //#include <sys/types.h>
28 //#include <sys/wait.h>
38 char *PACKAGE
= "GameServ";
39 char *VERSION
= "1.2.0 +devel";
44 List
<aClient
> clients
[U_TABLE_SIZE
];
51 int daemon(int nochdir
, int noclose
);
53 // Close all file descriptors from >= fd
54 void closeall(int fd
);
56 int main(int argc
, char *argv
[])
58 char buffer
[1024], buf
[1024];
60 char *cmd
, *source
= NULL
, *conf
= "gameserv.conf";
64 * This needs to be fixed to work for any number of arguments in any
70 if ( argc
> 2 || stricmp(argv
[1], "--help") == 0)
72 cout
<< "Usage: gameserv [options] [configfile]" << endl
;
73 cout
<< "Options:" << endl
;
74 cout
<< "--help Displays this help dialogue" << endl
;
77 conf
= new char[strlen(argv
[1])];
78 strcpy(conf
, argv
[1]);
83 if (load_config_file(conf
))
85 cout
<< "Config file loaded ok...\n"
86 << "Turning into a daemon" << endl
;
94 perror("Could not turn into a daemon");
101 if (load_monsters() == false)
104 shuttingdown
= false;
106 strcpy(boss
.name
, "Red Dragon");
107 strcpy(boss
.weapon
, "Breath of Unholy Fire");
108 boss
.strength
= 6667;
109 boss
.gold
= 2000000000;
110 boss
.exp
= 2000000000;
111 strcpy(boss
.death
, "You finally snuff out the deadly murderous "\
112 "dragon's dark flames. You have freed the land of its terror "\
113 "filled reign from above!");
115 // This loop will retry the connection 3 times
116 for (int retry
= 0; retry
< 3 && !shuttingdown
; retry
++)
121 long int loadtime
= time(NULL
);
122 long int currentTime
;
123 long int oldTime
= loadtime
;
127 sock
= make_connection(remoteport
, SOCK_STREAM
, remoteserver
);
129 fprintf(stderr
,"make_connection failed.\n");
130 unload_config_file();
135 raw("PROTOCTL NICKv2 VHP");
136 raw("PASS :%s", remotepass
);
137 raw("SERVER %s 1 :%s", servername
, servername
);
138 raw("NICK %S 1 %d %S %s %s %d +owghraAxNt %s :%s v%s", time(NULL
), gshost
,
139 servername
, time(NULL
), gshost
, PACKAGE
, VERSION
);
140 raw(":%S JOIN %s", c_Forest
);
141 raw(":%S MODE %s +mtn", c_Forest
);
142 #elif defined(BAHAMUT)
143 raw("PASS %s :TS", remotepass
);
144 raw("SERVER %s 1 :%s", servername
, servername
);
145 raw("NICK %S 1 %d +o %s %s %s 0 :GameServ", time(NULL
), gsident
, gshost
,
147 raw(":%s SJOIN %d %d %s +mnt :@%S", servername
, time(NULL
), time(NULL
), c_Forest
);
148 #elif defined(HYBRID)
149 raw("PASS %s :TS", remotepass
);
150 raw("SERVER %s 1 :%s", servername
, servername
);
151 raw("NICK %S 1 %d +o %s %s %s :GameServ", time(NULL
), gsident
, gshost
,
153 // Sending a timestamp of 1 to force ops.
154 raw(":%s SJOIN 1 %s +ntm :@%S", servername
, c_Forest
);
156 // Server numeric is: [] <-- must be unique
157 raw("PASS :%s", remotepass
);
158 raw("SERVER %s 1 %d %d P10 []AAF :%s", servername
, time(NULL
), time(NULL
), servername
);
159 raw("[] N %S 1 %d %s %s DAqAoB %s :%S", time(NULL
), gsident
, gshost
, gsnum
);
160 raw("[] B %s %d +tnm %s:o", c_Forest
, time(NULL
) - 864000, gsnum
);
164 raw("%s T %s :%s", gsnum
, c_Forest
, c_ForestTopic
);
165 raw("[] EB"); // End burst
168 raw(":%S MODE %s +o %S", c_Forest
);
170 raw(":%S TOPIC %s :%s", c_Forest
, c_ForestTopic
);
173 sock_gets(sock
,buffer
,sizeof(buffer
)-1); /* -1 added thanks to
174 David Duchene <dave@ltd.com> for pointing out the possible
175 buffer overflow resulting from the linefeed added below. */
179 log("Server: %s",buffer
);
183 if (sock_gets(sock
,buffer
,sizeof(buffer
)) == -1) {
189 if (buffer
[0] == ':')
191 source
= strtok(buf
, " ");
192 cmd
= strtok(NULL
, " ");
195 cmd
= strtok(buf
, " ");
197 source
= strtok(buf
, " ");
198 cmd
= strtok(NULL
, " ");
202 log("Server: %s", buffer
);
205 // Wait N seconds then we're loaded.
208 if (time(NULL
) >= welcomedelay
+ loadtime
)
211 retry
= 0; // Start the reconnection cycle over
215 // Save the player data every updateperiod seconds
216 currentTime
= time(NULL
);
217 if (currentTime
- oldTime
>= updateperiod
)
219 oldTime
= currentTime
;
225 if (stricmp(cmd
, "PING") == 0) {
227 timestamp
= strtok(NULL
, "");
228 raw("PONG %s", timestamp
);
230 if (stricmp(cmd
, "G") == 0) {
232 timestamp
= strtok(NULL
, " ");
233 raw("[] Z [] %s 0 %s", timestamp
+ 1, timestamp
);
236 } else if (stricmp(cmd
, "EB") == 0) {
239 } else if (stricmp(cmd
, "VERSION") == 0) {
241 server
= strtok(NULL
, " ");
243 raw(":%s 351 %s %s_%s. %s", servername
, source
+1, PACKAGE
, VERSION
, servername
);
245 } else if (strncmp(cmd
, "NICK", 4) == 0) {
246 if (buffer
[0] == ':')
249 if ((tempPtr
= find((source
+ 1))))
252 unsigned long oldhv
, newhv
;
253 nick
= strtok(NULL
, " ");
254 oldhv
= HASH((unsigned char *) tempPtr
->getNick(),
256 newhv
= HASH((unsigned char *) nick
, U_TABLE_SIZE
);
257 tempPtr
->setNick(nick
);
258 clients
[oldhv
].remove(tempPtr
);
259 clients
[newhv
].insertAtBack(tempPtr
);
266 } else if (stricmp(cmd
, "N") == 0 && strlen(source
) == 2) {
268 char *nick
, *realnick
;
269 realnick
= strtok(NULL
, " ");
271 for (int x
= 0; x
< 5; x
++)
272 nick
= strtok(NULL
, " ");
277 log ("aClient has modes");
280 // Searching for the +r mode (extra parameter)
281 for (unsigned int count
= 1; count
< strlen(nick
); count
++)
283 if (nick
[count
] == 'r')
285 nick
= strtok(NULL
, " ");
289 nick
= strtok(NULL
, " ");
294 nick
= strtok(NULL
, " ");
297 newuser
= new aClient(nick
, realnick
);
299 newuser
= new aClient(nick
);
305 notice(s_GameServ
, nick
, welcomemsg
, realnick
);
307 notice(s_GameServ
, nick
, welcomemsg
, nick
);
309 unsigned long hv
= HASH((unsigned char *) nick
, U_TABLE_SIZE
);
310 clients
[hv
].insertAtBack(newuser
);
314 } else if (stricmp(cmd
, "Q") == 0) {
316 } else if (stricmp(cmd
, "QUIT") == 0) {
324 unsigned long hv
= HASH((unsigned char *) source
, U_TABLE_SIZE
);
325 if ((quitter
= find(source
)))
326 clients
[hv
].remove(quitter
);
327 if ((quitter
= findIRCplayer(source
)))
329 if (player_fight(quitter
))
331 // Stop the fight on the other client
332 aClient
*otherplayer
= quitter
->stats
->battle
;
333 otherplayer
->stats
->battle
= NULL
;
334 notice(s_GameServ
, otherplayer
->getNick(), "%s "\
335 "has quit IRC. The fight stops here.",
336 quitter
->stats
->name
);
338 quitter
->stats
->battle
= NULL
;
339 quitter
->stats
->fight
= NULL
;
340 quitter
->stats
->master
= NULL
;
342 quitter
->setNick("Not Playing");
344 quitter
->setRealNick("Not Playing");
346 quitter
->stats
->client
= NULL
; // Unidentify them
353 } else if (stricmp(cmd
, "P") == 0) {
356 longname
= new char[strlen(s_GameServ
) + strlen(servername
) + 2];
358 sprintf(longname
, "%S@%s", servername
);
360 dest
= strtok(NULL
, " ");
361 rest
= strtok(NULL
, "");
362 if (stricmp(dest
, gsnum
) == 0 || stricmp(dest
, longname
) == 0)
365 gameserv(source
, rest
);
367 else if (stricmp(dest
, c_Forest
) == 0)
370 forest(source
, rest
);
373 } else if (stricmp(cmd
, "PRIVMSG") == 0) {
375 dest
= strtok(NULL
, " ");
376 rest
= strtok(NULL
, "");
377 if (strnicmp(dest
, s_GameServ
, strlen(s_GameServ
)) == 0)
378 gameserv(source
, rest
);
379 else if (stricmp(dest
, c_Forest
) == 0)
380 forest(source
, rest
);
383 } else if (stricmp(cmd
, "J") == 0) {
385 } else if (stricmp(cmd
, "JOIN") == 0) {
389 channel
= strtok(NULL
, " ");
396 joiner
= find(source
);
398 if (stricmp(channel
, c_Forest
) == 0 && is_playing(joiner
))
401 log("Player %s (IRC: %s) joined %s",
404 joiner
->getRealNick(),
410 raw(":%S MODE %s +v %s", c_Forest
, (source
));
417 } else if (stricmp(cmd
, "SJOIN") == 0) {
418 char *channel
, *nick
, *tmp
, *rest
;
419 strtok(NULL
, " "); // Ignore the TS
421 strtok(NULL
, " "); // Ignore the TS
423 channel
= strtok(NULL
, " ");
424 rest
= strtok(NULL
, "");
425 tmp
= strchr(rest
, ':');
427 nick
= strtok(tmp
, " ");
433 nick
++; // Assume for users set op and voice, they
434 // are never passed as +@nick
435 if (stricmp(channel
, c_Forest
) == 0 && is_playing(nick
))
436 raw(":%S MODE %s +v %s", channel
, nick
);
438 nick
= strtok(NULL
, " ");
443 log("Unrecognized Message: cmd = %s source = %s", cmd
, source
);
448 } // for loop for connection retry
463 unload_config_file();
467 aClient
*find(char *nick
)
469 return findbynick(nick
);
472 aClient
*find(const char *nick
)
474 return findbynick(nick
);
479 aClient
*findbyrealnick(char *realnick
)
481 ListNode
<aClient
> *newPtr
;
482 unsigned long hv
= HASH((unsigned char *) realnick
, U_TABLE_SIZE
);
483 newPtr
= clients
[hv
].First();
485 aClient
*client
= NULL
;
489 client
= newPtr
->getData();
490 if (stricmp(client
->getRealNick(), realnick
) == 0)
493 newPtr
= newPtr
->Next();
500 aClient
*findbyrealnick(char *realnick
)
502 return findbynick(realnick
);
507 aClient
*findbynick(char *nick
)
509 ListNode
<aClient
> *newPtr
;
510 unsigned long hv
= HASH((unsigned char *) nick
, U_TABLE_SIZE
);
511 newPtr
= clients
[hv
].First();
513 aClient
*client
= NULL
;
517 client
= newPtr
->getData();
519 if (strcmp(client
->getNick(), nick
) == 0)
521 if (stricmp(client
->getNick(), nick
) == 0)
525 newPtr
= newPtr
->Next();
530 aClient
*findIRCplayer(const char *nick
)
532 ListNode
<aClient
> *newPtr
;
535 unsigned long hv
= HASH((unsigned char *) nick
, U_TABLE_SIZE
);
536 for (newPtr
= players
[hv
].First(); newPtr
; newPtr
= newPtr
->Next())
538 p
= newPtr
->getData();
540 if (strcmp(p
->getNick(), nick
) == 0)
542 if (stricmp(p
->getNick(), nick
) == 0)
549 aClient
*findplayer(const char *name
)
551 ListNode
<aClient
> *newPtr
;
553 unsigned long hv
= HASH((unsigned char *) name
, U_TABLE_SIZE
);
554 for (newPtr
= players
[hv
].First(); newPtr
; newPtr
= newPtr
->Next())
556 p
= newPtr
->getData()->stats
;
557 if (stricmp(p
->name
, name
) == 0)
558 return newPtr
->getData();
564 aClient
*findbynick(const char *nick
)
566 ListNode
<aClient
> *newPtr
;
567 unsigned long hv
= HASH((unsigned char *) nick
, U_TABLE_SIZE
);
568 newPtr
= clients
[hv
].First();
570 aClient
*client
= NULL
;
574 client
= newPtr
->getData();
576 if (strcmp(client
->getNick(), nick
) == 0)
578 if (stricmp(client
->getNick(), nick
) == 0)
582 newPtr
= newPtr
->Next();
591 infile
.open(".gsday");
596 log("Error opening .gsday");
601 log("Generating new day");
616 if (day
< 1 || day
> 31)
624 outfile
.open(".gsday");
628 log("Error creating new file .gsday");
632 outfile
<< day
<< endl
;
637 /* daemon() - detach process from user and disappear into the background
638 * returns -1 on failure, but you can't do much except exit in that case
639 * since we may already have forked. This is based on the BSD version,
640 * so the caller is responsible for things like the umask, etc.
643 /* believed to work on all Posix systems */
645 int daemon(int nochdir
, int noclose
)
648 switch (pid
= fork())
652 default: _exit(0); /* exit the original process */
655 if (setsid() < 0) /* shoudn't fail */
658 /* dyke out this switch if you want to acquire a control tty in */
659 /* the future -- not normally advisable for daemons */
661 switch (pid
= fork())
667 outfile
.open(pidfile
);
669 cerr
<< "Unable to open " << pidfile
<< endl
;
670 outfile
<< pid
<< endl
;
682 open("/dev/null",O_RDWR
);
690 /* closeall() -- close all FDs >= a specified value */
692 void closeall(int fd
)
694 int fdlimit
= sysconf(_SC_OPEN_MAX
);
703 cout
<< " GGGG AAA MM MM EEEEEEE SSSSS EEEEEEE RRRRRR VV VV " << endl
;
704 cout
<< " GG GG AAAAA MMM MMM EE SS EE RR RR VV VV " << endl
;
705 cout
<< "GG AA AA MM MM MM EEEEE SSSSS EEEEE RRRRRR VV VV " << endl
;
706 cout
<< "GG GGG AAAAAAA MM MM EE SS EE RR RR VV VV " << endl
;
707 cout
<< "G G AA AA MM MM EEEEEEE SSSSS EEEEEEE RR RR VVV" << endl
;
708 cout
<< " GGGGG V\n\n" << endl
;
709 cout
<< "Version: " << VERSION
<< endl
;