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

# User Rev Content
1 elmex 1.1 /*
2 root 1.55 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.39 *
4 root 1.49 * 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 root 1.55 * 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 root 1.49 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.39 */
23 elmex 1.1
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 root 1.26 * maintanance (checking for lost connections and if data has arrived.)
32 elmex 1.1 */
33    
34     #include <global.h>
35 root 1.10 #include <sproto.h>
36     #include <sockproto.h>
37 elmex 1.1
38 pippijn 1.8 #include <sys/types.h>
39     #include <sys/time.h>
40     #include <sys/socket.h>
41     #include <netinet/in.h>
42     #include <netdb.h>
43 elmex 1.1
44 root 1.16 #include <unistd.h>
45     #include <arpa/inet.h>
46 elmex 1.1
47     #include <loader.h>
48    
49 root 1.51 #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 elmex 1.1
54 root 1.21 void
55     client::reset_state ()
56     {
57     if (!pl)
58     return;
59    
60     pl->run_on = 0;
61     pl->fire_on = 0;
62     }
63 elmex 1.1
64 root 1.20 void
65     client::queue_command (packet_type *handler, char *data, int datalen)
66 root 1.6 {
67 root 1.51 tstamp stamp = NOW;
68 elmex 1.1
69 root 1.20 if (cmd_queue.size () >= MAX_QUEUE_DEPTH)
70 root 1.21 {
71     //TODO: just disconnect here?
72     reset_state ();
73     send_packet_printf ("drawinfo %d command queue overflow, ignoring.", NDI_RED);
74     }
75 root 1.20 else
76 root 1.24 {
77     cmd_queue.push_back (command ());
78     command &cmd = cmd_queue.back ();
79     cmd.stamp = stamp;
80     cmd.handler = handler;
81 root 1.25 cmd.data = salloc<char> (datalen + 1, data);
82 root 1.24 cmd.datalen = datalen;
83     }
84 root 1.20 }
85 elmex 1.1
86 root 1.20 bool
87     client::handle_command ()
88 elmex 1.1 {
89 root 1.48 if (!cmd_queue.empty ()
90     && state == ST_PLAYING
91     && pl->ob->speed_left > 0.f)
92 root 1.26 {
93     command &cmd = cmd_queue.front ();
94 root 1.6
95 root 1.51 if (cmd.stamp + MAX_QUEUE_BACKLOG < NOW)
96 root 1.26 {
97 root 1.48 reset_state ();
98     send_packet_printf ("drawinfo %d ignoring delayed commands.", NDI_RED);
99 root 1.26 }
100     else
101 root 1.48 execute (cmd.handler, cmd.data, cmd.datalen);
102    
103     cmd_queue.pop_front ();
104     return true;
105 root 1.21 }
106 root 1.48 else
107     return false;
108 elmex 1.1 }
109    
110 root 1.6 void
111     flush_sockets (void)
112 elmex 1.1 {
113 root 1.19 for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
114 root 1.31 (*i)->flush ();
115 elmex 1.1 }
116    
117     /**
118 root 1.10 * This checks the sockets for input, does the right thing.
119 elmex 1.1 *
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 root 1.6 void
125     doeric_server (void)
126 elmex 1.1 {
127 root 1.33 //TODO: should not be done here, either
128 pippijn 1.40 for (unsigned i = 0; i < clients.size (); ++i)
129 root 1.6 {
130 root 1.42 client *ns = clients [i];
131 elmex 1.1
132 root 1.42 ns->tick ();
133     ns->refcnt_chk ();
134     }
135     }
136    
137     void
138     client::tick ()
139     {
140     if (!pl || destroyed ())
141     return;
142 root 1.37
143 root 1.42 /* 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 root 1.20
148 root 1.42 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 root 1.6
156 root 1.50 draw_client_map (pl);
157 root 1.20
158 root 1.42 if (update_look)
159 root 1.50 esrv_draw_look (pl);
160 root 1.41
161 root 1.54 if (ixface.empty ())
162 root 1.42 {
163 root 1.44 // regularly send a new face when queue is empty
164 root 1.43 if (bg_scrub && !--bg_scrub && enable_bg_scrub)
165 root 1.42 while (scrub_idx < faces.size () - 1)
166     {
167     ++scrub_idx;
168 root 1.54
169 root 1.42 if (!faces_sent [scrub_idx])
170     {
171     send_face (scrub_idx);
172 root 1.45 flush_fx ();
173    
174 root 1.42 bg_scrub = 1; // send up to one face per tick, unless an image was requested
175     break;
176     }
177     }
178 root 1.44
179     rate_avail = max_rate - outputbuffer_len ();
180 root 1.42 }
181     else
182 root 1.44 {
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 root 1.46
190 root 1.53 // if we can split images, transfer up to mss-sized packets if possible
191 root 1.52 // but never 768 bytes more.
192 root 1.46 if (fxix) avail += min (768, mss - (ol % mss));
193 root 1.44
194 root 1.46 bg_scrub = BG_SCRUB_RATE;
195    
196     while (avail > 0)
197 root 1.44 {
198 root 1.54 ixsend &ix = ixface.back ();
199    
200     if (facedata *d = face_data (ix.idx, faceset))
201 root 1.46 {
202 root 1.54 if (fxix)
203 root 1.46 {
204 root 1.53 // 9 bytes is enough for fx_FFFOOO, 40 leaves some room for image data
205 root 1.54 int chunk = min (min (avail - 40, MAXSOCKBUF - 9), ix.ofs);
206 root 1.46
207     if (chunk <= 0)
208     break;
209    
210 root 1.54 ix.ofs -= chunk;
211 root 1.46
212     packet sl ("ix");
213    
214 root 1.54 sl << ber32 (ix.idx)
215     << ber32 (ix.ofs)
216     << data (d->data.data () + ix.ofs, chunk);
217 root 1.46
218     send_packet (sl);
219     }
220     else
221     {
222 root 1.54 send_image (ix.idx);
223     ix.ofs = 0;
224 root 1.46 }
225 root 1.45 }
226     else
227 root 1.54 ix.ofs = 0;
228 root 1.44
229     int consumed = ol - outputbuffer_len ();
230 root 1.54
231 root 1.44 avail -= consumed;
232     rate_avail -= consumed;
233 root 1.54
234     ol = outputbuffer_len ();
235    
236     if (!ix.ofs)
237     {
238     ixface.pop_back ();
239     if (ixface.empty ())
240     break;
241     }
242 root 1.44 }
243     }
244 elmex 1.1 }
245 root 1.43