1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // sv_send.c
21 
22 #include "server.h"
23 #include "mvd.h"
24 
25 static int		demo_msglen;
26 static byte		demo_data[MAX_PACKETLEN];
27 
28 /*
29 =============================================================================
30 
31 MISC
32 
33 =============================================================================
34 */
35 
36 char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
37 
SV_FlushRedirect(int sv_redirected,char * outputbuf)38 void SV_FlushRedirect( int sv_redirected, char *outputbuf ) {
39 	if( sv_redirected == RD_PACKET ) {
40 		Netchan_OutOfBandPrint( NS_SERVER, &net_from, "print\n%s", outputbuf );
41 	} else if( sv_redirected == RD_CLIENT ) {
42 		MSG_WriteByte( svc_print );
43 		MSG_WriteByte( PRINT_HIGH );
44 		MSG_WriteString( outputbuf );
45 		SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR );
46 	}
47 }
48 
49 /*
50 =======================
51 SV_RateDrop
52 
53 Returns qtrue if the client is over its current
54 bandwidth estimation and should not be sent another packet
55 =======================
56 */
SV_RateDrop(client_t * client)57 static qboolean SV_RateDrop( client_t *client ) {
58 	int		total;
59 	int		i;
60 
61 	// never drop over the loopback
62 	if( NET_IsLocalAddress( &client->netchan->remote_address ) ) {
63 		return qfalse;
64 	}
65 	if( sv_lan_force_rate->integer && NET_IsLANAddress(
66                 &client->netchan->remote_address ) )
67     {
68 		return qfalse;
69 	}
70 
71 	total = 0;
72 	for( i = 0; i < RATE_MESSAGES; i++ ) {
73 		total += client->message_size[i];
74 	}
75 
76 	if( total > client->rate ) {
77 		client->surpressCount++;
78 		client->message_size[sv.framenum % RATE_MESSAGES] = 0;
79 		return qtrue;
80 	}
81 
82 	return qfalse;
83 }
84 
SV_CalcSendTime(client_t * client,int messageSize)85 void SV_CalcSendTime( client_t *client, int messageSize ) {
86 	int delta;
87 
88 	if( messageSize == -1 ) {
89 		return;
90 	}
91 
92 	// never drop over the loopback
93 	if( NET_IsLocalAddress( &client->netchan->remote_address ) ) {
94 		client->sendTime = 0;
95 		return;
96 	}
97 
98 	if( sv_lan_force_rate->integer && NET_IsLANAddress(
99                 &client->netchan->remote_address ) )
100     {
101 		client->sendTime = 0;
102 		return;
103 	}
104 
105 	client->message_size[sv.framenum % RATE_MESSAGES] = messageSize;
106 
107 	delta = messageSize * 1000 / client->rate;
108 	client->sendTime = svs.realtime + delta;
109 }
110 
111 /*
112 =============================================================================
113 
114 EVENT MESSAGES
115 
116 =============================================================================
117 */
118 
119 
120 /*
121 =================
122 SV_ClientPrintf
123 
124 Sends text across to be displayed if the level passes.
125 NOT archived in MVD stream.
126 =================
127 */
SV_ClientPrintf(client_t * client,int level,const char * fmt,...)128 void SV_ClientPrintf( client_t *client, int level, const char *fmt, ... ) {
129 	va_list		argptr;
130 	char		string[MAX_STRING_CHARS];
131 
132 	if( level < client->messagelevel )
133 		return;
134 
135 	va_start( argptr, fmt );
136 	Q_vsnprintf( string, sizeof( string ), fmt, argptr );
137 	va_end( argptr );
138 
139 	MSG_WriteByte( svc_print );
140 	MSG_WriteByte( level );
141 	MSG_WriteString( string );
142 
143 	SV_ClientAddMessage( client, MSG_RELIABLE|MSG_CLEAR );
144 
145 }
146 
147 /*
148 =================
149 SV_BroadcastPrintf
150 
151 Sends text to all active clients, including MVD clients.
152 NOT archived in MVD stream.
153 =================
154 */
SV_BroadcastPrintf(int level,const char * fmt,...)155 void SV_BroadcastPrintf( int level, const char *fmt, ... ) {
156 	va_list		argptr;
157 	char		string[MAX_STRING_CHARS];
158 	client_t	*client;
159 	int			i;
160 
161 	va_start( argptr, fmt );
162 	Q_vsnprintf( string, sizeof( string ), fmt, argptr );
163 	va_end( argptr );
164 
165 	MSG_WriteByte( svc_print );
166 	MSG_WriteByte( level );
167 	MSG_WriteString( string );
168 
169 	// echo to console
170 	if( dedicated->integer ) {
171 		// mask off high bits
172 		for( i = 0; string[i]; i++ )
173 			string[i] &= 127;
174 		Com_Printf( "%s", string );
175 	}
176 
177     FOR_EACH_CLIENT( client ) {
178 		if( client->state != cs_spawned )
179 			continue;
180 		if( level < client->messagelevel )
181 			continue;
182 		SV_ClientAddMessage( client, MSG_RELIABLE );
183 	}
184 
185 	SZ_Clear( &msg_write );
186 }
187 
188 /*
189 =================
190 SV_BroadcastCommand
191 
192 Sends command to all active clients, including MVD clients.
193 NOT archived in MVD stream.
194 =================
195 */
SV_BroadcastCommand(const char * fmt,...)196 void SV_BroadcastCommand( const char *fmt, ... ) {
197 	va_list		argptr;
198 	char		string[MAX_STRING_CHARS];
199 	client_t	*client;
200 
201 	if( !sv.state )
202 		return;
203 	va_start( argptr, fmt );
204 	Q_vsnprintf( string, sizeof( string ), fmt, argptr );
205 	va_end( argptr );
206 
207 	MSG_WriteByte( svc_stufftext );
208 	MSG_WriteString( string );
209 
210     FOR_EACH_CLIENT( client ) {
211 		if( client->state < cs_connected )
212 			continue;
213 		SV_ClientAddMessage( client, MSG_RELIABLE );
214 	}
215 
216 	SZ_Clear( &msg_write );
217 }
218 
219 
220 /*
221 =================
222 SV_Multicast
223 
224 Sends the contents of the write buffer to a subset of the clients,
225 then clears the write buffer.
226 
227 Archived in MVD stream.
228 
229 MULTICAST_ALL	same as broadcast (origin can be NULL)
230 MULTICAST_PVS	send to clients potentially visible from org
231 MULTICAST_PHS	send to clients potentially hearable from org
232 =================
233 */
SV_Multicast(vec3_t origin,multicast_t to)234 void SV_Multicast( vec3_t origin, multicast_t to ) {
235 	client_t	*client;
236 	byte		*mask;
237 	cleaf_t		*leaf;
238 	int			cluster;
239 	int			area1, area2;
240 	int			flags;
241 	vec3_t		org;
242 	player_state_t	*ps;
243 
244 	flags = 0;
245 
246 	switch( to ) {
247 	case MULTICAST_ALL_R:
248 		flags |= MSG_RELIABLE;	// intentional fallthrough
249 	case MULTICAST_ALL:
250 		area1 = 0;
251 		cluster = 0;
252 		mask = NULL;
253 		break;
254 
255 	case MULTICAST_PHS_R:
256 		flags |= MSG_RELIABLE;	// intentional fallthrough
257 	case MULTICAST_PHS:
258 		leaf = CM_PointLeaf( &sv.cm, origin );
259 		area1 = CM_LeafArea( leaf );
260 		cluster = CM_LeafCluster( leaf );
261 		mask = CM_ClusterPHS( &sv.cm, cluster );
262 		break;
263 
264 	case MULTICAST_PVS_R:
265 		flags |= MSG_RELIABLE;	// intentional fallthrough
266 	case MULTICAST_PVS:
267 		leaf = CM_PointLeaf( &sv.cm, origin );
268 		area1 = CM_LeafArea( leaf );
269 		cluster = CM_LeafCluster( leaf );
270 		mask = CM_ClusterPVS( &sv.cm, cluster );
271 		break;
272 
273 	default:
274 		mask = NULL;
275 		area1 = 0;
276 		Com_Error( ERR_DROP, "SV_Multicast: bad to: %i", to );
277 	}
278 
279 	// send the data to all relevent clients
280     FOR_EACH_CLIENT( client ) {
281 		if( client->state < cs_connected ) {
282 			continue;
283 		}
284         if( client->protocol == PROTOCOL_VERSION_MVD ) {
285             client->AddMulticast( client, origin, to );
286             continue;
287         }
288 		if( !( flags & MSG_RELIABLE ) ) {
289 			/* do not send unreliables to connecting clients */
290 			if( client->state != cs_spawned || client->download ||
291                     client->nodata )
292             {
293 				continue;
294 			}
295 		}
296 
297 		if( mask ) {
298 			// find the client's PVS
299 			ps = &client->edict->client->ps;
300 			VectorMA( ps->viewoffset, 0.125f, ps->pmove.origin, org );
301 			leaf = CM_PointLeaf( &sv.cm, org );
302 			area2 = CM_LeafArea( leaf );
303 			if( !CM_AreasConnected( &sv.cm, area1, area2 ) )
304 				continue;
305 			cluster = CM_LeafCluster( leaf );
306 			if( !Q_IsBitSet( mask, cluster ) ) {
307 				continue;
308 			}
309 		}
310 
311 		SV_ClientAddMessage( client, flags );
312 
313 	}
314 
315 	// if doing a serverrecord, store everything
316 	MVD_RecMulticast( origin, to );
317 
318 	/* clear the buffer */
319 	SZ_Clear( &msg_write );
320 
321 }
322 
323 
324 /*
325 ==================
326 SV_StartSound
327 
328 Each entity can have eight independant sound sources, like voice,
329 weapon, feet, etc.
330 
331 If cahnnel & 8, the sound will be sent to everyone, not just
332 things in the PHS.
333 
334 FIXME: if entity isn't in PHS, they must be forced to be sent or
335 have the origin explicitly sent.
336 
337 Channel 0 is an auto-allocate channel, the others override anything
338 already running on that entity/channel pair.
339 
340 An attenuation of 0 will play full volume everywhere in the level.
341 Larger attenuations will drop off.  (max 4 attenuation)
342 
343 Timeofs can range from 0.0 to 0.1 to cause sounds to be started
344 later in the frame than they normally would.
345 
346 If origin is NULL, the origin is determined from the entity origin
347 or the midpoint of the entity box for bmodels.
348 ==================
349 */
SV_StartSound(vec3_t origin,edict_t * entity,int channel,int soundindex,float volume,float attenuation,float timeofs)350 void SV_StartSound( vec3_t origin, edict_t *entity, int channel,
351 					int soundindex, float volume,
352 					float attenuation, float timeofs )
353 {
354 	int			sendchan;
355     int			flags;
356 	int			ent;
357 	vec3_t		origin_v;
358     vec3_t      mid;
359 	qboolean	use_phs;
360 
361 	if( volume < 0 || volume > 1.0 )
362 		Com_Error( ERR_DROP, "SV_StartSound: volume = %f", volume );
363 
364 	if( attenuation < 0 || attenuation > 4 )
365 		Com_Error( ERR_DROP, "SV_StartSound: attenuation = %f", attenuation );
366 
367 	if( timeofs < 0 || timeofs > 0.255 )
368 		Com_Error( ERR_DROP, "SV_StartSound: timeofs = %f", timeofs );
369 
370 	ent = NUM_FOR_EDICT( entity );
371 
372 	if( channel & 8 ) {	// no PHS flag
373 		use_phs = qfalse;
374 		channel &= 7;
375 	} else {
376 		use_phs = qtrue;
377 	}
378 
379 	sendchan = ( ent << 3 ) | ( channel & 7 );
380 
381 	flags = 0;
382 	if( volume != DEFAULT_SOUND_PACKET_VOLUME )
383 		flags |= SND_VOLUME;
384 	if( attenuation != DEFAULT_SOUND_PACKET_ATTENUATION )
385 		flags |= SND_ATTENUATION;
386 
387 	// always send the entity number for channel overrides
388 	flags |= SND_ENT;
389 
390 	if( timeofs )
391 		flags |= SND_OFFSET;
392 
393 	// if the sound doesn't attenuate,send it to everyone
394 	// (global radio chatter, voiceovers, etc)
395 	if( attenuation == ATTN_NONE )
396 		use_phs = qfalse;
397 
398 	// the client doesn't know that bmodels have weird origins
399 	// the origin can also be explicitly set
400 	if( ent == 0 || ( entity->svflags & SVF_NOCLIENT ) ||
401             entity->solid == SOLID_BSP || origin )
402 		flags |= SND_POS;
403 
404 	// use the entity origin unless it is a bmodel or explicitly specified
405 	if( !origin ) {
406 		origin = origin_v;
407 		if( ent == 0 ) {
408 			VectorClear( origin_v );
409 		} else if( entity->solid == SOLID_BSP ) {
410             VectorAdd( entity->mins, entity->maxs, mid );
411             VectorMA( entity->s.origin, 0.5f, mid, origin_v );
412 		} else {
413 			VectorCopy( entity->s.origin, origin_v );
414 		}
415 	}
416 
417 	MSG_WriteByte( svc_sound );
418 	MSG_WriteByte( flags );
419 	MSG_WriteByte( soundindex );
420 
421 	if( flags & SND_VOLUME )
422 		MSG_WriteByte( volume * 255 );
423 	if( flags & SND_ATTENUATION )
424 		MSG_WriteByte( attenuation * 64 );
425 	if( flags & SND_OFFSET )
426 		MSG_WriteByte( timeofs * 1000 );
427 
428 	if( flags & SND_ENT )
429 		MSG_WriteShort( sendchan );
430 
431 	if( flags & SND_POS )
432 		MSG_WritePos( origin );
433 
434 	if( channel & CHAN_RELIABLE ) {
435 		if( use_phs )
436 			SV_Multicast( origin, MULTICAST_PHS_R );
437 		else
438 			SV_Multicast( origin, MULTICAST_ALL_R );
439 	} else {
440 		if( use_phs )
441 			SV_Multicast( origin, MULTICAST_PHS );
442 		else
443 			SV_Multicast( origin, MULTICAST_ALL );
444 	}
445 }
446 
447 /*
448 =======================
449 SV_ClientAddMessage
450 
451 Adds contents of the current write buffer to client's message list.
452 Does NOT clean the buffer for multicast delivery purpose,
453 unless told otherwise.
454 =======================
455 */
SV_ClientAddMessage(client_t * client,int flags)456 void SV_ClientAddMessage( client_t *client, int flags ) {
457 	if( !msg_write.cursize ) {
458 		return;
459 	}
460 
461 	client->AddMessage( client, msg_write.data, msg_write.cursize,
462 		( flags & MSG_RELIABLE ) ? qtrue : qfalse );
463 
464 	if( sv_debug_send->integer > 1 ) {
465 		if( flags & MSG_RELIABLE ) {
466 			Com_Printf( "AddRel( %s ): %i bytes\n",
467 				client->name, msg_write.cursize );
468 		} else {
469 			Com_Printf( "AddMsg( %s ): %i bytes\n",
470 				client->name, msg_write.cursize );
471 		}
472 	}
473 
474 	if( flags & MSG_CLEAR ) {
475 		SZ_Clear( &msg_write );
476 	}
477 }
478 
479 /*
480 ===============================================================================
481 
482 FRAME UPDATES - OLD CLIENTS
483 
484 ===============================================================================
485 */
486 
SV_OldClientAddMessage(client_t * client,byte * data,int length,qboolean reliable)487 void SV_OldClientAddMessage( client_t *client, byte *data,
488 							  int length, qboolean reliable )
489 {
490 	clientMessage_t	*msg;
491 
492 	if( length > client->netchan->maxpacketlen ) {
493 		if( reliable ) {
494 			SV_DropClient( client, "oversize reliable message" );
495 		} else {
496             Com_DPrintf( "Dumped oversize unreliable for %s\n", client->name );
497         }
498 		return;
499 	}
500 
501     msg = ( clientMessage_t * )client->freeMsgList.first;
502 	if( !msg ) {
503 		Com_WPrintf( "Out of message slots for %s!\n", client->name );
504 		if( reliable ) {
505             SV_OldClientClearMessages( client );
506 			SV_DropClient( client, "no slot for reliable message" );
507 		}
508 		return;
509 	}
510 
511 	if( length > MSGQUEUE_MALLOC_TRESHOLD ) {
512 		msg->data = SV_Malloc( length );
513 	} else {
514 		msg->data = msg->localBuffer;
515 	}
516 
517 	memcpy( msg->data, data, length );
518 	msg->cursize = length;
519 	msg->reliable = reliable;
520 
521 	List_DeleteElem( msg );
522 	List_Append( &client->usedMsgList, msg );
523 }
524 
SV_OldClientRemoveMessage(client_t * client,clientMessage_t * msg)525 static void SV_OldClientRemoveMessage( client_t *client, clientMessage_t *msg )
526 {
527 	if( msg->cursize > MSGQUEUE_MALLOC_TRESHOLD ) {
528 		Z_Free( msg->data );
529 	}
530 
531 	msg->data = NULL;
532 	msg->cursize = 0;
533 
534 	List_DeleteElem( msg );
535     List_Append( &client->freeMsgList, msg );
536 }
537 
SV_OldClientClearMessages(client_t * client)538 void SV_OldClientClearMessages( client_t *client ) {
539 	listElem_t	*elem, *next;
540 
541 	for( elem = client->usedMsgList.first; elem; elem = next ) {
542         next = elem->next;
543 		SV_OldClientRemoveMessage( client, ( clientMessage_t * )elem );
544 	}
545 
546 }
547 
548 
549 /*
550 =======================
551 SV_OldClient_SendReliableMessages
552 
553 This should be the only place data is
554 ever written to client->netchan.message
555 =======================
556 */
SV_OldClientWriteReliableMessages(client_t * client,int maxSize)557 void SV_OldClientWriteReliableMessages( client_t *client, int maxSize ) {
558 	listElem_t	*elem, *next;
559 	clientMessage_t *msg;
560 	int count;
561 
562 	if( client->netchan->reliable_length ) {
563 		if( sv_debug_send->integer > 1 ) {
564 			Com_Printf( "SndRel( %s ): unacked reliable\n", client->name );
565 		}
566 		return;	// there is still outgoing reliable message pending
567 	}
568 
569 	// find at least one reliable message to send
570 	count = 0;
571 	for( elem = client->usedMsgList.first; elem; elem = next ) {
572         next = elem->next;
573 		msg = ( clientMessage_t * )elem;
574 		if( !msg->reliable ) {
575 			continue;
576 		}
577 
578 		// stop if this msg doesn't fit (reliables must be delivered in order)
579 		if( client->netchan->message.cursize + msg->cursize > maxSize ) {
580 			if( !count ) {
581 				Com_WPrintf( "Overflow on the first reliable message "
582 					"for %s (should not happen).\n", client->name );
583 			}
584 			break;
585 		}
586 
587 		if( sv_debug_send->integer > 1 ) {
588 			Com_Printf( "SndRel( %s ): %i bytes\n", client->name,
589                     msg->cursize );
590 		}
591 
592 		SZ_Write( &client->netchan->message, msg->data, msg->cursize );
593 		SV_OldClientRemoveMessage( client, msg );
594 		count++;
595 	}
596 
597 }
598 
599 
600 /*
601 =======================
602 OldClient_SendDatagram
603 =======================
604 */
SV_OldClientWriteDatagram(client_t * client)605 void SV_OldClientWriteDatagram( client_t *client ) {
606 	listElem_t	*elem, *next;
607 	clientMessage_t *msg;
608 	int cursize, maxsize;
609 	sizebuf_t	compressed;
610 	byte		compressed_data[MAX_PACKETLEN_WRITABLE];
611 
612 	maxsize = client->netchan->maxpacketlen;
613 	if( client->netchan->reliable_length ) {
614 		// there is still unacked reliable message pending
615 		maxsize -= client->netchan->reliable_length;
616 	} else {
617 		// find at least one reliable message to send
618 		// and make sure to reserve space for it
619 		for( elem = client->usedMsgList.first; elem; elem = elem->next ) {
620 			msg = ( clientMessage_t * )elem;
621 			if( msg->reliable ) {
622 				maxsize -= msg->cursize;
623 				break;
624 			}
625 		}
626 	}
627 
628 	// send over all the relevant entity_state_t
629 	// and the player_state_t
630 	client->WriteFrame( client );
631 	if( msg_write.cursize > maxsize ) {
632 		if( sv_debug_send->integer ) {
633 			Com_Printf( S_COLOR_BLUE"Frame overflowed for %s, ", client->name );
634 		}
635 		if( client->protocol != PROTOCOL_VERSION_DEFAULT ) {
636 			SZ_Init( &compressed, compressed_data, sizeof( compressed_data ) );
637 
638 			if( sv_debug_send->integer ) {
639 				Com_Printf( "deflating data... " );
640 			}
641 
642 			// compress the frame
643 			if( Com_ZLibDeflateBuffer( &msg_write, &compressed ) ) {
644 				cursize = msg_write.cursize;
645 				SZ_Clear( &msg_write );
646 
647 				if( compressed.cursize <= maxsize ) {
648 					if( sv_debug_send->integer ) {
649 						Com_Printf( "succeeded: %i --> %i\n",
650                                 cursize, compressed.cursize );
651 					}
652 
653 					MSG_WriteByte( svc_zpacket );
654 					MSG_WriteShort( compressed.cursize );
655 					MSG_WriteShort( cursize );
656 					MSG_WriteData( compressed.data, compressed.cursize );
657 				} else {
658 					if( sv_debug_send->integer ) {
659 						Com_Printf( "failed: %i --> %i\n",
660                                 cursize, compressed.cursize );
661 					}
662 				}
663 			} else {
664 				if( sv_debug_send->integer ) {
665 					Com_Printf( "deflate failed\n" );
666 				}
667 				SZ_Clear( &msg_write );
668 			}
669 		} else {
670 			if( sv_debug_send->integer ) {
671 				Com_Printf( "clearing frame\n" );
672 			}
673 			SZ_Clear( &msg_write );
674 		}
675 	}
676 
677 	// now try to write unreliable messages
678 	// it is necessary for this to be after the WriteEntities
679 	// so that entity references will be current
680 	if( msg_write.cursize + 4 <= maxsize ) {
681 		// temp entities first
682 		for( elem = client->usedMsgList.first; elem; elem = next ) {
683             next = elem->next;
684 			msg = ( clientMessage_t * )elem;
685 			if( msg->reliable ) {
686 				continue;
687 			}
688 			if( msg->data[0] != svc_temp_entity ) {
689 				continue;
690 			}
691 			// ignore some low-priority effects, these checks come from r1q2
692 			if( msg->data[1] == TE_BLOOD || msg->data[1] == TE_SPLASH ) {
693 				continue;
694 			}
695 			if( msg->data[1] == TE_GUNSHOT || msg->data[1] == TE_BULLET_SPARKS
696                     || msg->data[1] == TE_SHOTGUN )
697             {
698 				continue;
699 			}
700 
701 			// if this msg fits, write it
702 			if( msg_write.cursize + msg->cursize <= maxsize ) {
703 				MSG_WriteData( msg->data, msg->cursize );
704 			}
705 
706 			SV_OldClientRemoveMessage( client, msg );
707 		}
708 
709 		if( msg_write.cursize + 4 <= maxsize ) {
710 			// then sounds
711             for( elem = client->usedMsgList.first; elem; elem = next ) {
712                 next = elem->next;
713 				msg = ( clientMessage_t * )elem;
714 				if( msg->reliable ) {
715 					continue;
716 				}
717 				if( msg->data[0] != svc_sound ) {
718 					continue;
719 				}
720 
721 				// if this msg fits, write it
722 				if( msg_write.cursize + msg->cursize <= maxsize ) {
723 					MSG_WriteData( msg->data, msg->cursize );
724 				}
725 
726 				SV_OldClientRemoveMessage( client, msg );
727 			}
728 
729 			if( msg_write.cursize + 4 <= maxsize ) {
730 				// then everything else left
731 				for( elem = client->usedMsgList.first; elem; elem = next ) {
732                     next = elem->next;
733 					msg = ( clientMessage_t * )elem;
734 					if( msg->reliable ) {
735 						continue;
736 					}
737 
738 					// if this msg fits, write it
739 					if( msg_write.cursize + msg->cursize <= maxsize ) {
740 						MSG_WriteData( msg->data, msg->cursize );
741 					}
742 
743 					SV_OldClientRemoveMessage( client, msg );
744 				}
745 			}
746 		}
747 	}
748 
749 	// clear all unreliable messages still left
750 	for( elem = client->usedMsgList.first; elem; elem = next ) {
751         next = elem->next;
752 		msg = ( clientMessage_t * )elem;
753 		if( !msg->reliable ) {
754 			SV_OldClientRemoveMessage( client, msg );
755 		}
756 
757 	}
758 
759 	SV_OldClientWriteReliableMessages( client, client->netchan->maxpacketlen -
760             msg_write.cursize );
761 
762 	// send the datagram
763 	cursize = client->netchan->Transmit( client->netchan, msg_write.cursize,
764             msg_write.data );
765 
766 	// record the size for rate estimation
767 	SV_CalcSendTime( client, cursize );
768 
769 	SZ_Clear( &msg_write );
770 
771 }
772 
SV_OldClientAddUnicast(client_t * client,int clientNum)773 void SV_OldClientAddUnicast( client_t *client, int clientNum ) {
774     qboolean reliable = ( clientNum >> 7 ) & 1;
775     byte data[MAX_PACKETLEN];
776     sizebuf_t buf;
777 
778     SZ_Init( &buf, data, sizeof( data ) );
779 
780     SZ_WriteByte( &buf, svc_unicast );
781     SZ_WriteByte( &buf, clientNum );
782     SZ_WriteShort( &buf, msg_write.cursize );
783     SZ_Write( &buf, msg_write.data, msg_write.cursize );
784 
785 	SV_OldClientAddMessage( client, buf.data, buf.cursize, reliable );
786 
787 }
788 
SV_OldClientAddMulticast(client_t * client,const vec3_t origin,multicast_t to)789 void SV_OldClientAddMulticast( client_t *client, const vec3_t origin,
790         multicast_t to )
791 {
792     qboolean reliable = to >= MULTICAST_ALL_R ? qtrue : qfalse;
793     byte data[MAX_PACKETLEN];
794     sizebuf_t buf;
795     int size;
796 
797     SZ_Init( &buf, data, sizeof( data ) );
798 
799 	size = ( to << 12 ) | ( msg_write.cursize & 0xFFF );
800 
801     SZ_WriteByte( &buf, svc_multicast );
802     SZ_WriteShort( &buf, size );
803 
804     /* write exact position for PVS/PHS checks */
805     if( to != MULTICAST_ALL && to != MULTICAST_ALL_R ) {
806         SZ_WriteExactPos( &buf, origin );
807     }
808 
809     SZ_Write( &buf, msg_write.data, msg_write.cursize );
810 
811 	SV_OldClientAddMessage( client, buf.data, buf.cursize, reliable );
812 }
813 
814 
815 /*
816 ===============================================================================
817 
818 FRAME UPDATES - Q2PRO CLIENTS
819 
820 ===============================================================================
821 */
822 
SV_NewClientAddMessage(client_t * client,byte * data,int length,qboolean reliable)823 void SV_NewClientAddMessage( client_t *client, byte *data,
824 							  int length, qboolean reliable )
825 {
826 	sizebuf_t *buf = reliable ? &client->netchan->message : &client->datagram;
827 	SZ_Write( buf, data, length );
828 }
829 
SV_NewClientWriteDatagram(client_t * client)830 void SV_NewClientWriteDatagram( client_t *client ) {
831 	int cursize;
832 	int i;
833 
834 	// send over all the relevant entity_state_t
835 	// and the player_state_t
836 	client->WriteFrame( client );
837 
838 	if( msg_write.overflowed ) {
839 		// should never happen
840 		Com_WPrintf( "Frame overflowed for %s\n", client->name );
841 		SZ_Clear( &msg_write );
842 	}
843 
844 	// copy the accumulated multicast datagram
845 	// for this client out to the message
846 	// it is necessary for this to be after the WriteEntities
847 	// so that entity references will be current
848 	if( client->datagram.overflowed ) {
849 		Com_WPrintf( "Datagram overflowed for %s\n", client->name );
850 	} else if( msg_write.cursize + client->datagram.cursize >
851             msg_write.maxsize )
852     {
853 		Com_WPrintf( "Dumping datagram for %s\n", client->name );
854 	} else {
855 		MSG_WriteData( client->datagram.data, client->datagram.cursize );
856 	}
857 
858 	SZ_Clear( &client->datagram );
859 
860 	if( sv_pad_packets->integer ) {
861         int pad = msg_write.cursize + sv_pad_packets->integer;
862 
863         if( pad > msg_write.maxsize ) {
864             pad = msg_write.maxsize;
865         }
866 	    for( i = msg_write.cursize; i < pad; i++ ) {
867 		    MSG_WriteByte( svc_nop );
868 	    }
869     }
870 
871 	// send the datagram
872 	cursize = client->netchan->Transmit( client->netchan, msg_write.cursize,
873             msg_write.data );
874 
875 	// record the size for rate estimation
876 	SV_CalcSendTime( client, cursize );
877 
878 	// clear the write buffer
879 	SZ_Clear( &msg_write );
880 }
881 
SV_NewClientAddUnicast(client_t * client,int clientNum)882 void SV_NewClientAddUnicast( client_t *client, int clientNum ) {
883     sizebuf_t *buf;
884 
885     if( ( clientNum >> 7 ) & 1 ) {
886         buf = &client->netchan->message;
887     } else {
888         buf = &client->datagram;
889     }
890 
891     SZ_WriteByte( buf, svc_unicast );
892     SZ_WriteByte( buf, clientNum );
893     SZ_WriteShort( buf, msg_write.cursize );
894     SZ_Write( buf, msg_write.data, msg_write.cursize );
895 }
896 
SV_NewClientAddMulticast(client_t * client,const vec3_t origin,multicast_t to)897 void SV_NewClientAddMulticast( client_t *client, const vec3_t origin,
898         multicast_t to )
899 {
900     int size;
901     sizebuf_t *buf;
902 
903     if( to >= MULTICAST_ALL_R ) {
904         buf = &client->netchan->message;
905     } else {
906         buf = &client->datagram;
907     }
908 
909 	size = ( to << 12 ) | ( msg_write.cursize & 0xFFF );
910 
911     SZ_WriteByte( buf, svc_multicast );
912     SZ_WriteShort( buf, size );
913 
914     /* write exact position for PVS/PHS checks */
915     if( to != MULTICAST_ALL && to != MULTICAST_ALL_R ) {
916         SZ_WriteExactPos( buf, origin );
917     }
918 
919     SZ_Write( buf, msg_write.data, msg_write.cursize );
920 }
921 
922 /*
923 ===============================================================================
924 
925 COMMON STUFF
926 
927 ===============================================================================
928 */
929 
930 /*
931 ==================
932 SV_DemoCompleted
933 ==================
934 */
SV_DemoCompleted(void)935 void SV_DemoCompleted( void ) {
936 	Com_DPrintf( "SV_DemoCompleted()\n" );
937 	if( sv.demofile ) {
938 		FS_FCloseFile( sv.demofile );
939 		sv.demofile = 0;
940 	}
941 	SV_Nextserver();
942 }
943 
944 
945 /*
946 =======================
947 SV_SendClientMessages
948 
949 Called each game frame, sends svc_frame messages to spawned clients only.
950 Clients in earlier connection state are handled in SV_SendAsyncPackets.
951 =======================
952 */
SV_SendClientMessages(void)953 void SV_SendClientMessages( void ) {
954 	client_t	*client;
955 	int			msglen;
956 	int			r;
957 
958 	demo_msglen = 0;
959 
960 	// read the next demo message if needed
961 	if( sv.state == ss_demo && sv.demofile ) {
962 		// get the next message
963 		r = FS_Read( &msglen, 4, sv.demofile );
964 		if( r != 4 ) {
965 			SV_DemoCompleted();
966 			return;
967 		}
968 		msglen = LittleLong( msglen );
969 		if( msglen == -1 ) {
970 			SV_DemoCompleted();
971 			return;
972 		}
973 		if( msglen < 0 || msglen > MAX_PACKETLEN )
974 			Com_Error( ERR_DROP, "SV_SendClientMessages: bad demo msglen" );
975 		r = FS_Read( demo_data, msglen, sv.demofile );
976 		if( r != msglen ) {
977 			SV_DemoCompleted();
978 			return;
979 		}
980 		demo_msglen = msglen;
981 
982 	}
983 
984 	if( sv.state != ss_game && sv.state != ss_broadcast ) {
985 		// send a demo message to each connected client
986         FOR_EACH_CLIENT( client ) {
987 			if( client->netchan->type == NETCHAN_OLD ) {
988 				SV_OldClientWriteReliableMessages( client,
989                         client->netchan->maxpacketlen );
990 			}
991 			client->netchan->Transmit( client->netchan,
992                     demo_msglen, demo_data );
993 		}
994 		return;
995 	}
996 
997 	// send a message to each connected client
998     FOR_EACH_CLIENT( client ) {
999 		if( client->state != cs_spawned || client->download || client->nodata )
1000 			continue;
1001 
1002 		// if the reliable message overflowed,
1003 		// drop the client (should never happen)
1004 		if( client->netchan->message.overflowed ) {
1005 			SZ_Clear( &client->netchan->message );
1006 			SV_DropClient( client, "overflowed" );
1007 		}
1008 
1009 		// don't overrun bandwidth
1010 		if( SV_RateDrop( client ) ) {
1011 			if( sv_debug_send->integer ) {
1012 				Com_Printf( "Frame %d surpressed for %s\n", sv.framenum,
1013                         client->name );
1014 			}
1015 			client->surpressCount++;
1016 			continue;
1017 		}
1018 
1019 		// don't write any frame data until all fragments are sent
1020 		if( client->netchan->fragment_pending ) {
1021 			msglen = client->netchan->TransmitNextFragment( client->netchan );
1022 			SV_CalcSendTime( client, msglen );
1023 			continue;
1024 		}
1025 
1026         client->BuildFrame( client );
1027 	    client->WriteDatagram( client );
1028 	}
1029 }
1030 
1031