]>
jfr.im git - irc/gameservirc.git/blob - gameserv/tcpclient.cpp
bc0e9107d14fd2777f05732c4a9b150c5471f520
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/.
31 //#include <sys/types.h>
32 //#include <sys/wait.h>
37 const string PACKAGE
= "GameServ";
38 const string VERSION
= "1.3.4 +devel";
44 list
<aClient
*> clients
[U_TABLE_SIZE
];
46 void save_lastrefresh();
47 void load_lastrefresh();
48 void load_lastrollover();
49 void save_lastrollover();
57 int daemon(int nochdir
, int noclose
);
59 // Close all file descriptors from >= fd
60 void closeall(int fd
);
62 int main(int argc
, char *argv
[])
64 char buffer
[1024], buf
[1024];
65 memset(buffer
, 0, 1024);
69 char *cmd
, *source
= NULL
, *conf
;
72 strcpy(conf
, "gameserv.conf");
75 * This needs to be fixed to work for any number of arguments in any
81 if ( argc
> 2 || stricmp(argv
[1], "--help") == 0)
83 cout
<< "Usage: gameserv [options] [configfile]" << endl
;
84 cout
<< "Options:" << endl
;
85 cout
<< "--help Displays this help dialogue" << endl
;
95 if (load_config_file(conf
))
97 cout
<< "Config file loaded ok...\n"
98 << "Turning into a daemon" << endl
;
106 // Turn into a daemon
109 perror("Could not turn into a daemon");
113 if (load_items() == 0)
115 log("Error loading items");
119 if (load_store() == 0)
121 log("Error loading store");
124 if (load_tavern() == 0)
126 log("Error loading tavern");
131 loadNews(newsdata
, todaysnews
);
134 if (load_masters() == false)
136 log("Error loading masters");
140 if (load_monsters() == false)
142 log("Error loading monsters");
148 log("Error loading dragon");
152 if (load_levels() == false)
154 log("Error loading levels");
158 shuttingdown
= false;
160 char ignoreservers
[32][256];
162 currentserver
= strtok(ignoreserverslist
, " ");
163 for (int server
= 0; server
< 32 && currentserver
!= NULL
; server
++)
165 strncpy(ignoreservers
[server
], currentserver
, 255);
166 log("Placing %s on the server ignore list", currentserver
);
167 currentserver
= strtok(NULL
, " ");
170 // This loop will retry the connection 3 times
171 for (int retry
= 0; retry
< 3 && !shuttingdown
; retry
++)
177 long int loadtime
= time(NULL
);
178 long int currentTime
;
179 long int oldTime
= loadtime
;
181 lastidlecheck
= loadtime
;
184 log("Setting primary Idle Check timestamp: %ld", lastidlecheck
);
189 sock
= conn(remoteserver
, remoteport
, localhost
, 0);
190 // sock = make_connection(remoteport, SOCK_STREAM, remoteserver);
193 fprintf(stderr
,"make_connection failed.\n");
194 unload_config_file();
197 log("<S socket connected.");
200 raw("PASS :%s", remotepass
);
201 raw("SERVER %s 1 :%s", servername
, servername
);
202 raw("NICK <S 1 %d %s %s %s %d :%s v%s", time(NULL
), gsident
, gshost
,
203 servername
, time(NULL
), PACKAGE
.c_str(), VERSION
.c_str());
204 raw(":<S JOIN %s", c_Forest
);
205 raw(":<S MODE %s +tn", c_Forest
);
206 #elif defined(BAHAMUT)
207 raw("PASS %s :TS", remotepass
);
208 raw("SERVER %s 1 :%s", servername
, servername
);
209 raw("NICK <S 1 %d +w%s %s %s %s 0 :GameServ", time(NULL
), (isBOper() ? "o" : ""),
210 gsident
, gshost
, servername
);
211 raw(":%s SJOIN %d %d %s +nt :@<S", servername
, time(NULL
), time(NULL
), c_Forest
);
212 #elif defined(HYBRID)
213 raw("PASS %s :TS", remotepass
);
214 raw("SERVER %s 1 :%s", servername
, servername
);
215 raw("NICK <S 1 %d +w%s %s %s %s :GameServ", time(NULL
), (isBOper() ? "o" : ""),
216 gsident
, gshost
, servername
);
217 raw(":%s SJOIN %ld %s +nt :@<S", servername
, time(NULL
), c_Forest
);
218 #elif defined(ULTIMATE2)
219 raw("PASS %s :TS", remotepass
);
220 raw("SERVER %s 1 :%s", servername
, servername
);
221 raw("NICK <S 1 %d %s %s %s 0 :GameServ",
222 time(NULL
), gsident
, gshost
, servername
);
224 raw(":<S mode <S +o");
225 raw(":<S JOIN %s", c_Forest
);
226 #elif defined(PTLINK)
227 raw("PASS %s :TS", remotepass
);
228 raw("SERVER %s 1 :%s", servername
, servername
);
229 raw("NICK <S 1 %d %s%s %s %s %s :GameServ", time(NULL
), (isBOper() ? "+iow " : ""), gsident
, gshost
, gshost
, servername
);
230 raw(":%s SJOIN %d %s +nt :@<S", servername
, time(NULL
), c_Forest
);
232 raw("PASS %s :TS", remotepass
);
233 raw("SERVER %s 1 %d :%s", servername
, time(NULL
), servername
);
234 raw("NNICK <S 1 %d +w%s %s %s %s %s :GameServ", time(NULL
),(isBOper() ? "o" : ""), gsident
, gshost
, gshost
, servername
);
235 raw(":%s SJOIN %d %s +nt :@<S", servername
, time(NULL
), c_Forest
);
236 #elif defined(BAHAMUT8)
237 raw("PASS %s :TS", remotepass
);
238 raw("SERVER %s %d :%s", servername
, time(NULL
), servername
);
239 raw("NICK <S 1 %d +w%s %s %s %s 0 %d :GameServ", time(NULL
), (isBOper() ? "o" : ""), gsident
, gshost
, servername
, time(NULL
));
240 raw(":%s SJOIN %d %d %s +nt :@<S", servername
, time(NULL
), time(NULL
), c_Forest
);
242 // Server numeric is: [] <-- must be unique
243 raw("PASS :%s", remotepass
);
244 raw("SERVER %s 1 %d %d P10 []AAF :%s", servername
, time(NULL
), time(NULL
), servername
);
245 raw("[] N <S 1 %d %s %s %s DAqAoB %s :<S", time(NULL
), gsident
, gshost
,
246 (isBOper() ? "+o" : ""), gsnum
);
247 raw("[] B %s %d +tn %s:o", c_Forest
, time(NULL
) - 864000, gsnum
);
251 raw("%s T %s :%s", gsnum
, c_Forest
, c_ForestTopic
);
252 raw("[] EB"); // End burst
255 #if defined(ULTIMATE2)
256 raw(":%s MODE %s +o <S %ld", servername
, c_Forest
,
259 raw(":<S MODE %s +o <S", c_Forest
);
262 raw(":<S TOPIC %s :%s", c_Forest
, c_ForestTopic
);
268 raw(":<S PRIVMSG %s :IDENTIFY %s", nsname
, nspass
);
271 sock_gets(sock
,buffer
,sizeof(buffer
)-1); /* -1 added thanks to
272 David Duchene <dave@ltd.com> for pointing out the possible
273 buffer overflow resulting from the linefeed added below. */
277 log("Server: %s",buffer
);
282 if (sock_gets(sock
,buffer
,sizeof(buffer
)) == -1)
289 if (buffer
[0] == ':')
291 source
= strtok(buf
, " ");
292 cmd
= strtok(NULL
, " ");
296 cmd
= strtok(buf
, " ");
299 source
= strtok(buf
, " ");
300 cmd
= strtok(NULL
, " ");
304 log("Server: %s", buffer
);
307 // Wait N seconds then we're loaded.
310 if (time(NULL
) >= welcomedelay
+ loadtime
)
313 retry
= 0; // Start the reconnection cycle over
318 long TIME
= time(NULL
);
319 if (TIME
- lastidlecheck
>= idlecheckperiod
)
322 lastidlecheck
= TIME
;
326 // Refresh players and clear news if the time is up
327 currentTime
= time(NULL
);
329 if (isRolloverForestFights())
331 if (currentTime
- lastrollover
>= rolloverperiod
)
334 lastrollover
= currentTime
;
336 notice(s_GameServ
, c_Forest
, "Adding %d forest fights to all players!", numrolloverfights
);
340 if (currentTime
- lastrefresh
>= refreshperiod
)
343 clearNews(todaysnews
);
344 saveNews(newsdata
, todaysnews
);
345 lastrefresh
= currentTime
;
347 notice(s_GameServ
, c_Forest
, "Refreshing all players "\
348 "and resetting news!");
351 // Save the player data every updateperiod seconds
352 if (currentTime
- oldTime
>= updateperiod
)
354 oldTime
= currentTime
;
355 log("Saving to %s", playerdata
);
358 saveNews(newsdata
, todaysnews
);
361 // Send notice to the channel of the update
362 notice(s_GameServ
, c_Forest
, "<S player data saved");
368 if (stricmp(cmd
, "PING") == 0)
371 timestamp
= strtok(NULL
, "");
372 raw("PONG %s", timestamp
);
376 if (stricmp(cmd
, "G") == 0)
379 timestamp
= strtok(NULL
, " ");
380 raw("[] Z [] %s 0 %s", timestamp
+ 1, timestamp
);
384 else if (stricmp(cmd
, "EB") == 0)
389 else if (stricmp(cmd
, "VERSION") == 0)
392 server
= strtok(NULL
, " ");
394 raw(":%s 351 %s %s_%s. %s", servername
, source
+1, PACKAGE
.c_str(), VERSION
.c_str(), servername
);
396 // Code indenting is clean up until here!
398 else if (strncmp(cmd
, "NICK", 4) == 0
400 || strncmp(cmd
, "NNICK", 5) == 0
404 if (buffer
[0] == ':')
407 if ((tempPtr
= find((source
+ 1))))
410 unsigned long oldhv
, newhv
;
411 nick
= strtok(NULL
, " ");
412 oldhv
= iHASH((unsigned char *) tempPtr
->getNick());
413 newhv
= iHASH((unsigned char *) nick
);
414 tempPtr
->setNick(nick
);
415 clients
[oldhv
].remove(tempPtr
);
416 clients
[newhv
].push_back(tempPtr
);
423 } else if (stricmp(cmd
, "N") == 0 && strlen(source
) == 2) {
425 char *nick
, *realnick
;
426 realnick
= strtok(NULL
, " ");
428 for (int x
= 0; x
< 5; x
++)
429 nick
= strtok(NULL
, " ");
434 log ("aClient has modes");
436 // Searching for the +r mode (extra parameter)
437 for (unsigned int count
= 1; count
< strlen(nick
); count
++)
439 if (nick
[count
] == 'r')
441 nick
= strtok(NULL
, " ");
445 nick
= strtok(NULL
, " ");
450 nick
= strtok(NULL
, " ");
453 newuser
= new aClient(nick
, realnick
);
455 newuser
= new aClient(nick
);
463 notice(s_GameServ
, nick
, welcomemsg
, realnick
);
465 notice(s_GameServ
, nick
, welcomemsg
, nick
);
469 unsigned long hv
= sHASH((unsigned char *) nick
);
471 unsigned long hv
= iHASH((unsigned char *) nick
);
474 #if defined(HYBRID) || defined(BAHAMUT) || defined(ULTIMATE2) || defined(PTLINK)
478 nickserver
= strtok(NULL
, " ");
479 if (nickserver
[0] == '+')
482 nickserver
= strtok(NULL
, " ");
483 for (int x
= 0; x
< 32; x
++)
485 if (stricmp(ignoreservers
[x
], nickserver
) == 0)
491 #elif defined(UNREAL)
497 nickserver
= strtok(NULL
, " ");
498 for (int x
= 0; x
< 32; x
++)
500 if (stricmp(ignoreservers
[x
], nickserver
) == 0)
507 clients
[hv
].push_back(newuser
);
510 } else if (stricmp(cmd
, "Q") == 0) {
511 // unsigned long hv = sHASH((unsigned char *) source);
513 } else if (stricmp(cmd
, "QUIT") == 0)
523 unsigned long hv
= iHASH((unsigned char *) source
);
524 if (!(quitter
= find(source
)))
526 log("Fatal Error: could not find %s in the "\
527 "clients list", source
);
531 clients
[hv
].remove(quitter
);
541 else if (stricmp(cmd
, "P") == 0)
545 longname
= new char[strlen(s_GameServ
) + strlen(servername
) + 2];
547 sprintf(longname
, "<S@%s", servername
);
549 dest
= strtok(NULL
, " ");
550 rest
= strtok(NULL
, "");
551 if (stricmp(dest
, gsnum
) == 0 || stricmp(dest
, longname
) == 0)
554 gameserv(source
, rest
);
556 else if (stricmp(dest
, c_Forest
) == 0 && isListenOnCF())
559 forest(source
, rest
);
563 else if (stricmp(cmd
, "PRIVMSG") == 0)
566 dest
= strtok(NULL
, " ");
567 rest
= strtok(NULL
, "");
568 if (strnicmp(dest
, s_GameServ
, strlen(s_GameServ
)) == 0)
569 gameserv(source
, rest
);
570 else if (stricmp(dest
, c_Forest
) == 0 && isListenOnCF())
571 forest(source
, rest
);
574 } else if (stricmp(cmd
, "J") == 0) {
576 } else if (stricmp(cmd
, "JOIN") == 0) {
580 channel
= strtok(NULL
, " ");
587 joiner
= find(source
);
589 if (stricmp(channel
, c_Forest
) == 0 && is_playing(joiner
))
592 log("Player %s (IRC: %s) joined %s",
593 joiner
->stats
->getName().c_str(),
595 joiner
->getRealNick(),
601 raw(":<S MODE %s +v %s", c_Forest
, (source
));
608 } else if (stricmp(cmd
, "SJOIN") == 0) {
609 char *channel
, *nick
, *tmp
, *rest
;
610 strtok(NULL
, " "); // Ignore the TS
612 strtok(NULL
, " "); // Ignore the TS
614 channel
= strtok(NULL
, " ");
615 rest
= strtok(NULL
, "");
616 tmp
= strchr(rest
, ':');
618 nick
= strtok(tmp
, " ");
624 nick
++; // Assume for users set op and voice, they
625 // are never passed as +@nick
626 if (stricmp(channel
, c_Forest
) == 0 && is_playing(nick
))
627 raw(":<S MODE %s +v %s", channel
, nick
);
629 nick
= strtok(NULL
, " ");
634 log("Unrecognized Message: cmd = %s source = %s", cmd
, source
);
639 } // for loop for connection retry
645 saveNews(newsdata
, todaysnews
);
656 unload_config_file();
660 aClient
*find(char *nick
)
662 return findbynick(nick
);
665 aClient
*find(const char *nick
)
667 return findbynick(nick
);
672 aClient
*findbyrealnick(char *realnick
)
674 ListNode
<aClient
> *newPtr
;
675 unsigned long hv
= sHASH((unsigned char *) realnick
);
676 newPtr
= clients
[hv
].First();
678 aClient
*client
= NULL
;
682 client
= newPtr
->getData();
683 if (stricmp(client
->getRealNick(), realnick
) == 0)
686 newPtr
= newPtr
->Next();
693 aClient
*findbyrealnick(char *realnick
)
695 return findbynick(realnick
);
700 aClient
*findbynick(char *nick
)
702 list
<aClient
*>::iterator iter
;
704 unsigned long hv
= sHASH((unsigned char *) nick
);
706 unsigned long hv
= iHASH((unsigned char *) nick
);
709 aClient
*client
= NULL
;
711 for(iter
= clients
[hv
].begin(); iter
!= clients
[hv
].end(); iter
++)
715 if (strcmp(client
->getNick(), nick
) == 0)
718 if (stricmp(client
->getNick(), nick
) == 0)
728 Player
*findplayer(const char *name
)
730 list
<Player
*>::iterator iter
;
732 unsigned long hv
= iHASH((unsigned char *) name
);
733 for (iter
= players
[hv
].begin(); iter
!= players
[hv
].end(); iter
++)
736 if (stricmp(p
->getName().c_str(), name
) == 0)
745 list
<Player
*>::iterator iter
;
748 for (int x
= 0; x
< U_TABLE_SIZE
; x
++)
750 for (iter
= players
[x
].begin(); iter
!= players
[x
].end(); iter
++)
754 switch(p
->getLevel())
757 if ((time(NULL
) - p
->lastlogin
) / 86400 >= level1expire
)
759 logout(p
->getClient());
765 if ((time(NULL
) - p
->lastlogin
) / 86400 >= defaultexpire
)
767 logout(p
->getClient());
780 aClient
*findbynick(const char *nick
)
782 list
<aClient
*>::iterator iter
;
784 unsigned long hv
= sHASH((unsigned char *) nick
);
786 unsigned long hv
= iHASH((unsigned char *) nick
);
789 aClient
*client
= NULL
;
791 for (iter
= clients
[hv
].begin(); iter
!= clients
[hv
].end(); iter
++)
795 if (strcmp(client
->getNick(), nick
) == 0)
797 if (stricmp(client
->getNick(), nick
) == 0)
805 /* daemon() - detach process from user and disappear into the background
806 * returns -1 on failure, but you can't do much except exit in that case
807 * since we may already have forked. This is based on the BSD version,
808 * so the caller is responsible for things like the umask, etc.
811 /* believed to work on all Posix systems */
813 int daemon(int nochdir
, int noclose
)
816 switch (pid
= fork())
820 default: _exit(0); /* exit the original process */
823 if (setsid() < 0) /* shoudn't fail */
826 /* dyke out this switch if you want to acquire a control tty in */
827 /* the future -- not normally advisable for daemons */
829 switch (pid
= fork())
835 outfile
.open(pidfile
);
837 cerr
<< "Unable to open " << pidfile
<< endl
;
838 outfile
<< pid
<< endl
;
850 open("/dev/null",O_RDWR
);
858 /* closeall() -- close all FDs >= a specified value */
860 void closeall(int fd
)
862 int fdlimit
= sysconf(_SC_OPEN_MAX
);
871 cout
<< " GGGG AAA MM MM EEEEEEE SSSSS EEEEEEE RRRRRR VV VV " << endl
;
872 cout
<< " GG GG AAAAA MMM MMM EE SS EE RR RR VV VV " << endl
;
873 cout
<< "GG AA AA MM MM MM EEEEE SSSSS EEEEE RRRRRR VV VV " << endl
;
874 cout
<< "GG GGG AAAAAAA MM MM EE SS EE RR RR VV VV " << endl
;
875 cout
<< "G G AA AA MM MM EEEEEEE SSSSS EEEEEEE RR RR VVV" << endl
;
876 cout
<< " GGGGG V\n\n" << endl
;
877 cout
<< "Version: " << VERSION
<< endl
;
878 cout
<< "http://www.gameserv.us - http://www.sourceforge.net/projects/gameservirc" << endl
;
881 void load_lastrefresh()
884 infile
.open(".gsrefresh");
888 log("Error opening .gsrefresh");
892 long mytime
= time(NULL
);
894 log("Generating new refresh time");
897 // Just a safety measure... tho no one should
898 // get anywhere near the actual time as their refreshperiod
899 if (refreshperiod
>= mytime
)
901 log("Refresh period is greater than or equal to the actual time... setting it to 86400");
902 refreshperiod
= 86400;
905 lastrefresh
= mytime
- (mytime
% refreshperiod
);
911 infile
>> lastrefresh
;
918 void load_lastrollover()
921 infile
.open(".gsrollover");
925 log("Error opening .gsrollover");
929 long mytime
= time(NULL
);
931 log("Generating new rollover time");
933 lastrollover
= mytime
;
936 infile
>> lastrollover
;
939 if (lastrollover
< 0)
943 void save_lastrefresh()
947 outfile
.open(".gsrefresh");
951 log("Error creating new file .gsrefresh");
954 outfile
<< lastrefresh
<< endl
<< lastrollover
;
959 void save_lastrollover()
963 outfile
.open(".gsrollover");
967 log("Error creating new file .gsrollover");
970 outfile
<< lastrollover
<< endl
;
975 list
<item
*>::iterator iter
;
976 for (iter
= Items
.begin(); iter
!= Items
.end(); iter
++)
984 list
<aClient
*>::iterator iter
;
985 for (unsigned long x
= 0; x
< U_TABLE_SIZE
; x
++)
987 for (iter
= clients
[x
].begin(); iter
!= clients
[x
].end(); iter
++)
990 clients
[x
].erase(iter
);
997 list
<Player
*>::iterator iter
;
998 for (unsigned long x
= 0; x
< U_TABLE_SIZE
; x
++)
1000 for (iter
= players
[x
].begin(); iter
!= players
[x
].end(); iter
++)
1003 players
[x
].erase(iter
);