ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/loop.C
Revision: 1.55
Committed: Sun Jul 1 05:00:20 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.54: +13 -14 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002-2003,2007 Mark Wedel & The Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 /**
25 * \file
26 * Main client/server loops.
27 *
28 * \date 2003-12-02
29 *
30 * loop.c mainly deals with initialization and higher level socket
31 * maintanance (checking for lost connections and if data has arrived.)
32 */
33
34 #include <global.h>
35 #include <sproto.h>
36 #include <sockproto.h>
37
38 #include <sys/types.h>
39 #include <sys/time.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <netdb.h>
43
44 #include <unistd.h>
45 #include <arpa/inet.h>
46
47 #include <loader.h>
48
49 #define BG_SCRUB_RATE 4 // how often to send a face in the background
50
51 #define MAX_QUEUE_DEPTH 500
52 #define MAX_QUEUE_BACKLOG 3.
53
54 void
55 client::reset_state ()
56 {
57 if (!pl)
58 return;
59
60 pl->run_on = 0;
61 pl->fire_on = 0;
62 }
63
64 void
65 client::queue_command (packet_type *handler, char *data, int datalen)
66 {
67 tstamp stamp = NOW;
68
69 if (cmd_queue.size () >= MAX_QUEUE_DEPTH)
70 {
71 //TODO: just disconnect here?
72 reset_state ();
73 send_packet_printf ("drawinfo %d command queue overflow, ignoring.", NDI_RED);
74 }
75 else
76 {
77 cmd_queue.push_back (command ());
78 command &cmd = cmd_queue.back ();
79 cmd.stamp = stamp;
80 cmd.handler = handler;
81 cmd.data = salloc<char> (datalen + 1, data);
82 cmd.datalen = datalen;
83 }
84 }
85
86 bool
87 client::handle_command ()
88 {
89 if (!cmd_queue.empty ()
90 && state == ST_PLAYING
91 && pl->ob->speed_left > 0.f)
92 {
93 command &cmd = cmd_queue.front ();
94
95 if (cmd.stamp + MAX_QUEUE_BACKLOG < NOW)
96 {
97 reset_state ();
98 send_packet_printf ("drawinfo %d ignoring delayed commands.", NDI_RED);
99 }
100 else
101 execute (cmd.handler, cmd.data, cmd.datalen);
102
103 cmd_queue.pop_front ();
104 return true;
105 }
106 else
107 return false;
108 }
109
110 void
111 flush_sockets (void)
112 {
113 for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
114 (*i)->flush ();
115 }
116
117 /**
118 * This checks the sockets for input, does the right thing.
119 *
120 * A bit of this code is grabbed out of socket.c
121 * There are 2 lists we need to look through - init_sockets is a list
122 *
123 */
124 void
125 doeric_server (void)
126 {
127 //TODO: should not be done here, either
128 for (unsigned i = 0; i < clients.size (); ++i)
129 {
130 client *ns = clients [i];
131
132 ns->tick ();
133 ns->refcnt_chk ();
134 }
135 }
136
137 void
138 client::tick ()
139 {
140 if (!pl || destroyed ())
141 return;
142
143 /* Update the players stats once per tick. More efficient than
144 * sending them whenever they change, and probably just as useful
145 */
146 esrv_update_stats (pl);
147
148 if (last_weight != -1 && last_weight != WEIGHT (pl->ob))
149 {
150 esrv_update_item (UPD_WEIGHT, pl->ob, pl->ob);
151 if (last_weight != WEIGHT (pl->ob))
152 LOG (llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n",
153 (unsigned long) last_weight, WEIGHT (pl->ob));
154 }
155
156 draw_client_map (pl);
157
158 if (update_look)
159 esrv_draw_look (pl);
160
161 if (ixface.empty ())
162 {
163 // regularly send a new face when queue is empty
164 if (bg_scrub && !--bg_scrub && enable_bg_scrub)
165 while (scrub_idx < faces.size () - 1)
166 {
167 ++scrub_idx;
168
169 if (!faces_sent [scrub_idx])
170 {
171 send_face (scrub_idx);
172 flush_fx ();
173
174 bg_scrub = 1; // send up to one face per tick, unless an image was requested
175 break;
176 }
177 }
178
179 rate_avail = max_rate - outputbuffer_len ();
180 }
181 else
182 {
183 int ol = outputbuffer_len ();
184
185 rate_avail = min (max_rate, rate_avail + max_rate);
186 rate_avail -= ol;
187
188 int avail = rate_avail;
189
190 // if we can split images, transfer up to mss-sized packets if possible
191 // but never 768 bytes more.
192 if (fxix) avail += min (768, mss - (ol % mss));
193
194 bg_scrub = BG_SCRUB_RATE;
195
196 while (avail > 0)
197 {
198 ixsend &ix = ixface.back ();
199
200 if (facedata *d = face_data (ix.idx, faceset))
201 {
202 if (fxix)
203 {
204 // 9 bytes is enough for fx_FFFOOO, 40 leaves some room for image data
205 int chunk = min (min (avail - 40, MAXSOCKBUF - 9), ix.ofs);
206
207 if (chunk <= 0)
208 break;
209
210 ix.ofs -= chunk;
211
212 packet sl ("ix");
213
214 sl << ber32 (ix.idx)
215 << ber32 (ix.ofs)
216 << data (d->data.data () + ix.ofs, chunk);
217
218 send_packet (sl);
219 }
220 else
221 {
222 send_image (ix.idx);
223 ix.ofs = 0;
224 }
225 }
226 else
227 ix.ofs = 0;
228
229 int consumed = ol - outputbuffer_len ();
230
231 avail -= consumed;
232 rate_avail -= consumed;
233
234 ol = outputbuffer_len ();
235
236 if (!ix.ofs)
237 {
238 ixface.pop_back ();
239 if (ixface.empty ())
240 break;
241 }
242 }
243 }
244 }
245