Skip to content
This repository
Browse code

* Kompressionsflag innerhalb von demos wird jetzt nicht mehr ignorie…

…rt. Damit beschraenkt sich das clientseitige Demospeichern auf ein 'netcat' und 'save-demo.rb' ist nicht mehr notwendig. Um alte Demos weiterhin abzuspielen, kann die Environmentvariable UNCOMPRESSED_DEMO_COMPATIBILITY gesetzt werden.

 * Die Unkomprimierten Serverdemos koennen mit 'demo-compress.rb' nachtraeglich komprimiert werden.


git-svn-id: http://infon.googlecode.com/svn/trunk@115 8171fb75-e542-0410-96e4-03d5dd800671
  • Loading branch information...
commit b4f20aa5fa702123990d19498ae860b9454daa46 1 parent 7fd3421
Florian Wesch authored
113 client.c
@@ -106,9 +106,7 @@ static void client_start_compression() {
106 106 if (compression)
107 107 PROTOCOL_ERROR();
108 108
109   - // Bei Demofiles Kompressionstart ignorieren,
110   - // da diese unkomprimiert abgelegt werden.
111   - if (is_file_source)
  109 + if (getenv("UNCOMPRESSED_DEMO_COMPATIBILITY") && is_file_source)
112 110 return;
113 111
114 112 strm.zalloc = Z_NULL;
@@ -171,20 +169,10 @@ static void client_handle_packet(packet_t *packet) {
171 169 }
172 170 }
173 171
174   -static void client_readable(int fd, short event, void *arg) {
175   - struct event *cb_event = arg;
176   -
177   - int ret = evbuffer_read(in_buf, fd, 8192);
178   - if (ret < 0) {
179   - client_destroy(strerror(errno));
180   - return;
181   - } else if (ret == 0) {
182   - client_destroy("eof reached");
183   - return;
184   - }
185   -
186   - traffic += ret;
187   -
  172 +// returns 0 on error
  173 +// returns 1 if more data is needed
  174 +// returns 2 if more time is needed
  175 +static int client_parse_in_buf() {
188 176 restart:
189 177 if (compression) {
190 178 char buf[8192];
@@ -197,13 +185,13 @@ static void client_readable(int fd, short event, void *arg) {
197 185 int ret = inflate(&strm, Z_SYNC_FLUSH);
198 186 if (ret != Z_OK && ret != Z_BUF_ERROR) {
199 187 client_destroy("decompression error");
200   - return;
  188 + return 0;
201 189 }
202 190
203 191 evbuffer_add(packet_buf, buf, sizeof(buf) - strm.avail_out);
204 192 if (EVBUFFER_LENGTH(packet_buf) > 1024 * 1024) {
205   - client_destroy("too much to decompress. funny server?");
206   - return;
  193 + client_destroy("too much to decompress. funny data?");
  194 + return 0;
207 195 }
208 196 } while (strm.avail_out == 0);
209 197 evbuffer_drain(in_buf, EVBUFFER_LENGTH(in_buf) - strm.avail_in);
@@ -215,9 +203,9 @@ static void client_readable(int fd, short event, void *arg) {
215 203 while (EVBUFFER_LENGTH(packet_buf) >= PACKET_HEADER_SIZE) {
216 204 int packet_len = PACKET_HEADER_SIZE + EVBUFFER_DATA(packet_buf)[0];
217 205
218   - // Genuegend Daten da?
  206 + // Nicht genuegend Daten da?
219 207 if (EVBUFFER_LENGTH(packet_buf) < packet_len)
220   - break;
  208 + return 1;
221 209
222 210 // Alten Kompressionszustand merken
223 211 int old_compression = compression;
@@ -227,11 +215,13 @@ static void client_readable(int fd, short event, void *arg) {
227 215 memcpy(&packet, EVBUFFER_DATA(packet_buf), packet_len);
228 216 packet_rewind(&packet);
229 217 client_handle_packet(&packet);
230   - evbuffer_drain(packet_buf, packet_len);
231 218
232 219 // Disconnect Packet?
233 220 if (!client_is_connected())
234   - return;
  221 + return 0;
  222 +
  223 + // Weg damit
  224 + evbuffer_drain(packet_buf, packet_len);
235 225
236 226 // Wurde Kompression aktiviert? Dann Rest des packet_buf zurueck
237 227 // in den in_buf, da es sich dabei bereits um komprimierte Daten
@@ -241,9 +231,31 @@ static void client_readable(int fd, short event, void *arg) {
241 231 evbuffer_drain(packet_buf, EVBUFFER_LENGTH(packet_buf));
242 232 goto restart;
243 233 }
  234 +
  235 + // Beim Demo abspielen muss erst pausiert werden
  236 + if (is_file_source && next_packet_countdown > 0)
  237 + return 2;
244 238 }
  239 +
  240 + return 1;
  241 +}
245 242
246   - event_add(cb_event, NULL);
  243 +static void client_readable(int fd, short event, void *arg) {
  244 + struct event *cb_event = arg;
  245 +
  246 + int ret = evbuffer_read(in_buf, fd, 8192);
  247 + if (ret < 0) {
  248 + client_destroy(strerror(errno));
  249 + return;
  250 + } else if (ret == 0) {
  251 + client_destroy("eof reached");
  252 + return;
  253 + }
  254 +
  255 + traffic += ret;
  256 +
  257 + if (client_parse_in_buf())
  258 + event_add(cb_event, NULL);
247 259 }
248 260
249 261 static void client_writable(int fd, short event, void *arg) {
@@ -274,34 +286,33 @@ int client_is_connected() {
274 286 }
275 287
276 288 void file_loop(int delta) {
277   - static packet_t packet;
278   - static char errbuf[128];
279 289 int ret;
  290 +
280 291 next_packet_countdown -= delta;
  292 +
281 293 while (next_packet_countdown <= 0) {
282   - ret = read(clientfd, &packet, PACKET_HEADER_SIZE);
283   - if (ret != PACKET_HEADER_SIZE) {
284   - snprintf(errbuf, sizeof(errbuf), "eof, reading header: want %d, got %d", PACKET_HEADER_SIZE, ret);
285   - client_destroy(errbuf);
286   - return;
287   - }
  294 + switch (client_parse_in_buf()) {
  295 + // error -> disconnected
  296 + case 0:
  297 + return;
288 298
289   - traffic += ret;
290   -
291   - ret = read(clientfd, &packet.data, packet.len);
292   - if (ret != packet.len) {
293   - snprintf(errbuf, sizeof(errbuf), "eof, reading packet: want %d, got %d", packet.len, ret);
294   - client_destroy(errbuf);
295   - return;
  299 + // more data needed?
  300 + case 1:
  301 + ret = evbuffer_read(in_buf, clientfd, 4096);
  302 +
  303 + if (ret < 0) {
  304 + client_destroy(strerror(errno));
  305 + return;
  306 + } else if (ret == 0) {
  307 + client_destroy("eof");
  308 + return;
  309 + }
  310 +
  311 + traffic += ret;
  312 + break;
  313 + case 2: // call again later
  314 + return;
296 315 }
297   -
298   - traffic += ret;
299   -
300   - packet_rewind(&packet);
301   - client_handle_packet(&packet);
302   -
303   - if (!client_is_connected())
304   - return;
305 316 }
306 317 }
307 318
@@ -394,8 +405,12 @@ int client_open_file(char *filename) {
394 405 return fd;
395 406 }
396 407
397   -void client_init(char *source, char *demo_save_name) {
  408 +void client_init(char *source) {
398 409 struct stat stat_buf;
  410 +
  411 + if (!strcmp(source, "-"))
  412 + source = "/dev/stdin";
  413 +
399 414 if (stat(source, &stat_buf) < 0) {
400 415 #ifdef WIN32
401 416 WSADATA wsa;
2  client.h
@@ -26,7 +26,7 @@ int client_is_connected();
26 26
27 27 int client_traffic();
28 28
29   -void client_init(char *source, char *demo_save_name);
  29 +void client_init(char *source);
30 30 void client_shutdown();
31 31
32 32 #endif
5 demo-compress.rb
... ... @@ -0,0 +1,5 @@
  1 +require 'zlib'
  2 +File.open(ARGV[1], "wb") do |out|
  3 + out.write("\x00\xFE")
  4 + out.write(Zlib::Deflate.deflate(File.read(ARGV[0]), Zlib::BEST_COMPRESSION))
  5 +end
2  demo2graph.rb
@@ -169,7 +169,7 @@ def tick
169 169 when 32:
170 170 welcome = @file.read(len).delete("\n").strip
171 171 when 254:
172   - # puts "compression start (ignored for demos)"
  172 + @file.compress = true
173 173 when 255:
174 174 version = @file.read8
175 175 # puts "server protocol version %d" % @file.read8
BIN  example.demo
Binary file not shown
35 game.c
@@ -152,7 +152,7 @@ void game_init() {
152 152 lua_setglobal(L, "GAME_NAME");
153 153 }
154 154
155   -void game_one_round() {
  155 +void game_one_game() {
156 156 should_end_round = 0;
157 157 game_time = 0;
158 158
@@ -175,28 +175,16 @@ void game_one_round() {
175 175 int lasttick = 0;
176 176 gettimeofday(&start, NULL);
177 177
178   - server_round_start();
179   - player_round_start();
  178 + server_game_start();
  179 + player_game_start();
180 180
181   - // Demo Aufnahme starten
182   - client_t *demowriter = NULL;
183   -
184   - lua_pushliteral(L, "onNewGameDemoStart");
  181 + // Spiel gestartet
  182 + lua_pushliteral(L, "onNewGameStarted");
185 183 lua_rawget(L, LUA_GLOBALSINDEX);
186   - if (lua_pcall(L, 0, 1, 0) != 0) {
187   - fprintf(stderr, "error calling onNewGameDemoStart: %s\n", lua_tostring(L, -1));
188   - } else {
189   - const char *demoname = lua_tostring(L, -1);
190   - if (demoname) {
191   - demowriter = server_start_demo_writer(demoname);
192   - if (demowriter) {
193   - fprintf(stderr, "started recording demo %s\n", demoname);
194   - } else {
195   - fprintf(stderr, "couldn't start demo file %s\n", demoname);
196   - }
197   - }
198   - }
199   - lua_pop(L, 1);
  184 + if (lua_pcall(L, 0, 0, 0) != 0) {
  185 + fprintf(stderr, "error calling onNewGameStarted: %s\n", lua_tostring(L, -1));
  186 + lua_pop(L, 1);
  187 + }
200 188
201 189 while (!game_exit && !should_end_round) {
202 190 int tick = get_tick();
@@ -240,10 +228,9 @@ void game_one_round() {
240 228 // IO Lesen/Schreiben
241 229 server_tick();
242 230 }
243   -
244   - if (demowriter)
245   - server_destroy(demowriter, "game ended");
246 231
  232 + server_game_end();
  233 +
247 234 creature_shutdown();
248 235 world_shutdown();
249 236 }
2  game.h
@@ -24,7 +24,7 @@
24 24 #include "server.h"
25 25
26 26 void game_init();
27   -void game_one_round();
  27 +void game_one_game();
28 28 void game_send_initial_update(client_t *client);
29 29
30 30 #endif
2  infon.c
@@ -96,7 +96,7 @@ int main(int argc, char *argv[]) {
96 96 if (!renderer_open(width, height, fullscreen))
97 97 die("cannot open renderer. sorry");
98 98
99   - client_init(host, NULL);
  99 + client_init(host);
100 100 client_game_init();
101 101
102 102 int lastticks = get_tick();
5 infond.c
@@ -61,6 +61,7 @@ int main(int argc, char *argv[]) {
61 61 fprintf(stderr, "no coredump possible. enable them to help debug crashes.\n");
62 62 #endif
63 63
  64 + signal(SIGTERM, sighandler);
64 65 signal(SIGINT, sighandler);
65 66 signal(SIGPIPE, SIG_IGN);
66 67
@@ -70,7 +71,7 @@ int main(int argc, char *argv[]) {
70 71
71 72 luaL_openlibs(L);
72 73 if (luaL_dofile(L, "infond.lua"))
73   - die("cannot read 'infond.lua'");
  74 + die("cannot read 'infond.lua': ", lua_tostring(L, -1));
74 75
75 76 game_init();
76 77 server_init();
@@ -81,7 +82,7 @@ int main(int argc, char *argv[]) {
81 82 #endif
82 83
83 84 while (!game_exit) {
84   - game_one_round();
  85 + game_one_game();
85 86 }
86 87
87 88 player_shutdown();
10 infond.lua
@@ -264,7 +264,7 @@ function on_client_close(fd, reason)
264 264 clients[fd] = nil
265 265 end
266 266
267   -function server_new_round()
  267 +function server_new_game()
268 268 server_tick = coroutine.wrap(ServerMain)
269 269 end
270 270
@@ -275,13 +275,11 @@ end
275 275 -- Game C Callbacks
276 276 -----------------------------------------------------------
277 277
278   -function onNewGameDemoStart()
  278 +function onNewGameStarted()
279 279 if type(demo) == "string" then
280   - return string.format("%s-%08X.demo", demo, os.time());
  280 + server_start_demo(string.format("%s-%08X.demo", demo, os.time()));
281 281 elseif type(demo) == "function" then
282   - return demo()
283   - else
284   - return nil
  282 + server_start_demo(demo())
285 283 end
286 284 end
287 285
21 listener.c
@@ -18,6 +18,7 @@
18 18
19 19 */
20 20
  21 +#include <netinet/tcp.h>
21 22 #include <arpa/inet.h>
22 23 #include <netinet/in.h>
23 24 #include <sys/types.h>
@@ -60,7 +61,25 @@ static void listener_cb(int fd, short event, void *arg) {
60 61 goto error;
61 62 }
62 63
63   - if (!server_accept(clientfd, &peer))
  64 + /* TCP_NODELAY setzen. Dadurch werden Daten fruehestmoeglich versendet */
  65 + static const int one = 1;
  66 + if (setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
  67 + fprintf(stderr, "cannot enable TCP_NODELAY: %s\n", strerror(errno));
  68 + goto error;
  69 + }
  70 +
  71 + /* SO_LINGER setzen. Falls sich noch Daten in der Sendqueue der Verbindung
  72 + befinden, werden diese verworfen. */
  73 + static const struct linger l = { 1, 0 };
  74 + if (setsockopt(clientfd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) {
  75 + fprintf(stderr, "cannot set SO_LINGER: %s\n", strerror(errno));
  76 + goto error;
  77 + }
  78 +
  79 + static char address[128];
  80 + sprintf(address, "ip:%s:%d", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
  81 +
  82 + if (!server_accept(clientfd, address))
64 83 goto error;
65 84
66 85 event_add(cb_event, NULL);
26 lua-5.1.1/src/lvm.c
@@ -56,6 +56,28 @@ int luaV_tostring (lua_State *L, StkId obj) {
56 56 }
57 57 }
58 58
  59 +static StkId traceexec (lua_State *L, const Instruction *pc) {
  60 + lu_byte mask = L->hookmask;
  61 + const Instruction *oldpc = GETPC(L);
  62 + SAVEPC(L, pc);
  63 + if (mask > LUA_MASKLINE) { /* instruction-hook set? */
  64 + if (L->hookcount == 0) {
  65 + resethookcount(L);
  66 + luaD_callhook(L, LUA_HOOKCOUNT, -1);
  67 + }
  68 + }
  69 + if (mask & LUA_MASKLINE) {
  70 + Proto *p = ci_func(L->ci)->l.p;
  71 + int npc = pcRel(pc, p);
  72 + int newline = getline(p, npc);
  73 + /* call linehook when enter a new function, when jump back (loop),
  74 + or when enter a new line */
  75 + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
  76 + luaD_callhook(L, LUA_HOOKLINE, newline);
  77 + }
  78 + return L->base;
  79 +}
  80 +
59 81 static void callTMres (lua_State *L, StkId res, const TValue *f,
60 82 const TValue *p1, const TValue *p2) {
61 83 ptrdiff_t result = savestack(L, res);
@@ -384,6 +406,10 @@ int luaV_execute (lua_State *L) {
384 406 SAVEPC(L, pc);
385 407 cpu_limit_exceeded(L); // never returns
386 408 }
  409 + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
  410 + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
  411 + base = traceexec(L, pc);
  412 +
387 413 /* warning!! several calls may realloc the stack and invalidate `ra' */
388 414 ra = RA(i);
389 415 lua_assert(base == L->base && L->base == L->ci->base);
11 player.c
@@ -679,8 +679,13 @@ player_t *player_create(const char *pass) {
679 679 lua_set_cycles(player->L, player->max_cycles);
680 680 player_init_events(player);
681 681
682   - if (luaL_dofile(player->L, "player.lua"))
683   - die("cannot read 'player.lua'");
  682 + // player.lua sourcen
  683 + if (luaL_dofile(player->L, "player.lua")) {
  684 + fprintf(stderr, "cannot source 'player.lua': %s\n", lua_tostring(player->L, -1));
  685 + lua_close(player->L);
  686 + player->L = NULL;
  687 + return NULL;
  688 + }
684 689
685 690 player_to_network(player, PLAYER_DIRTY_ALL, SEND_BROADCAST);
686 691
@@ -1160,7 +1165,7 @@ void player_init() {
1160 1165 lua_setglobal(L, "CREATURE_FLYER");
1161 1166 }
1162 1167
1163   -void player_round_start() {
  1168 +void player_game_start() {
1164 1169 int playerno;
1165 1170 for (playerno = 0; playerno < MAXPLAYERS; playerno++) {
1166 1171 if (PLAYER_USED(&players[playerno]))
2  player.h
@@ -97,7 +97,7 @@ void player_send_initial_update(client_t *client);
97 97 void player_to_network(player_t *player, int dirtymask, client_t *client);
98 98
99 99 void player_init();
100   -void player_round_start();
  100 +void player_game_start();
101 101 void player_shutdown();
102 102
103 103 #endif
40 player.lua
@@ -33,7 +33,6 @@ dofile = nil -- would allow file loading
33 33 loadfile = nil -- no file loading
34 34 _VERSION = nil -- who cares
35 35 newproxy = nil -- huh?
36   -debug = nil -- no debugging function
37 36 gcinfo = nil -- no access to the garbage collector
38 37 os = nil -- no os access
39 38 package = nil -- package support is not needed
@@ -45,6 +44,7 @@ module = nil -- module support not needed
45 44 do
46 45 local orig_loadstring = loadstring
47 46 local check_code_size = string.len
  47 + local error = error
48 48 loadstring = function(code, name)
49 49 if check_code_size(code) > 16384 then
50 50 error("code too large")
@@ -54,6 +54,31 @@ do
54 54 end
55 55 end
56 56
  57 +-- provide thread tracing function
  58 +do
  59 + local sethook = debug.sethook
  60 + local getinfo = debug.getinfo
  61 + local type, error, print = type, error, print
  62 + thread_trace = function(thread, text)
  63 + if type(thread) ~= "thread" then
  64 + error("arg #1 is not a thread")
  65 + end
  66 + local dumper = function(what, where)
  67 + local info = getinfo(2, "nlS")
  68 + print(text .. ":" .. info.source .. ":" .. info.currentline)
  69 + end
  70 + sethook(thread, dumper, "l")
  71 + end
  72 + thread_untrace = function(thread)
  73 + if type(thread) ~= "thread" then
  74 + error("arg #1 is not a thread")
  75 + end
  76 + sethook(thread)
  77 + end
  78 +end
  79 +
  80 +debug = nil -- no debugging functions
  81 +
57 82 collectgarbage()
58 83 collectgarbage = nil -- no access to the garbage collector
59 84
@@ -367,11 +392,7 @@ function player_think(events)
367 392 local parent = other ~= -1 and other or nil
368 393 local creature = {}
369 394 setmetatable(creature, {
370   - __index = function(self, what)
371   - if Creature[what] then
372   - return Creature[what]
373   - end
374   - end,
  395 + __index = Creature,
375 396 __tostring = function(self)
376 397 local x, y = get_pos(self.id)
377 398 local states = { [0]="idle", [1]="walk", [2]="heal", [3]="eat",
@@ -442,6 +463,11 @@ function player_think(events)
442 463 creature.message = 'main() terminated (maybe it was killed for using too much cpu/memory?)'
443 464 end
444 465 else
  466 + if creature.debug then
  467 + thread_trace(creature.thread, creature.id)
  468 + else
  469 + thread_untrace(creature.thread)
  470 + end
445 471 local ok, msg = coroutine.resume(creature.thread, creature)
446 472 if not ok then
447 473 creature.message = msg
@@ -457,7 +483,7 @@ function player_think(events)
457 483
458 484 can_yield = false
459 485
460   - -- Nach jeder Runde eventuell vorhandene Funktion onRoundStart aufrufen
  486 + -- Nach jeder Runde eventuell vorhandene Funktion onRoundEnd aufrufen
461 487 if onRoundEnd then
462 488 local ok, msg = pcall(onRoundEnd)
463 489 if not ok then
76 save-demo.rb
... ... @@ -1,76 +0,0 @@
1   -require 'socket'
2   -require 'zlib'
3   -
4   -raise "#$0 <server> <demofile>" unless ARGV.size == 2
5   -
6   -TCPSocket.open(ARGV[0], 1234) { |socket|
7   -
8   - class << socket
9   - alias_method :orig_read, :read
10   - attr_accessor :traffic
11   - attr_accessor :compress
12   - attr_accessor :zstream
13   - attr_accessor :buf
14   - attr_accessor :dump
15   -
16   - def read(x)
17   - if @compress
18   - while @buf.size < x
19   - @buf << @zstream.inflate(orig_read(1))
20   - @traffic += 1
21   - end
22   - ret = @buf[0...x]
23   - @buf = @buf[x..-1]
24   - else
25   - ret = orig_read(x)
26   - @traffic += x
27   - end
28   - @dump.write(ret) if @dump
29   - ret
30   - end
31   -
32   - def read8
33   - read(1)[0]
34   - end
35   -
36   - def read16
37   - ret = read8
38   - ret = ret & 0x7F | read8 << 7 if ret & 0x80 != 0
39   - ret
40   - end
41   -
42   - def read32
43   - read(4).unpack("N")[0]
44   - end
45   -
46   - def readXX(len)
47   - read(len).unpack("A*")[0]
48   - end
49   - end
50   -
51   - socket.traffic = 0
52   - socket.buf = ""
53   - socket.compress = false
54   - socket.zstream = Zlib::Inflate.new
55   - socket.dump = File.new(ARGV[1], "wb+")
56   -
57   - loop do
58   - len = socket.read8
59   - case type = socket.read8
60   - when 4:
61   - break
62   - when 32:
63   - socket.write("guiclient\n")
64   - puts "welcome: %s" % socket.read(len).delete("\n").strip
65   - when 254:
66   - puts "compression start"
67   - socket.compress = true
68   - else
69   - socket.readXX(len)
70   - end
71   - print "."
72   - STDOUT.flush
73   - end
74   -
75   - socket.dump.close
76   -}
91 server.c
@@ -60,11 +60,7 @@ int client_num(client_t *client) {
60 60 return client - clients;
61 61 }
62 62
63   -client_t *server_accept(int fd, struct sockaddr_in *peer) {
64   - static struct linger l = { 1, 0 };
65   - static const int one = 1;
66   - static char address[128];
67   -
  63 +client_t *server_accept(int fd, const char *address) {
68 64 if (fd >= MAXCLIENTS) {
69 65 fprintf(stderr, "cannot accept() new incoming connection: file descriptor too large\n");
70 66 return NULL;
@@ -73,21 +69,16 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
73 69 memset(&clients[fd], 0, sizeof(client_t));
74 70 client_t *client = &clients[fd];
75 71
76   - if (peer) {
77   - sprintf(address, "ip:%s:%d", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port));
78   - } else if (fd == STDIN_FILENO) {
79   - sprintf(address, "special:console");
80   - } else {
81   - sprintf(address, "special:demodumper");
82   - client->is_demo_dumper = 1;
83   - }
  72 + // Demo Dumper wird leicht unterschiedlich behandelt
  73 + client->is_demo_dumper = strstr(address, "special:demodumper") == address;
84 74
85   - /* Non Blocking setzen */
  75 + // Non Blocking setzen */
86 76 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
87 77 fprintf(stderr, "cannot set accept()ed socket nonblocking: %s\n", strerror(errno));
88 78 return NULL;
89 79 }
90 80
  81 + // Soll Verbindung angenommen werden?
91 82 lua_pushliteral(L, "on_new_client");/* funcname */
92 83 lua_rawget(L, LUA_GLOBALSINDEX); /* func */
93 84 lua_pushstring(L, address); /* addr */
@@ -107,22 +98,7 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
107 98
108 99 lua_pop(L, 2);
109 100
110   - if (peer) {
111   - /* TCP_NODELAY setzen. Dadurch werden Daten fruehestmoeglich versendet */
112   - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
113   - fprintf(stderr, "cannot enable TCP_NODELAY: %s\n", strerror(errno));
114   - return NULL;
115   - }
116   -
117   - /* SO_LINGER setzen. Falls sich noch Daten in der Sendqueue der Verbindung
118   - befinden, werden diese verworfen. */
119   - if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) {
120   - fprintf(stderr, "cannot set SO_LINGER: %s\n", strerror(errno));
121   - return NULL;
122   - }
123   - }
124   -
125   - // Aktivieren
  101 + // Libevent aktivieren
126 102 event_set(&client->rd_event, fd, EV_READ, server_readable, &client->rd_event);
127 103 event_set(&client->wr_event, fd, EV_WRITE, server_writable, &client->wr_event);
128 104
@@ -141,6 +117,7 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
141 117 client->next_gui = NULL;
142 118 client->prev_gui = NULL;
143 119
  120 + // Annehmen
144 121 lua_pushliteral(L, "on_client_accepted");
145 122 lua_rawget(L, LUA_GLOBALSINDEX);
146 123 lua_pushnumber(L, fd);
@@ -238,9 +215,15 @@ static void server_writable(int fd, short event, void *arg) {
238 215 }
239 216
240 217 void server_start_compression(client_t *client) {
  218 + // Kompression bereits aktiviert?
241 219 if (client->compress)
242 220 return;
243 221
  222 + // Demos sind immer unkomprimiert. Eine Kompression ueber
  223 + // die erstellte Datei macht wesentlich mehr Sinn.
  224 + if (client->is_demo_dumper)
  225 + return;
  226 +
244 227 client->strm.zalloc = Z_NULL;
245 228 client->strm.zfree = Z_NULL;
246 229 client->strm.opaque = NULL;
@@ -278,7 +261,6 @@ void server_writeto(client_t *client, const void *data, size_t size) {
278 261 }
279 262 evbuffer_add(client->out_buf, buf, sizeof(buf) - client->strm.avail_out);
280 263 }
281   - // printf("%d => %d\n", client->strm.total_in, client->strm.total_out);
282 264 } else {
283 265 evbuffer_add(client->out_buf, (void*)data, size);
284 266 }
@@ -392,6 +374,18 @@ static void client_turn_into_gui_client(client_t *client) {
392 374 initial_update(client);
393 375 }
394 376
  377 +client_t *server_start_demo_writer(const char *demoname, int one_game) {
  378 + int server_demo_fd = open(demoname, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, S_IRUSR|S_IWUSR);
  379 + if (server_demo_fd < 0)
  380 + return NULL;
  381 + static char address[512];
  382 + snprintf(address, sizeof(address), "special:demodumper:%s", demoname);
  383 + client_t *demowriter = server_accept(server_demo_fd, address);
  384 + client_turn_into_gui_client(demowriter);
  385 + demowriter->kick_at_end_of_game = one_game;
  386 + return demowriter;
  387 +}
  388 +
395 389 client_t *client_get_checked_lua(lua_State *L, int idx) {
396 390 int clientno = luaL_checklong(L, idx);
397 391 if (clientno < 0 || clientno >= MAXCLIENTS)
@@ -402,6 +396,15 @@ client_t *client_get_checked_lua(lua_State *L, int idx) {
402 396 return client;
403 397 }
404 398
  399 +static int luaStartDemoWriter(lua_State *L) {
  400 + const char *demofile = luaL_checkstring(L, 1);
  401 + int one_game = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : 1;
  402 + client_t *demowriter = server_start_demo_writer(demofile, one_game);
  403 + if (!demowriter) luaL_error(L, "cannot start demo %s", demofile);
  404 + lua_pushnumber(L, client_num(demowriter));
  405 + return 1;
  406 +}
  407 +
405 408 static int luaClientWrite(lua_State *L) {
406 409 size_t msglen; const char *msg = luaL_checklstring(L, 2, &msglen);
407 410 client_t *client = client_get_checked_lua(L, 1);
@@ -540,31 +543,31 @@ void server_init() {
540 543 lua_register(L, "client_disconnect", luaClientDisconnect);
541 544 lua_register(L, "client_print", luaClientPrint);
542 545 lua_register(L, "cprint", luaClientPrint);
  546 + lua_register(L, "server_start_demo", luaStartDemoWriter);
543 547
544 548 // XXX: HACK: stdin client starten
545 549 #ifdef CONSOLE_CLIENT
546   - server_accept(STDIN_FILENO, NULL);
  550 + server_accept(STDIN_FILENO, "special:console");
547 551 #endif
548 552 }
549 553
550   -client_t *server_start_demo_writer(const char *demoname) {
551   - int server_demo_fd = open(demoname, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, S_IRUSR|S_IWUSR);
552   - if (server_demo_fd < 0)
553   - return NULL;
554   - client_t *demowriter = server_accept(server_demo_fd, NULL);
555   - client_turn_into_gui_client(demowriter);
556   - return demowriter;
557   -}
558   -
559   -void server_round_start() {
560   - lua_pushliteral(L, "server_new_round");
  554 +void server_game_start() {
  555 + lua_pushliteral(L, "server_new_game");
561 556 lua_rawget(L, LUA_GLOBALSINDEX);
562 557 if (lua_pcall(L, 0, 0, 0) != 0) {
563   - fprintf(stderr, "error calling server_new_round: %s\n", lua_tostring(L, -1));
  558 + fprintf(stderr, "error calling server_new_game: %s\n", lua_tostring(L, -1));
564 559 lua_pop(L, 1);
565 560 }
566 561 }
567 562
  563 +void server_game_end() {
  564 + int clientno;
  565 + for (clientno = 0; clientno < MAXCLIENTS; clientno++) {
  566 + if (CLIENT_USED(&clients[clientno]) && clients[clientno].kick_at_end_of_game)
  567 + server_destroy(&clients[clientno], "game ended");
  568 + }
  569 +}
  570 +
568 571 void server_shutdown() {
569 572 int clientno;
570 573 for (clientno = 0; clientno < MAXCLIENTS; clientno++) {
8 server.h
@@ -51,6 +51,7 @@ typedef struct client_s {
51 51 z_stream strm;
52 52
53 53 char *kill_me;
  54 + int kick_at_end_of_game;
54 55
55 56 // Verbindung von: 1-player <-> N-client
56 57 struct player_s *player;
@@ -63,7 +64,7 @@ typedef struct client_s {
63 64 struct client_s *prev_gui;
64 65 } client_t;
65 66
66   -client_t *server_accept(int fd, struct sockaddr_in *peer);
  67 +client_t *server_accept(int fd, const char *address);
67 68 void server_writeto(client_t *client, const void *data, size_t size);
68 69 void server_writeto_all_gui_clients(const void *data, size_t size);
69 70 void server_destroy(client_t *client, const char *reason);
@@ -72,12 +73,13 @@ client_t *client_get_checked_lua(lua_State *L, int idx);
72 73
73 74 void server_send_packet(packet_t *packet, client_t *client);
74 75
75   -client_t *server_start_demo_writer(const char *demoname);
  76 +client_t *server_start_demo_writer(const char *demoname, int one_game);
76 77
77 78 void server_tick();
78 79
79 80 void server_init();
80   -void server_round_start();
  81 +void server_game_start();
  82 +void server_game_end();
81 83 void server_shutdown();
82 84
83 85 #endif

0 comments on commit b4f20aa

Please sign in to comment.
Something went wrong with that request. Please try again.