From 63dc4c5f646941f8793b950c293a46014118f955 Mon Sep 17 00:00:00 2001 From: ac_stef Date: Mon, 1 Sep 2008 11:51:05 +0000 Subject: [PATCH] compressed transfer of cfg files git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@2472 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/client.cpp | 17 ++++++----- source/src/clients2c.cpp | 7 +++-- source/src/protocol.h | 1 + source/src/protos.h | 4 +-- source/src/server.cpp | 66 ++++++++++++++++++++++++++-------------- source/src/worldio.cpp | 46 ++++++++++++++++++++++------ 6 files changed, 97 insertions(+), 44 deletions(-) diff --git a/source/src/client.cpp b/source/src/client.cpp index ed3cb96d..4ebc1014 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -445,20 +445,21 @@ void sendmap(char *mapname) else mapname = getclientmap(); if(securemapcheck(mapname)) return; - int mapsize, cfgsize; + int mapsize, cfgsize, cfgsizegz; uchar *mapdata = readmap(path(mapname), &mapsize); - uchar *cfgdata = readmcfg(path(mapname), &cfgsize); + uchar *cfgdata = readmcfggz(path(mapname), &cfgsize, &cfgsizegz); if(!mapdata) return; - if(!cfgdata) cfgsize = 0; + if(!cfgdata) { cfgsize = 0; cfgsizegz = 0; } - ENetPacket *packet = enet_packet_create(NULL, MAXTRANS + mapsize + cfgsize, ENET_PACKET_FLAG_RELIABLE); + ENetPacket *packet = enet_packet_create(NULL, MAXTRANS + mapsize + cfgsizegz, ENET_PACKET_FLAG_RELIABLE); ucharbuf p(packet->data, packet->dataLength); putint(p, SV_SENDMAP); sendstring(mapname, p); putint(p, mapsize); putint(p, cfgsize); - if(MAXMAPSENDSIZE - p.length() < mapsize + cfgsize) + putint(p, cfgsizegz); + if(MAXMAPSENDSIZE - p.length() < mapsize + cfgsizegz || cfgsize > MAXCFGFILESIZE) { conoutf("map %s is too large to send", mapname); delete[] mapdata; @@ -468,16 +469,16 @@ void sendmap(char *mapname) } p.put(mapdata, mapsize); delete[] mapdata; - if(cfgsize) + if(cfgsizegz) { - p.put(cfgdata, cfgsize); + p.put(cfgdata, cfgsizegz); delete[] cfgdata; } enet_packet_resize(packet, p.length()); sendpackettoserv(2, packet); conoutf("sending map %s to server...", mapname); - s_sprintfd(msg)("[map %s uploaded to server, \"getmap\" to receive it]", mapname); + s_sprintfd(msg)("[map %s uploaded to server, \"/getmap\" to receive it]", mapname); toserver(msg); } diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 03ba98cb..915d8e58 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -767,7 +767,8 @@ void receivefile(uchar *data, int len) conoutf("received map \"%s\" from server, reloading..", &text); int mapsize = getint(p); int cfgsize = getint(p); - int size = mapsize + cfgsize; + int cfgsizegz = getint(p); + int size = mapsize + cfgsizegz; if(p.remaining() < size) { p.forceoverread(); @@ -780,8 +781,8 @@ void receivefile(uchar *data, int len) } writemap(path(text), mapsize, &p.buf[p.len]); p.len += mapsize; - writecfg(path(text), cfgsize, &p.buf[p.len]); - p.len += cfgsize; + writecfggz(path(text), cfgsize, cfgsizegz, &p.buf[p.len]); + p.len += cfgsizegz; changemapserv(text, gamemode); break; } diff --git a/source/src/protocol.h b/source/src/protocol.h index 3d5a229e..d8624bb9 100644 --- a/source/src/protocol.h +++ b/source/src/protocol.h @@ -8,6 +8,7 @@ #define DEMO_VERSION 1 // bump when demo format changes #define DEMO_MAGIC "ASSAULTCUBE_DEMO" #define MAXMAPSENDSIZE 65536 +#define MAXCFGFILESIZE 65536 // network messages codes, c2s, c2c, s2c enum diff --git a/source/src/protos.h b/source/src/protos.h index 6be00e28..e6dcbde1 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -474,9 +474,9 @@ extern void render_particles(int time, int typemask = ~0); extern void save_world(char *fname); extern bool load_world(char *mname); extern void writemap(char *name, int size, uchar *data); -extern void writecfg(char *name, int size, uchar *data); +extern void writecfggz(char *name, int size, int sizegz, uchar *data); extern uchar *readmap(char *name, int *size); -extern uchar *readmcfg(char *name, int *size); +extern uchar *readmcfggz(char *name, int *size, int *sizegz); // physics extern float raycube(const vec &o, const vec &ray, vec &surface); diff --git a/source/src/server.cpp b/source/src/server.cpp index a1ed1d08..92a557e5 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -1841,22 +1841,23 @@ void sendwhois(int sender, int cn) #define SERVERMAP_PATH "packages/maps/servermaps/" string copyname; -int copysize, copymapsize, copycfgsize; +int copysize, copymapsize, copycfgsize, copycfgsizegz; uchar *copydata = NULL; bool mapavailable(const char *mapname) { return !strcmp(copyname, mapname); } -bool sendmapserv(int n, string mapname, int mapsize, int cfgsize, uchar *data) +bool sendmapserv(int n, string mapname, int mapsize, int cfgsize, int cfgsizegz, uchar *data) { string name; FILE *fp; bool written = false; - if(!mapname[0] || mapsize <= 0 || mapsize + cfgsize > MAXMAPSENDSIZE) return false; + if(!mapname[0] || mapsize <= 0 || mapsize + cfgsizegz > MAXMAPSENDSIZE || cfgsize > MAXCFGFILESIZE) return false; s_strcpy(copyname, mapname); copymapsize = mapsize; copycfgsize = cfgsize; - copysize = mapsize + cfgsize; + copycfgsizegz = cfgsizegz; + copysize = mapsize + cfgsizegz; DELETEA(copydata); copydata = new uchar[copysize]; memcpy(copydata, data, copysize); @@ -1873,8 +1874,12 @@ bool sendmapserv(int n, string mapname, int mapsize, int cfgsize, uchar *data) fp = fopen(name, "wb"); if(fp) { - fwrite(copydata + copymapsize, 1, copycfgsize, fp); + uchar *rawcfg = new uchar[copycfgsize]; + uLongf rawsize = copycfgsize; + if(uncompress(rawcfg, &rawsize, copydata + copymapsize, copycfgsizegz) == Z_OK && rawsize - copycfgsize == 0) + fwrite(rawcfg, 1, copycfgsize, fp); fclose(fp); + DELETEA(rawcfg); written = true; } } @@ -1890,6 +1895,7 @@ ENetPacket *getmapserv(int n) sendstring(copyname, p); putint(p, copymapsize); putint(p, copycfgsize); + putint(p, copycfgsizegz); p.put(copydata, copysize); enet_packet_resize(packet, p.length()); return packet; @@ -1897,12 +1903,17 @@ ENetPacket *getmapserv(int n) // provide maps by the server +#define GZBUFSIZE ((MAXCFGFILESIZE * 11) / 10) + void getservermap(void) { + static uchar *gzbuf = NULL; string cgzname, cfgname; - int cgzsize, cfgsize; + int cgzsize, cfgsize, cfgsizegz; const char *name = behindpath(smapname); // no paths allowed here + if(!gzbuf) gzbuf = new uchar[GZBUFSIZE]; + if(!gzbuf) return; if(!strcmp(name, behindpath(copyname))) return; s_sprintf(cgzname)(SERVERMAP_PATH "%s.cgz", name); path(cgzname); @@ -1919,18 +1930,28 @@ void getservermap(void) path(cfgname); uchar *cgzdata = (uchar *)loadfile(cgzname, &cgzsize); uchar *cfgdata = (uchar *)loadfile(cfgname, &cfgsize); - if(cgzdata) + if(cgzdata && cfgsize < MAXCFGFILESIZE) { - if(!cfgdata) cfgsize = 0; - s_strcpy(copyname, name); - copymapsize = cgzsize; - copycfgsize = cfgsize; - copysize = cgzsize + cfgsize; - DELETEA(copydata); - copydata = new uchar[copysize]; - memcpy(copydata, cgzdata, cgzsize); - memcpy(copydata + cgzsize, cfgdata, cfgsize); - logger->writeline(log::info,"loaded map %s, %d + %d bytes.", cgzname, cgzsize, cfgsize); + uLongf gzbufsize = GZBUFSIZE; + if(!cfgdata || compress2(gzbuf, &gzbufsize, cfgdata, cfgsize, 9) != Z_OK) + { + cfgsize = 0; + gzbufsize = 0; + } + cfgsizegz = (int) gzbufsize; + if(cgzsize + cfgsizegz < MAXMAPSENDSIZE) + { + s_strcpy(copyname, name); + copymapsize = cgzsize; + copycfgsize = cfgsize; + copycfgsizegz = cfgsizegz; + copysize = cgzsize + cfgsizegz; + DELETEA(copydata); + copydata = new uchar[copysize]; + memcpy(copydata, cgzdata, cgzsize); + memcpy(copydata + cgzsize, gzbuf, cfgsizegz); + logger->writeline(log::info,"loaded map %s, %d + %d(%d) bytes.", cgzname, cgzsize, cfgsize, cfgsizegz); + } } DELETEA(cgzdata); DELETEA(cfgdata); @@ -2392,17 +2413,18 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1 filtertext(text, text); int mapsize = getint(p); int cfgsize = getint(p); - if(p.remaining() < mapsize + cfgsize) + int cfgsizegz = getint(p); + if(p.remaining() < mapsize + cfgsizegz) { p.forceoverread(); break; } - if(sendmapserv(sender, text, mapsize, cfgsize, &p.buf[p.len])) + if(sendmapserv(sender, text, mapsize, cfgsize, cfgsizegz, &p.buf[p.len])) { - logger->writeline(log::info,"[%s] %s sent map %s, %d + %d bytes written", - clients[sender]->hostname, clients[sender]->name, text, mapsize, cfgsize); + logger->writeline(log::info,"[%s] %s sent map %s, %d + %d(%d) bytes written", + clients[sender]->hostname, clients[sender]->name, text, mapsize, cfgsize, cfgsizegz); } - p.len += mapsize + cfgsize; + p.len += mapsize + cfgsizegz; break; } diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index bace283c..ebabbdc9 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -125,22 +125,50 @@ uchar *readmap(char *name, int *size) return data; } -void writecfg(char *name, int size, uchar *data) +void writecfggz(char *name, int size, int sizegz, uchar *data) { - if(!size) return; + if(size < 1 || !sizegz || size > MAXCFGFILESIZE) return; setnames(name); - FILE *f = openfile(mcfname, "w"); - if(!f) { conoutf("\f3could not write config to %s", mcfname); return; } - fwrite(data, 1, size, f); - fclose(f); - conoutf("wrote map config to %s", mcfname); + + uchar *rawcfg = new uchar[size]; + uLongf rawsize = size; + if(rawcfg && uncompress(rawcfg, &rawsize, data, sizegz) == Z_OK && rawsize - size == 0) + { + FILE *f = openfile(mcfname, "w"); + if(f) + { + fwrite(rawcfg, 1, size, f); + fclose(f); + conoutf("wrote map config to %s", mcfname); + } + else + { + conoutf("\f3could not write config to %s", mcfname); + } + } + DELETEA(rawcfg); } -uchar *readmcfg(char *name, int *size) +#define GZBUFSIZE ((MAXCFGFILESIZE * 11) / 10) + +uchar *readmcfggz(char *name, int *size, int *sizegz) { setnames(name); + uchar *gzbuf = new uchar[GZBUFSIZE]; uchar *data = (uchar*)loadfile(mcfname, size, "r"); - return data; + if(data && *size < MAXCFGFILESIZE) + { + uLongf gzbufsize = GZBUFSIZE; + if(compress2(gzbuf, &gzbufsize, data, *size, 9) != Z_OK) + { + *size = 0; + gzbufsize = 0; + DELETEA(gzbuf); + } + *sizegz = (int) gzbufsize; + } + DELETEA(data); + return gzbuf; }