2 "$Id: metaserver.c 11626 2009-04-04 12:41:46Z lalo $";
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
48 #ifdef HAVE_CURL_CURL_H
49 #include <curl/curl.h>
50 #include <curl/types.h>
51 #include <curl/easy.h>
73 if (!meta_servers[entry].sc_version || !meta_servers[entry].cs_version)
76 if (meta_servers[entry].sc_version !=
VERSION_SC) {
91 (meta_servers[entry].sc_version==1027 ||
92 meta_servers[entry].sc_version==1028))
95 if (meta_servers[entry].cs_version !=
VERSION_CS)
return 0;
128 buf[strlen(buf)-1] = 0;
188 static char *
metaservers[] = {
"http://crossfire.real-time.com/metaserver2/meta_client.php"};
216 #ifdef HAVE_CURL_CURL_H
217 size_t realsize = size * nmemb;
218 char *cp, *newline, *eq, inbuf[CURL_MAX_WRITE_SIZE*2+1], *leftover;
220 leftover = (
char*) data;
222 if (realsize > CURL_MAX_WRITE_SIZE) {
223 LOG(
LOG_CRITICAL,
"common::metaserver2_writer",
"Function called with more data than allowed!");
231 memcpy(inbuf, leftover, strlen(leftover));
232 memcpy(inbuf+strlen(leftover), ptr, realsize);
241 for (cp = inbuf; cp != NULL && *cp!=0; cp=newline) {
242 newline=strchr(cp,
'\n');
251 strncpy(leftover, cp, CURL_MAX_WRITE_SIZE-1);
252 leftover[CURL_MAX_WRITE_SIZE-1] = 0;
262 if (!strcmp(cp,
"START_SERVER_DATA")) {
268 else if (!strcmp(cp,
"END_SERVER_DATA")) {
276 if (!strcasecmp(meta_servers[i].hostname, meta_servers[meta_numservers].hostname)) {
277 memcpy(&meta_servers[i], &meta_servers[meta_numservers],
sizeof(
Meta_Info));
281 if (i>=meta_numservers) {
291 LOG(
LOG_ERROR,
"common::metaserver2_writer",
"Unknown line: %s",cp);
294 if (!strcmp(cp,
"hostname")) {
297 else if (!strcmp(cp,
"port")) {
300 else if (!strcmp(cp,
"html_comment")) {
303 else if (!strcmp(cp,
"text_comment")) {
306 else if (!strcmp(cp,
"archbase")) {
309 else if (!strcmp(cp,
"mapbase")) {
312 else if (!strcmp(cp,
"codebase")) {
315 else if (!strcmp(cp,
"flags")) {
318 else if (!strcmp(cp,
"version")) {
321 else if (!strcmp(cp,
"num_players")) {
324 else if (!strcmp(cp,
"in_bytes")) {
327 else if (!strcmp(cp,
"out_bytes")) {
330 else if (!strcmp(cp,
"uptime")) {
333 else if (!strcmp(cp,
"sc_version")) {
336 else if (!strcmp(cp,
"cs_version")) {
339 else if (!strcmp(cp,
"last_update")) {
350 LOG(
LOG_ERROR,
"common::metaserver2_writer",
"Unknown line: %s=%s",cp,eq);
370 #ifdef HAVE_CURL_CURL_H
373 char leftover[CURL_MAX_WRITE_SIZE];
375 curl = curl_easy_init();
378 curl_easy_setopt(curl, CURLOPT_URL, metaserver2);
380 curl_easy_setopt(curl, CURLOPT_WRITEDATA, leftover);
381 res = curl_easy_perform(curl);
382 curl_easy_cleanup(curl);
399 int metaserver_choice;
402 metaserver_choice = random() % (
sizeof(
metaservers) /
sizeof(
char*));
430 #ifndef HAVE_CURL_CURL_H
445 LOG(
LOG_ERROR,
"common::metaserver2_get_info",
"Thread creation failed.");
462 #ifdef HAVE_CURL_CURL_H
463 curl_global_init(CURL_GLOBAL_ALL);
488 char *get_line_from_sock(
char *s,
size_t n,
int fd) {
489 static long charsleft = 0;
497 LOG(
LOG_CRITICAL,
"common::get_line_from_sock",
"Serious program logic error in get_line_from_sock().");
501 if (charsleft >
MS_LARGE_BUF*4-3 && strchr(inbuf,
'\n') == NULL) {
507 while (charsleft == 0 || (cp = strchr(inbuf,
'\n')) == NULL) {
513 if (select(0, &fdset, NULL, NULL, &tv) == 0) {
518 nlen = recv(fd, inbuf+charsleft-1,
MS_LARGE_BUF*4-1-charsleft, 0);
519 if (nlen == SOCKET_ERROR || nlen <= 0)
532 memcpy(s, inbuf, cp-inbuf+1);
537 while (cp[++ct] != 0) {
538 inbuf[ct-1] = cp[ct];
550 struct protoent *protox;
552 struct sockaddr_in insock;
559 protox = getprotobyname(
"tcp");
560 if (protox == NULL) {
561 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Error getting protobyname (tcp)");
568 fd = socket(PF_INET, SOCK_STREAM, protox->p_proto);
570 perror(
"get_metaserver_info: Error on socket command.\n");
576 insock.sin_family = AF_INET;
577 insock.sin_port = htons((
unsigned short)
meta_port);
581 struct hostent *hostbn = gethostbyname(
meta_server);
582 if (hostbn == NULL) {
589 memcpy(&insock.sin_addr, hostbn->h_addr, hostbn->h_length);
591 if (connect(fd, (
struct sockaddr *)&insock,
sizeof(insock)) == -1) {
592 perror(
"Can't connect to metaserver");
605 if ((fp = fdopen(fd,
"r")) == NULL) {
606 perror(
"fdopen failed.");
628 while (get_line_from_sock(inbuf,
MS_LARGE_BUF*4-1, fd) != NULL) {
632 cp = strchr(inbuf,
'|');
634 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
647 cp1 = strchr(cp,
'|');
649 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
654 cp = strchr(cp1+1,
'|');
656 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
669 cp1 = strchr(cp,
'|');
671 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
676 cp = strchr(cp1+1,
'|');
678 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
689 cp1 = strchr(cp,
'\n');
691 LOG(
LOG_WARNING,
"common::metaserver_get_info",
"Corrupt line from server: %s", inbuf);
699 cp1 = strchr(cp,
'|');
711 LOG(
LOG_WARNING,
"common:metaserver_get_info",
"Have reached maximum metaserver count\n");
747 LOG(
LOG_ERROR,
"common::metaserver1_get_info",
"Thread creation failed.");
834 snprintf(buf,
sizeof(buf),
"%2d) %-15.15s %2d %-12.12s %2d",
836 meta_servers[i].num_players, meta_servers[i].version,
837 meta_servers[i].idle_time);
841 if (show_selection) {
865 char *server_name = NULL, *server_ip;
877 if (num == 0 && sel[0] ==
'0') {
890 if (num == 0 || strchr(sel,
'.') != NULL) {
919 if ((sel = strrchr(server_name,
':')) != NULL && (port = atoi(sel+1)) > 0) {
920 snprintf(buf2,
sizeof(buf2),
"%s", server_name);
921 buf2[sel-server_name] =
'\0';
929 snprintf(buf,
sizeof(buf),
"Trying to connect to %s:%d", server_name, port);
949 if (index != 0 || !cached_servers_num) {
954 if (index == cached_servers_num) {
955 name = strdup(server_name);
956 ip = strdup(server_ip);
957 cached_servers_num++;
959 cached_servers_num--;
987 int main(
int argc,
char *argv[])
993 printf(
"%s:%d:%s:%d:%s:%s\n",
994 meta_servers[i].ip_addr,
995 meta_servers[i].idle_time,
996 meta_servers[i].hostname,
997 meta_servers[i].num_players,
998 meta_servers[i].version,
999 meta_servers[i].text_comment);
1005 #ifdef MS2_STANDALONE
1016 void draw_info(
const char *str,
int color) { }
1024 int main(
int argc,
char *argv[])
1030 fprintf(stderr,
"Collecting data.");
1031 while (metaserver2_check_status()) {
1032 fprintf(stderr,
".");
1035 fprintf(stderr,
"\n");
1037 printf(
"%s:%d:%s:%d:%s:%s\n",
1038 meta_servers[i].ip_addr,
1039 meta_servers[i].idle_time,
1040 meta_servers[i].hostname,
1041 meta_servers[i].num_players,
1042 meta_servers[i].version,
1043 meta_servers[i].text_comment);
int init_connection(char *host, int port)
void LOG(LogLevel level, const char *origin, const char *format,...)
sint16 use_config[CONFIG_NUMS]
void draw_info(const char *str, int color)