[Freeciv-Dev] Re: (PR#2757) Patch: New metaserver sample civclient/civse
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=2757 >
a new verion. add support for gui-gtk and gui-xaw. Just about ready.
-mike
? client/.clinet.c.swp
Index: client/clinet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.c,v
retrieving revision 1.101
diff -u -r1.101 clinet.c
--- client/clinet.c 24 Sep 2004 20:18:39 -0000 1.101
+++ client/clinet.c 25 Sep 2004 06:42:52 -0000
@@ -67,6 +67,7 @@
#include "mem.h"
#include "netintf.h"
#include "packets.h"
+#include "registry.h"
#include "support.h"
#include "version.h"
@@ -93,7 +94,7 @@
static struct server_list *lan_servers;
static union my_sockaddr server_addr;
-/**************************************************************************
+/*************************************************************************
Close socket and cleanup. This one doesn't print a message, so should
do so before-hand if necessary.
**************************************************************************/
@@ -492,6 +493,95 @@
}
#endif
+/**************************************************************************
+...
+**************************************************************************/
+const char *get_metaserver_state_text(int state_id)
+{
+ switch (state_id) {
+ case 'P': return _("Pregame");
+ case 'S': return _("Waiting");
+ case 'R': return _("Running");
+ case 'E': return _("Endgame");
+ default: return _("Unknown");
+ }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static struct server_list *parse_metaserver_data(fz_FILE *f)
+{
+ struct server_list *server_list;
+ struct section_file the_file, *file = &the_file;
+ int nservers, i, j;
+
+ server_list = fc_malloc(sizeof(struct server_list));
+ server_list_init(server_list);
+
+ /* This call closes f. */
+ if (!section_file_load_from_stream(file, f)) {
+ return server_list;
+ }
+
+ nservers = secfile_lookup_int_default(file, 0, "main.nservers");
+
+ for (i = 0; i < nservers; i++) {
+ char *host, *port, *version, *state, *message, *nplayers;
+ int n;
+ struct server *pserver = (struct server*)fc_malloc(sizeof(struct server));
+
+ host = secfile_lookup_str_default(file, "", "server%d.host", i);
+ pserver->host = mystrdup(host);
+
+ port = secfile_lookup_str_default(file, "", "server%d.port", i);
+ pserver->port = mystrdup(port);
+
+ version = secfile_lookup_str_default(file, "", "server%d.version", i);
+ pserver->version = mystrdup(version);
+
+ state = secfile_lookup_str_default(file, "", "server%d.state", i);
+ pserver->state = mystrdup(state);
+
+ message = secfile_lookup_str_default(file, "", "server%d.message", i);
+ pserver->message = mystrdup(message);
+
+ nplayers = secfile_lookup_str_default(file, "0", "server%d.nplayers", i);
+ pserver->nplayers = mystrdup(nplayers);
+ n = atoi(nplayers);
+
+ if (n > 0) {
+ pserver->players = fc_malloc(n * sizeof(*pserver->players));
+ } else {
+ pserver->players = NULL;
+ }
+
+ for (j = 0; j < n; j++) {
+ char *name, *nation, *type, *host;
+
+ name = secfile_lookup_str_default(file, "",
+ "server%d.player%d.name", i, j);
+ pserver->players[j].name = mystrdup(name);
+
+ type = secfile_lookup_str_default(file, "",
+ "server%d.player%d.type", i, j);
+ pserver->players[j].type = mystrdup(type);
+
+ host = secfile_lookup_str_default(file, "",
+ "server%d.player%d.host", i, j);
+ pserver->players[j].host = mystrdup(host);
+
+ nation = secfile_lookup_str_default(file, "",
+ "server%d.player%d.nation", i, j);
+ pserver->players[j].nation = mystrdup(nation);
+ }
+
+ server_list_insert(server_list, pserver);
+ }
+
+ section_file_free(file);
+ return server_list;
+}
/**************************************************************************
Create the list of servers from the metaserver
@@ -500,69 +590,27 @@
**************************************************************************/
struct server_list *create_server_list(char *errbuf, int n_errbuf)
{
- struct server_list *server_list;
union my_sockaddr addr;
int s;
fz_FILE *f;
- char *proxy_url;
- char urlbuf[512];
- char *urlpath;
- char *server;
- int port;
- char str[512];
+ const char *urlpath;
+ char metaname[MAX_LEN_ADDR];
+ int metaport;
+ const char *capstr;
+ char str[MAX_LEN_PACKET];
char machine_string[128];
#ifdef HAVE_UNAME
struct utsname un;
#endif
- if ((proxy_url = getenv("http_proxy"))) {
- if (strncmp(proxy_url, "http://", strlen("http://")) != 0) {
- (void) mystrlcpy(errbuf, _("Invalid $http_proxy value, must "
- "start with 'http://'"), n_errbuf);
- return NULL;
- }
- sz_strlcpy(urlbuf, proxy_url);
- } else {
- if (strncmp(metaserver, "http://", strlen("http://")) != 0) {
- (void) mystrlcpy(errbuf, _("Invalid metaserver URL, must start "
- "with 'http://'"), n_errbuf);
- return NULL;
- }
- sz_strlcpy(urlbuf, metaserver);
- }
- server = &urlbuf[strlen("http://")];
-
- {
- char *s;
- if ((s = strchr(server,':'))) {
- if (sscanf(&s[1], "%d", &port) != 1) {
- port = 80;
- }
- s[0] = '\0';
- s++;
- while (my_isdigit(s[0])) {
- s++;
- }
- } else {
- port = 80;
- if (!(s = strchr(server,'/'))) {
- s = &server[strlen(server)];
- }
- } /* s now points past the host[:port] part */
-
- if (s[0] == '/') {
- s[0] = '\0';
- s++;
- } else if (s[0] != '\0') {
- (void) mystrlcpy(errbuf, _("Invalid $http_proxy value, cannot "
- "find separating '/'"), n_errbuf);
- /* which is obligatory if more characters follow */
- return NULL;
- }
- urlpath = s;
+ urlpath = my_lookup_httpd(metaname, &metaport, METALIST_ADDR);//metaserver);
+ if (!urlpath) {
+ (void) mystrlcpy(errbuf, _("Invalid $http_proxy or metaserver value, must "
+ "start with 'http://'"), n_errbuf);
+ return NULL;
}
- if (!net_lookup_service(server, port, &addr)) {
+ if (!net_lookup_service(metaname, metaport, &addr)) {
(void) mystrlcpy(errbuf, _("Failed looking up host"), n_errbuf);
return NULL;
}
@@ -572,7 +620,7 @@
return NULL;
}
- if(connect(s, &addr.sockaddr, sizeof (addr)) == -1) {
+ if(connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) {
(void) mystrlcpy(errbuf, mystrerror(), n_errbuf);
my_closesocket(s);
return NULL;
@@ -596,56 +644,34 @@
#endif
#endif /* HAVE_UNAME */
- my_snprintf(str,sizeof(str),
- "GET %s%s%s HTTP/1.0\r\nUser-Agent: Freeciv/%s %s %s %s\r\n\r\n",
- proxy_url ? "" : "/",
- urlpath,
- proxy_url ? metaserver : "",
- VERSION_STRING,
- client_string,
- machine_string,
- default_tileset_name);
-
- f = my_querysocket(s, str, strlen(str));
-
-#define NEXT_FIELD p=strstr(p,"<TD>"); if(!p) continue; p+=4;
-#define END_FIELD p=strstr(p,"</TD>"); if(!p) continue; *p++='\0';
-#define GET_FIELD(x) NEXT_FIELD (x)=p; END_FIELD
+ capstr = my_url_encode(our_capability);
- server_list = fc_malloc(sizeof(struct server_list));
- server_list_init(server_list);
+ my_snprintf(str, sizeof(str),
+ "POST %s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "User-Agent: Freeciv/%s %s %s\r\n"
+ "Connection: close\r\n"
+ "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n"
+ "client_cap=%s\r\n",
+ urlpath,
+ metaname, metaport,
+ VERSION_STRING, client_string, machine_string,
+ strlen("client_cap=")+strlen(capstr),
+ capstr);
- while(fz_fgets(str, 512, f)) {
- if((0 == strncmp(str, "<TR BGCOLOR",11)) && strchr(str, '\n')) {
- char *name,*port,*version,*status,*players,*metastring;
- char *p;
- struct server *pserver = (struct server*)fc_malloc(sizeof(struct
server));
-
- p=strstr(str,"<a"); if(!p) continue;
- p=strchr(p,'>'); if(!p) continue;
- name=++p;
- p=strstr(p,"</a>"); if(!p) continue;
- *p++='\0';
-
- GET_FIELD(port);
- GET_FIELD(version);
- GET_FIELD(status);
- GET_FIELD(players);
- GET_FIELD(metastring);
-
- pserver->name = mystrdup(name);
- pserver->port = mystrdup(port);
- pserver->version = mystrdup(version);
- pserver->status = mystrdup(status);
- pserver->players = mystrdup(players);
- pserver->metastring = mystrdup(metastring);
+ f = my_querysocket(s, str, strlen(str));
- server_list_insert(server_list, pserver);
- }
+ /* skip HTTP headers */
+ while (fz_fgets(str, sizeof(str), f) && strcmp(str, "\r\n") != 0) {
+ /* nothing */
}
- fz_fclose(f);
- return server_list;
+ /* XXX: TODO check for magic Content-Type: text/x-ini -vasc */
+
+ /* parse HTTP message body */
+ return parse_metaserver_data(f);
}
/**************************************************************************
@@ -656,17 +682,31 @@
void delete_server_list(struct server_list *server_list)
{
server_list_iterate(*server_list, ptmp)
- free(ptmp->name);
+ int i;
+ int n = atoi(ptmp->nplayers);
+
+ free(ptmp->host);
free(ptmp->port);
free(ptmp->version);
- free(ptmp->status);
- free(ptmp->players);
- free(ptmp->metastring);
+ free(ptmp->state);
+ free(ptmp->message);
+
+ if (ptmp->players) {
+ for (i = 0; i < n; i++) {
+ free(ptmp->players[i].name);
+ free(ptmp->players[i].type);
+ free(ptmp->players[i].host);
+ free(ptmp->players[i].nation);
+ }
+ free(ptmp->players);
+ }
+ free(ptmp->nplayers);
+
free(ptmp);
server_list_iterate_end;
server_list_unlink_all(server_list);
- free(server_list);
+ free(server_list);
}
/**************************************************************************
@@ -790,7 +830,7 @@
char version[256];
char status[256];
char players[256];
- char metastring[1024];
+ char message[1024];
fd_set readfs, exceptfs;
struct timeval tv;
@@ -826,7 +866,7 @@
dio_get_string(&din, version, sizeof(version));
dio_get_string(&din, status, sizeof(status));
dio_get_string(&din, players, sizeof(players));
- dio_get_string(&din, metastring, sizeof(metastring));
+ dio_get_string(&din, message, sizeof(message));
if (!mystrcasecmp("none", servername)) {
from = gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
@@ -836,7 +876,7 @@
/* UDP can send duplicate or delayed packets. */
server_list_iterate(*lan_servers, aserver) {
- if (!mystrcasecmp(aserver->name, servername)
+ if (!mystrcasecmp(aserver->host, servername)
&& !mystrcasecmp(aserver->port, port)) {
return lan_servers;
}
@@ -846,12 +886,13 @@
("Received a valid announcement from a server on the LAN."));
pserver = (struct server*)fc_malloc(sizeof(struct server));
- pserver->name = mystrdup(servername);
+ pserver->host = mystrdup(servername);
pserver->port = mystrdup(port);
pserver->version = mystrdup(version);
- pserver->status = mystrdup(status);
- pserver->players = mystrdup(players);
- pserver->metastring = mystrdup(metastring);
+ pserver->state = mystrdup(status);
+ pserver->nplayers = mystrdup(players);
+ pserver->message = mystrdup(message);
+ pserver->players = NULL;
server_list_insert(lan_servers, pserver);
} else {
Index: client/clinet.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.h,v
retrieving revision 1.19
diff -u -r1.19 clinet.h
--- client/clinet.h 13 Apr 2004 16:40:00 -0000 1.19
+++ client/clinet.h 25 Sep 2004 06:42:52 -0000
@@ -14,7 +14,7 @@
#define FC__CLINET_H
#define DEFAULT_SOCK_PORT 5555
-#define METALIST_ADDR "http://meta.freeciv.org/metaserver/"
+#define METALIST_ADDR "http://meta.freeciv.org/~kauf/metaserver.phtml"
#define SERVER_LAN_PORT 4555
#define SERVER_LAN_TTL 1
@@ -43,12 +43,24 @@
struct server
{
- char *name;
+ char *host;
char *port;
+ char *capability;
+ char *patches;
char *version;
- char *status;
- char *players;
- char *metastring;
+ char *state;
+ char *topic;
+ char *message;
+
+ struct players
+ {
+ char *name;
+ char *type;
+ char *host;
+ char *nation;
+ } *players;
+
+ char *nplayers;
};
#define SPECLIST_TAG server
@@ -59,6 +71,7 @@
TYPED_LIST_ITERATE(struct server, serverlist, pserver)
#define server_list_iterate_end LIST_ITERATE_END
+const char *get_metaserver_state_text(int state_id);
struct server_list *create_server_list(char *errbuf, int n_errbuf);
void delete_server_list(struct server_list *server_list);
int begin_lanserver_scan(void);
Index: client/gui-gtk/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/connectdlg.c,v
retrieving revision 1.47
diff -u -r1.47 connectdlg.c
--- client/gui-gtk/connectdlg.c 9 Sep 2004 21:22:33 -0000 1.47
+++ client/gui-gtk/connectdlg.c 25 Sep 2004 06:42:52 -0000
@@ -256,12 +256,12 @@
row[i] = buf[i];
}
server_list_iterate(*server_list,pserver) {
- sz_strlcpy(buf[0], pserver->name);
+ sz_strlcpy(buf[0], pserver->host);
sz_strlcpy(buf[1], pserver->port);
sz_strlcpy(buf[2], pserver->version);
- sz_strlcpy(buf[3], _(pserver->status));
- sz_strlcpy(buf[4], pserver->players);
- sz_strlcpy(buf[5], pserver->metastring);
+ sz_strlcpy(buf[3], _(pserver->state));
+ sz_strlcpy(buf[4], pserver->nplayers);
+ sz_strlcpy(buf[5], pserver->message);
gtk_clist_append(GTK_CLIST(lan_list), row);
} server_list_iterate_end;
@@ -599,12 +599,12 @@
row[i]=buf[i];
server_list_iterate(*server_list,pserver) {
- sz_strlcpy(buf[0], pserver->name);
+ sz_strlcpy(buf[0], pserver->host);
sz_strlcpy(buf[1], pserver->port);
sz_strlcpy(buf[2], pserver->version);
- sz_strlcpy(buf[3], _(pserver->status));
- sz_strlcpy(buf[4], pserver->players);
- sz_strlcpy(buf[5], pserver->metastring);
+ sz_strlcpy(buf[3], _(pserver->state));
+ sz_strlcpy(buf[4], pserver->nplayers);
+ sz_strlcpy(buf[5], pserver->message);
gtk_clist_append(GTK_CLIST(meta_list), row);
}
Index: client/gui-gtk-2.0/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/connectdlg.c,v
retrieving revision 1.48
diff -u -r1.48 connectdlg.c
--- client/gui-gtk-2.0/connectdlg.c 19 Sep 2004 01:00:54 -0000 1.48
+++ client/gui-gtk-2.0/connectdlg.c 25 Sep 2004 06:42:52 -0000
@@ -260,12 +260,12 @@
server_list_iterate(*server_list, pserver) {
GtkTreeIter it;
- row[0] = pserver->name;
+ row[0] = pserver->host;
row[1] = pserver->port;
row[2] = pserver->version;
- row[3] = _(pserver->status);
- row[4] = pserver->players;
- row[5] = pserver->metastring;
+ row[3] = _(pserver->state);
+ row[4] = pserver->nplayers;
+ row[5] = pserver->message;
gtk_list_store_append(storelan, &it);
gtk_list_store_set(storelan, &it,
@@ -1143,7 +1143,7 @@
static int get_meta_list(char *errbuf, int n_errbuf)
{
struct server_list *server_list = create_server_list(errbuf, n_errbuf);
- gchar *row[6];
+ gchar *row[3];
if (!server_list) {
return -1;
@@ -1154,12 +1154,12 @@
server_list_iterate(*server_list, pserver) {
GtkTreeIter it;
- row[0] = pserver->name;
+ row[0] = pserver->host;
row[1] = pserver->port;
row[2] = pserver->version;
- row[3] = _(pserver->status);
- row[4] = pserver->players;
- row[5] = pserver->metastring;
+ row[3] = _(pserver->state);
+ row[4] = pserver->nplayers;
+ row[5] = pserver->message;
gtk_list_store_append(storemeta, &it);
gtk_list_store_set(storemeta, &it,
Index: client/gui-xaw/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/connectdlg.c,v
retrieving revision 1.35
diff -u -r1.35 connectdlg.c
--- client/gui-xaw/connectdlg.c 9 Sep 2004 21:22:34 -0000 1.35
+++ client/gui-xaw/connectdlg.c 25 Sep 2004 06:42:52 -0000
@@ -514,8 +514,8 @@
server_list_iterate(*server_list,pserver) {
if (pserver == NULL) continue;
my_snprintf(line, sizeof(line), "%-35s %-5s %-11s %-11s %2s %s",
- pserver->name, pserver->port, pserver->version,
- _(pserver->status), pserver->players, pserver->metastring);
+ pserver->host, pserver->port, pserver->version,
+ _(pserver->state), pserver->nplayers, pserver->message);
if (*list) free(*list);
*list=mystrdup(line);
list++;
Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.33
diff -u -r1.33 connecthand.c
--- server/connecthand.c 17 Sep 2004 19:04:21 -0000 1.33
+++ server/connecthand.c 25 Sep 2004 06:42:52 -0000
@@ -175,7 +175,7 @@
send_conn_info(dest, &game.est_connections);
conn_list_insert_back(&game.est_connections, pconn);
send_conn_info(&game.est_connections, dest);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
}
/**************************************************************************
Index: server/meta.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.c,v
retrieving revision 1.60
diff -u -r1.60 meta.c
--- server/meta.c 17 May 2004 02:16:15 -0000 1.60
+++ server/meta.c 25 Sep 2004 06:42:52 -0000
@@ -11,28 +11,11 @@
GNU General Public License for more details.
***********************************************************************/
-/*
- * This bit sends "I'm here" packages to the metaserver.
- */
-
-/*
-The desc block should look like this:
-1) GameName - Freeciv
-2) Version - 1.5.0
-3) State - Running(Open for new players)
-4) Host - Empty
-5) Port - 5555
-6) NoPlayers - 3
-7) InfoText - Warfare - starts at 8:00 EMT
-
-The info string should look like this:
- GameSpecific text block
-*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,9 +40,12 @@
#include <winsock.h>
#endif
+#include "capstr.h"
+#include "connection.h"
#include "dataio.h"
#include "fcintl.h"
#include "log.h"
+#include "mem.h"
#include "netintf.h"
#include "support.h"
#include "timing.h"
@@ -72,9 +58,10 @@
bool server_is_open = FALSE;
-static int sockfd=0;
static union my_sockaddr meta_addr;
-
+static char metaname[MAX_LEN_ADDR];
+static int metaport;
+static char *metaserver_path;
/*************************************************************************
Return static string with default info line to send to metaserver.
@@ -99,11 +86,6 @@
*************************************************************************/
void meta_addr_split(void)
{
- char *metaserver_port_separator = strchr(srvarg.metaserver_addr, ':');
-
- if (metaserver_port_separator) {
- sscanf(metaserver_port_separator + 1, "%hu", &srvarg.metaserver_port);
- }
}
/*************************************************************************
@@ -111,122 +93,210 @@
*************************************************************************/
char *meta_addr_port(void)
{
- static char retstr[300];
+ return srvarg.metaserver_addr;
+}
- if (srvarg.metaserver_port == DEFAULT_META_SERVER_PORT) {
- sz_strlcpy(retstr, srvarg.metaserver_addr);
- } else {
- my_snprintf(retstr, sizeof(retstr),
- "%s:%d", srvarg.metaserver_addr, srvarg.metaserver_port);
- }
+/*************************************************************************
+...
+*************************************************************************/
+static void metaserver_failed(void)
+{
+ con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
+ con_flush();
- return retstr;
+ server_close_meta();
}
/*************************************************************************
-...
- Returns true if able to send
+ construct the POST message and send info to metaserver.
*************************************************************************/
-static bool send_to_metaserver(char *desc, char *info)
+static bool send_to_metaserver(int flags)
{
- unsigned char buffer[MAX_LEN_PACKET];
- struct data_out dout;
- size_t size;
+ static char msg[8192];
+ static char str[8192];
+ int rest = sizeof(str);
+ int n;
+ char *s = str;
+ char host[512];
+ char state;
+ int sock;
- dio_output_init(&dout, buffer, sizeof(buffer));
+ if (!server_is_open) {
+ return FALSE;
+ }
- if(sockfd<=0)
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ freelog(LOG_ERROR, "Metaserver: can't open stream socket: %s",
+ mystrerror());
+ metaserver_failed();
+ return FALSE;
+ }
+
+ if (connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) {
+ freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror());
+ metaserver_failed();
+ my_closesocket(sock);
return FALSE;
+ }
- dio_put_uint16(&dout, 0);
- dio_put_uint8(&dout, PACKET_UDP_PCKT);
- dio_put_string(&dout, desc);
- dio_put_string(&dout, info);
+ switch(server_state) {
+ case PRE_GAME_STATE:
+ state = 'P';
+ break;
+ case SELECT_RACES_STATE:
+ state = 'S';
+ break;
+ case RUN_GAME_STATE:
+ state = 'R';
+ break;
+ case GAME_OVER_STATE:
+ state = 'E';
+ break;
+ default:
+ state = 'U';
+ break;
+ }
- size = dio_output_used(&dout);
+ /* get hostname */
+ if (my_gethostname(host, sizeof(host)) != 0) {
+ sz_strlcpy(host, "unknown");
+ }
- dio_output_rewind(&dout);
- dio_put_uint16(&dout, size);
+ my_snprintf(s, rest, "host=%s&port=%d&state=%c&", host, srvarg.port, state);
+ s = end_of_strn(s, &rest);
- my_writesocket(sockfd, buffer, size);
- return TRUE;
-}
+ if (flags & META_GOODBYE) {
+ mystrlcpy(s, "bye=1&", rest);
+ s = end_of_strn(s, &rest);
+ } else {
+ if (flags & META_VERSION) {
+ my_snprintf(s, rest, "version=%s&", my_url_encode(VERSION_STRING));
+ s = end_of_strn(s, &rest);
-/*************************************************************************
-...
-*************************************************************************/
-void server_close_udp(void)
-{
- server_is_open = FALSE;
+ my_snprintf(s, rest, "patches=%s&", my_url_encode("none"));
+ s = end_of_strn(s, &rest);
- if(sockfd<=0)
- return;
- my_closesocket(sockfd);
- sockfd=0;
+ my_snprintf(s, rest, "capability=%s&", my_url_encode(our_capability));
+ s = end_of_strn(s, &rest);
+ }
+
+ if (flags & META_COMMENT) {
+ my_snprintf(s, rest, "topic=%s&",
+ my_url_encode(srvarg.extra_metaserver_info));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "message=%s&",
+ my_url_encode(srvarg.metaserver_info_line));
+ s = end_of_strn(s, &rest);
+ }
+
+ /* NOTE: send info for ALL players or none at all. */
+ if (get_num_human_and_ai_players() == 0) {
+ mystrlcpy(s, "dropplrs=1&", rest);
+ s = end_of_strn(s, &rest);
+ } else {
+ players_iterate(plr) {
+ char type;
+ struct connection *pconn = find_conn_by_user(plr->username);
+
+ if (is_barbarian(plr)) {
+ type = 'B';
+ } else if (plr->ai.control) {
+ type = 'A';
+ } else {
+ type = 'H';
+ }
+
+ my_snprintf(s, rest, "plu[]=%s&", my_url_encode(plr->username));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "plt[]=%c&", type);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "pll[]=%s&", my_url_encode(plr->name));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "pln[]=%s&",
+ my_url_encode(plr->nation != NO_NATION_SELECTED
+ ? get_nation_name_plural(plr->nation)
+ : "none"));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "plh[]=%s&", pconn ? my_url_encode(pconn->addr)
+ : my_url_encode("none"));
+ s = end_of_strn(s, &rest);
+ } players_iterate_end;
+ }
+
+ /* send some variables: should be listed in inverted order
+ * FIXME: these should be input from the settings array */
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("timeout"), game.timeout);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("endyear"), game.end_year);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("generator"), map.generator);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("size"), map.size);
+ s = end_of_strn(s, &rest);
+ }
+
+ n = my_snprintf(msg, sizeof(msg),
+ "POST %s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n"
+ "%s\r\n",
+ metaserver_path,
+ metaname,
+ metaport,
+ sizeof(str)-rest+1,
+ str
+ );
+
+ my_writesocket(sock, msg, n);
+
+ return TRUE;
}
/*************************************************************************
...
*************************************************************************/
-static void metaserver_failed(void)
+void server_close_meta(void)
{
- con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
- con_flush();
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_GOODBYE);
+
+ server_is_open = FALSE;
}
/*************************************************************************
...
*************************************************************************/
-void server_open_udp(void)
+void server_open_meta(void)
{
- char *metaname = srvarg.metaserver_addr;
- int metaport;
- union my_sockaddr bind_addr;
-
- /*
- * Fill in the structure "meta_addr" with the address of the
- * server that we want to connect with, checks if server address
- * is valid, both decimal-dotted and name.
- */
- metaport = srvarg.metaserver_port;
- if (!net_lookup_service(metaname, metaport, &meta_addr)) {
- freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
- metaname,
- metaport);
- metaserver_failed();
- return;
+ const char *path;
+
+ if (metaserver_path) {
+ free(metaserver_path);
+ metaserver_path = NULL;
}
-
- /*
- * Open a UDP socket (an Internet datagram socket).
- */
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- freelog(LOG_ERROR, "Metaserver: can't open datagram socket: %s",
- mystrerror());
- metaserver_failed();
+
+ if (!(path = my_lookup_httpd(metaname, &metaport, srvarg.metaserver_addr))) {
return;
}
+
+ metaserver_path = mystrdup(path);
- /*
- * Bind any local address for us and
- * associate datagram socket with server.
- */
- if (!net_lookup_service(srvarg.bind_addr, 0, &bind_addr)) {
+ if (!net_lookup_service(metaname, metaport, &meta_addr)) {
freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
- srvarg.bind_addr, 0);
- metaserver_failed();
- }
-
- /* set source IP */
- if (bind(sockfd, &bind_addr.sockaddr, sizeof(bind_addr)) == -1) {
- freelog(LOG_ERROR, "Metaserver: bind failed: %s", mystrerror());
- metaserver_failed();
- return;
- }
-
- /* no, this is not weird, see man connect(2) --vasc */
- if (connect(sockfd, &meta_addr.sockaddr, sizeof(meta_addr))==-1) {
- freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror());
+ metaname, metaport);
metaserver_failed();
return;
}
@@ -234,15 +304,12 @@
server_is_open = TRUE;
}
-
/**************************************************************************
...
**************************************************************************/
-bool send_server_info_to_metaserver(bool do_send, bool reset_timer)
+bool send_server_info_to_metaserver(bool do_send, bool reset_timer, int flags)
{
static struct timer *time_since_last_send = NULL;
- char desc[4096], info[4096];
- int num_nonbarbarians = get_num_human_and_ai_players();
if (reset_timer && time_since_last_send)
{
@@ -261,59 +328,6 @@
time_since_last_send = new_timer(TIMER_USER, TIMER_ACTIVE);
}
- /* build description block */
- desc[0]='\0';
-
- cat_snprintf(desc, sizeof(desc), "Freeciv\n");
- cat_snprintf(desc, sizeof(desc), VERSION_STRING"\n");
- /* note: the following strings are not translated here;
- we mark them so they may be translated when received by a client */
- switch(server_state) {
- case PRE_GAME_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Pregame"));
- break;
- case RUN_GAME_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Running"));
- break;
- case GAME_OVER_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Game over"));
- break;
- default:
- cat_snprintf(desc, sizeof(desc), N_("Waiting"));
- }
- cat_snprintf(desc, sizeof(desc), "\n");
- cat_snprintf(desc, sizeof(desc), "%s\n", "UNSET");
- cat_snprintf(desc, sizeof(desc), "%d\n", srvarg.port);
- cat_snprintf(desc, sizeof(desc), "%d\n", num_nonbarbarians);
- cat_snprintf(desc, sizeof(desc), "%s %s", srvarg.metaserver_info_line,
- srvarg.extra_metaserver_info);
-
- /* now build the info block */
- info[0]='\0';
- cat_snprintf(info, sizeof(info),
- "Players:%d Min players:%d Max players:%d\n",
- num_nonbarbarians, game.min_players, game.max_players);
- cat_snprintf(info, sizeof(info),
- "Timeout:%d Year: %s\n",
- game.timeout, textyear(game.year));
-
-
- cat_snprintf(info, sizeof(info),
- "NO: NAME: HOST:\n");
- cat_snprintf(info, sizeof(info),
- "----------------------------------------\n");
-
- players_iterate(pplayer) {
- if (!is_barbarian(pplayer)) {
- /* Fixme: how should metaserver handle multi-connects?
- * Uses player_addr_hack() for now.
- */
- cat_snprintf(info, sizeof(info), "%2d %-20s %s\n",
- pplayer->player_no, pplayer->name,
- player_addr_hack(pplayer));
- }
- } players_iterate_end;
-
clear_timer_start(time_since_last_send);
- return send_to_metaserver(desc, info);
+ return send_to_metaserver(flags);
}
Index: server/meta.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.h,v
retrieving revision 1.24
diff -u -r1.24 meta.h
--- server/meta.h 7 Nov 2002 16:04:54 -0000 1.24
+++ server/meta.h 25 Sep 2004 06:42:52 -0000
@@ -15,26 +15,26 @@
#include "shared.h" /* bool type */
-/*
- * Definitions for UDP.
- */
-
-#define DEFAULT_META_SERVER_NO_SEND TRUE
-#define DEFAULT_META_SERVER_PORT 12245
-#define DEFAULT_META_SERVER_ADDR "meta.freeciv.org"
-#define METASERVER_UPDATE_INTERVAL (3*60)
-
-#define PACKET_UDP_PCKT 2
+#define DEFAULT_META_SERVER_NO_SEND TRUE
+#define DEFAULT_META_SERVER_ADDR "http://meta.freeciv.org/metaserver.phtml"
+#define METASERVER_UPDATE_INTERVAL (3*60)
+
+enum metainfo_type {
+ META_INFO = 0,
+ META_VERSION = 1,
+ META_COMMENT = 2,
+ META_GOODBYE = 4
+};
const char *default_meta_server_info_string(void);
void meta_addr_split(void);
char *meta_addr_port(void);
-void server_close_udp(void);
-void server_open_udp(void);
+void server_close_meta(void);
+void server_open_meta(void);
-bool send_server_info_to_metaserver(bool do_send, bool reset_timer);
+bool send_server_info_to_metaserver(bool do_send, bool reset_timer, int flags);
extern bool server_is_open;
Index: server/sernet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sernet.c,v
retrieving revision 1.121
diff -u -r1.121 sernet.c
--- server/sernet.c 20 Jul 2004 17:05:26 -0000 1.121
+++ server/sernet.c 25 Sep 2004 06:42:53 -0000
@@ -233,7 +233,7 @@
}
#endif
- server_close_udp();
+ server_close_meta();
my_shutdown_network();
}
@@ -397,7 +397,7 @@
sz_strlcpy(srvarg.metaserver_info_line,
"restarting for lack of players");
freelog(LOG_NORMAL, srvarg.metaserver_info_line);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT);
server_state = GAME_OVER_STATE;
force_end_of_sniff = TRUE;
@@ -414,7 +414,7 @@
"restarting in %d seconds for lack of players",
srvarg.quitidle);
freelog(LOG_NORMAL, srvarg.metaserver_info_line);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT);
}
} else {
last_noplayers = 0;
@@ -459,7 +459,7 @@
/* Don't wait if timeout == -1 (i.e. on auto games) */
if (server_state != PRE_GAME_STATE && game.timeout == -1) {
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
return 0;
}
@@ -497,7 +497,7 @@
con_prompt_off(); /* output doesn't generate a new prompt */
if(select(max_desc+1, &readfs, &writefs, &exceptfs, &tv)==0) { /* timeout
*/
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
if(game.timeout != 0
&& (time(NULL)>game.turn_start + game.timeout)
&& (server_state == RUN_GAME_STATE)){
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.198
diff -u -r1.198 srv_main.c
--- server/srv_main.c 21 Sep 2004 05:51:12 -0000 1.198
+++ server/srv_main.c 25 Sep 2004 06:42:53 -0000
@@ -177,7 +177,6 @@
srvarg.metaserver_no_send = DEFAULT_META_SERVER_NO_SEND;
sz_strlcpy(srvarg.metaserver_info_line, default_meta_server_info_string());
sz_strlcpy(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR);
- srvarg.metaserver_port = DEFAULT_META_SERVER_PORT;
srvarg.bind_addr = NULL;
srvarg.port = DEFAULT_SOCK_PORT;
@@ -1379,7 +1378,7 @@
game.nplayers++;
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if (!((game.nplayers == old_nplayers+1)
&& strcmp(player_name, pplayer->name)==0)) {
@@ -1400,7 +1399,7 @@
announce_ai_player(pplayer);
set_ai_level_direct(pplayer, pplayer->ai.skill_level);
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
}
/*************************************************************************
@@ -1549,7 +1548,7 @@
end_phase();
end_turn();
freelog(LOG_DEBUG, "Sendinfotometaserver");
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
conn_list_do_unbuffer(&game.game_connections);
@@ -1607,10 +1606,10 @@
if(!(srvarg.metaserver_no_send)) {
freelog(LOG_NORMAL, _("Sending info to metaserver [%s]"),
meta_addr_port());
- server_open_udp(); /* open socket for meta server */
+ server_open_meta(); /* open socket for meta server */
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE,
META_VERSION|META_COMMENT);
/* accept new players, wait for serverop to start..*/
server_state = PRE_GAME_STATE;
@@ -1667,7 +1666,7 @@
sniff_packets(); /* Accepting commands. */
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if (game.is_new_game) {
load_rulesets();
@@ -1788,7 +1787,7 @@
/* start the game */
server_state = RUN_GAME_STATE;
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if(game.is_new_game) {
/* Before the player map is allocated (and initiailized)! */
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.351
diff -u -r1.351 stdinhand.c
--- server/stdinhand.c 20 Sep 2004 22:06:52 -0000 1.351
+++ server/stdinhand.c 25 Sep 2004 06:42:53 -0000
@@ -496,8 +496,8 @@
**************************************************************************/
static void open_metaserver_connection(struct connection *caller)
{
- server_open_udp();
- if (send_server_info_to_metaserver(TRUE, FALSE)) {
+ server_open_meta();
+ if (send_server_info_to_metaserver(TRUE, FALSE, META_VERSION|META_COMMENT)) {
notify_player(NULL, _("Open metaserver connection to [%s]."),
meta_addr_port());
}
@@ -508,8 +508,8 @@
**************************************************************************/
static void close_metaserver_connection(struct connection *caller)
{
- if (send_server_info_to_metaserver(TRUE, TRUE)) {
- server_close_udp();
+ if (send_server_info_to_metaserver(TRUE, TRUE, META_INFO)) {
+ server_close_meta();
notify_player(NULL, _("Close metaserver connection to [%s]."),
meta_addr_port());
}
@@ -569,7 +569,7 @@
return TRUE;
}
sz_strlcpy(srvarg.metaserver_info_line, arg);
- if (!send_server_info_to_metaserver(TRUE, FALSE)) {
+ if (!send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT)) {
cmd_reply(CMD_METAINFO, caller, C_METAERROR,
_("Not reporting to the metaserver."));
} else {
@@ -824,7 +824,7 @@
notify_player(NULL, _("Game: %s has been added as an AI-controlled player."),
arg);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
pplayer = find_player_by_name(arg);
if (!pplayer)
@@ -955,8 +955,7 @@
"experimental");
if (*srvarg.metaserver_addr != '\0' &&
- ((0 != strcmp(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR)) ||
- (srvarg.metaserver_port != DEFAULT_META_SERVER_PORT))) {
+ ((0 != strcmp(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR)))) {
fprintf(script_file, "metaserver %s\n", meta_addr_port());
}
Index: utility/netintf.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/netintf.c,v
retrieving revision 1.21
diff -u -r1.21 netintf.c
--- utility/netintf.c 17 May 2004 02:16:15 -0000 1.21
+++ utility/netintf.c 25 Sep 2004 06:42:53 -0000
@@ -22,6 +22,7 @@
#include <errno.h>
#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ARPA_INET_H
@@ -226,6 +227,108 @@
return fz_from_stream(fp);
}
+/*************************************************************************
+ Returns a valid httpd server and port, plus the path to the resource
+ at the url location.
+*************************************************************************/
+const char *my_lookup_httpd(char *server, int *port, const char *url)
+{
+ const char *purl, *str, *ppath, *pport;
+
+ if ((purl = getenv("http_proxy"))) {
+ if (strncmp(purl, "http://", strlen("http://")) != 0) {
+ return NULL;
+ }
+ str = purl;
+ } else {
+ if (strncmp(url, "http://", strlen("http://")) != 0) {
+ return NULL;
+ }
+ str = url;
+ }
+
+ str += strlen("http://");
+
+ pport = strchr(str, ':');
+ ppath = strchr(str, '/');
+
+ /* snarf server. */
+ server[0] = '\0';
+
+ if (pport) {
+ strncat(server, str, MIN(MAX_LEN_ADDR, pport-str));
+ } else {
+ if (ppath) {
+ strncat(server, str, MIN(MAX_LEN_ADDR, ppath-str));
+ } else {
+ strncat(server, str, MAX_LEN_ADDR);
+ }
+ }
+
+ /* snarf port. */
+ if (!pport || sscanf(pport+1, "%d", port) != 1) {
+ *port = 80;
+ }
+
+ /* snarf path. */
+ if (!ppath) {
+ ppath = "/";
+ }
+
+ return (purl ? url : ppath);
+}
+
+/*************************************************************************
+ Returns TRUE if ch is an unreserved ASCII character.
+*************************************************************************/
+static bool is_url_safe(unsigned ch)
+{
+ const char *unreserved = "-_.!~*'|";
+
+ if ((ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) {
+ return TRUE;
+ } else {
+ return (strchr(unreserved, ch) != NULL);
+ }
+}
+
+/***************************************************************
+ URL-encode a string as per RFC 2396.
+ Should work for all ASCII based charsets: including UTF-8.
+***************************************************************/
+const char *my_url_encode(const char *txt)
+{
+ static char buf[2048];
+ int pos;
+ unsigned ch;
+ char *ptr;
+
+ /* in a worst case scenario every character needs "% HEX HEX" encoding. */
+ if (sizeof(buf) <= (3*strlen(txt))) {
+ return "";
+ }
+
+ ptr = buf;
+ for (ptr = buf; *txt != '\0'; txt++) {
+ ch = (unsigned char) *txt;
+
+ if (is_url_safe(ch)) {
+ *ptr++ = *txt;
+ pos++;
+ } else if (ch == ' ') {
+ *ptr++ = '+';
+ pos++;
+ } else {
+ sprintf(ptr, "%%%2.2X", ch);
+ ptr += 3;
+ pos += 3;
+ }
+ }
+ *ptr++ = '\0';
+
+ return buf;
+}
+
/**************************************************************************
Finds the next (lowest) free port.
**************************************************************************/
Index: utility/netintf.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/netintf.h,v
retrieving revision 1.11
diff -u -r1.11 netintf.h
--- utility/netintf.h 8 May 2004 19:21:01 -0000 1.11
+++ utility/netintf.h 25 Sep 2004 06:42:53 -0000
@@ -66,4 +66,7 @@
fz_FILE *my_querysocket(int sock, void *buf, size_t size);
int find_next_free_port(int starting_port);
+const char *my_lookup_httpd(char *server, int *port, const char *url);
+const char *my_url_encode(const char *txt);
+
#endif /* FC__NETINTF_H */
|
|