76 |
76 |
77 |
77 |
78 #define SEND_MTU 1460 |
78 #define SEND_MTU 1460 |
79 |
79 |
80 #if defined(ENABLE_NETWORK) |
80 #if defined(ENABLE_NETWORK) |
|
81 |
|
82 enum { |
|
83 PACKET_TYPE_WELCOME = 0, |
|
84 PACKET_TYPE_READY, |
|
85 PACKET_TYPE_ACK, |
|
86 PACKET_TYPE_SYNC, |
|
87 PACKET_TYPE_XMIT, |
|
88 PACKET_TYPE_COMMAND, |
|
89 }; |
81 |
90 |
82 // sent from client -> server whenever the client wants to exec a command. |
91 // sent from client -> server whenever the client wants to exec a command. |
83 // send from server -> client when another player execs a command. |
92 // send from server -> client when another player execs a command. |
84 typedef struct CommandPacket { |
93 typedef struct CommandPacket { |
85 byte packet_length; |
94 byte packet_length; |
90 byte player;// player id, this is checked by the server. |
99 byte player;// player id, this is checked by the server. |
91 byte when; // offset from the current max_frame value minus 1. this is set by the server. |
100 byte when; // offset from the current max_frame value minus 1. this is set by the server. |
92 uint32 dp[8]; |
101 uint32 dp[8]; |
93 } CommandPacket; |
102 } CommandPacket; |
94 |
103 |
95 assert_compile(sizeof(CommandPacket) == 16 + 32); |
|
96 |
|
97 #define COMMAND_PACKET_BASE_SIZE (sizeof(CommandPacket) - 8 * sizeof(uint32)) |
104 #define COMMAND_PACKET_BASE_SIZE (sizeof(CommandPacket) - 8 * sizeof(uint32)) |
98 |
105 |
99 // sent from server -> client periodically to tell the client about the current tick in the server |
106 // sent from server -> client periodically to tell the client about the current tick in the server |
100 // and how far the client may progress. |
107 // and how far the client may progress. |
101 typedef struct SyncPacket { |
108 typedef struct SyncPacket { |
105 byte server; // where is the server currently executing? this is negatively relative to the old value of max. |
112 byte server; // where is the server currently executing? this is negatively relative to the old value of max. |
106 uint32 random_seed_1; // current random state at server. used to detect out of sync. |
113 uint32 random_seed_1; // current random state at server. used to detect out of sync. |
107 uint32 random_seed_2; |
114 uint32 random_seed_2; |
108 } SyncPacket; |
115 } SyncPacket; |
109 |
116 |
110 assert_compile(sizeof(SyncPacket) == 12); |
|
111 |
|
112 // sent from server -> client as an acknowledgement that the server received the command. |
117 // sent from server -> client as an acknowledgement that the server received the command. |
113 // the command will be executed at the current value of "max". |
118 // the command will be executed at the current value of "max". |
114 typedef struct AckPacket { |
119 typedef struct AckPacket { |
115 byte packet_length; |
120 byte packet_length; |
116 byte packet_type; |
121 byte packet_type; |
|
122 byte when; |
117 } AckPacket; |
123 } AckPacket; |
118 |
124 |
119 typedef struct ReadyPacket { |
125 typedef struct ReadyPacket { |
120 byte packet_length; |
126 byte packet_length; |
121 byte packet_type; |
127 byte packet_type; |
122 } ReadyPacket; |
128 } ReadyPacket; |
123 |
129 |
124 typedef struct FilePacketHdr { |
130 typedef struct FilePacketHdr { |
125 byte packet_length; |
131 byte packet_length; |
126 byte packet_type; |
132 byte packet_type; |
127 byte unused[2]; |
|
128 } FilePacketHdr; |
133 } FilePacketHdr; |
129 |
|
130 assert_compile(sizeof(FilePacketHdr) == 4); |
|
131 |
134 |
132 // sent from server to client when the client has joined. |
135 // sent from server to client when the client has joined. |
133 typedef struct WelcomePacket { |
136 typedef struct WelcomePacket { |
134 byte packet_length; |
137 byte packet_length; |
135 byte packet_type; |
138 byte packet_type; |
136 byte unused[2]; |
139 uint32 player_seeds[MAX_PLAYERS][2]; |
|
140 uint32 frames_max; |
|
141 uint32 frames_srv; |
|
142 uint32 frames_cnt; |
137 } WelcomePacket; |
143 } WelcomePacket; |
138 |
144 |
139 typedef struct Packet Packet; |
145 typedef struct Packet Packet; |
140 struct Packet { |
146 struct Packet { |
141 Packet *next; // this one has to be the first element. |
147 Packet *next; // this one has to be the first element. |
153 |
159 |
154 uint eaten; |
160 uint eaten; |
155 Packet *head, **last; |
161 Packet *head, **last; |
156 |
162 |
157 uint buflen; // receive buffer len |
163 uint buflen; // receive buffer len |
158 byte buf[256]; // receive buffer |
164 byte buf[1024]; // receive buffer |
159 } ClientState; |
165 } ClientState; |
160 |
166 |
161 |
|
162 static uint _not_packet; |
|
163 |
167 |
164 typedef struct QueuedCommand QueuedCommand; |
168 typedef struct QueuedCommand QueuedCommand; |
165 struct QueuedCommand { |
169 struct QueuedCommand { |
166 QueuedCommand *next; |
170 QueuedCommand *next; |
167 CommandPacket cp; |
171 CommandPacket cp; |
168 CommandCallback *callback; |
172 CommandCallback *callback; |
169 uint32 cmd; |
173 uint32 cmd; |
170 int32 frame; |
174 uint32 frame; |
171 }; |
175 }; |
172 |
176 |
173 typedef struct CommandQueue CommandQueue; |
177 typedef struct CommandQueue CommandQueue; |
174 struct CommandQueue { |
178 struct CommandQueue { |
175 QueuedCommand *head, **last; |
179 QueuedCommand *head, **last; |
193 static bool _network_ready_sent; |
197 static bool _network_ready_sent; |
194 static uint16 _network_ready_ahead = 1; |
198 static uint16 _network_ready_ahead = 1; |
195 static uint16 _network_client_timeout; |
199 static uint16 _network_client_timeout; |
196 |
200 |
197 typedef struct FutureSeeds { |
201 typedef struct FutureSeeds { |
198 int32 frame; |
202 uint32 frame; |
199 uint32 seed[2]; |
203 uint32 seed[2]; |
200 } FutureSeeds; |
204 } FutureSeeds; |
201 |
205 |
202 // remember some future seeds that the server sent to us. |
206 // remember some future seeds that the server sent to us. |
203 static FutureSeeds _future_seed[8]; |
207 static FutureSeeds _future_seed[8]; |
221 NET_UDPCMD_GETSERVERINFO, |
225 NET_UDPCMD_GETSERVERINFO, |
222 NET_UDPCMD_SERVERINFO, |
226 NET_UDPCMD_SERVERINFO, |
223 }; |
227 }; |
224 |
228 |
225 void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet); |
229 void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet); |
|
230 static void CloseClient(ClientState *cs); |
|
231 void NetworkSendWelcome(ClientState *cs, bool direct); |
226 |
232 |
227 uint32 _network_ip_list[10]; // network ip list |
233 uint32 _network_ip_list[10]; // network ip list |
228 |
234 |
229 // this is set to point to the savegame |
235 // this is set to point to the savegame |
230 static byte *_transmit_file; |
236 static byte *_transmit_file; |
338 *nq->last = qp; |
344 *nq->last = qp; |
339 nq->last = &qp->next; |
345 nq->last = &qp->next; |
340 return qp; |
346 return qp; |
341 } |
347 } |
342 |
348 |
|
349 static void QueueClear(CommandQueue *nq) { |
|
350 QueuedCommand *qp; |
|
351 while ((qp=nq->head)) { |
|
352 // unlink it. |
|
353 if (!(nq->head = qp->next)) nq->last = &nq->head; |
|
354 free(qp); |
|
355 } |
|
356 nq->last = &nq->head; |
|
357 } |
|
358 |
343 // go through the player queues for each player and see if there are any pending commands |
359 // go through the player queues for each player and see if there are any pending commands |
344 // that should be executed this frame. if there are, execute them. |
360 // that should be executed this frame. if there are, execute them. |
345 void NetworkProcessCommands() |
361 void NetworkProcessCommands() |
346 { |
362 { |
347 CommandQueue *nq; |
363 CommandQueue *nq; |
414 b += n; |
430 b += n; |
415 p = NULL; |
431 p = NULL; |
416 } while (len -= n); |
432 } while (len -= n); |
417 } |
433 } |
418 |
434 |
|
435 // send data direct to a client |
|
436 static void SendDirectBytes(ClientState *cs, void *bytes, uint len) |
|
437 { |
|
438 char *buf = (char*)bytes; |
|
439 uint n; |
|
440 |
|
441 n = send(cs->socket, buf, len, 0); |
|
442 if (n == -1) { |
|
443 int err = GET_LAST_ERROR(); |
|
444 DEBUG(net, 0) ("[NET] send() failed with error %d", err); |
|
445 CloseClient(cs); |
|
446 } |
|
447 } |
|
448 |
419 // client: |
449 // client: |
420 // add it to the client's ack queue, and send the command to the server |
450 // add it to the client's ack queue, and send the command to the server |
421 // server: |
451 // server: |
422 // add it to the server's player queue, and send it to all clients. |
452 // add it to the server's player queue, and send it to all clients. |
423 void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) |
453 void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) |
425 int nump; |
455 int nump; |
426 QueuedCommand *qp; |
456 QueuedCommand *qp; |
427 ClientState *cs; |
457 ClientState *cs; |
428 |
458 |
429 qp = AllocQueuedCommand(_networking_server ? &_command_queue : &_ack_queue); |
459 qp = AllocQueuedCommand(_networking_server ? &_command_queue : &_ack_queue); |
430 qp->cp.packet_type = 0; |
460 qp->cp.packet_type = PACKET_TYPE_COMMAND; |
431 qp->cp.tile = tile; |
461 qp->cp.tile = tile; |
432 qp->cp.p1 = p1; |
462 qp->cp.p1 = p1; |
433 qp->cp.p2 = p2; |
463 qp->cp.p2 = p2; |
434 qp->cp.cmd = (uint16)cmd; |
464 qp->cp.cmd = (uint16)cmd; |
435 qp->cp.player = _local_player; |
465 qp->cp.player = _local_player; |
436 qp->cp.when = 0; |
466 qp->cp.when = 0; |
437 qp->cmd = cmd; |
467 qp->cmd = cmd; |
438 qp->callback = callback; |
468 qp->callback = callback; |
439 |
469 |
440 // so the server knows when to execute it. |
470 // so the server knows when to execute it. |
441 qp->frame = _frame_counter_max; |
471 qp->frame = _frame_counter + 5; |
442 |
472 |
443 // calculate the amount of extra bytes. |
473 // calculate the amount of extra bytes. |
444 nump = 8; |
474 nump = 8; |
445 while ( nump != 0 && ((uint32*)_decode_parameters)[nump-1] == 0) nump--; |
475 while ( nump != 0 && ((uint32*)_decode_parameters)[nump-1] == 0) nump--; |
446 qp->cp.packet_length = COMMAND_PACKET_BASE_SIZE + nump * sizeof(uint32); |
476 qp->cp.packet_length = COMMAND_PACKET_BASE_SIZE + nump * sizeof(uint32); |
478 static void HandleCommandPacket(ClientState *cs, CommandPacket *np) |
508 static void HandleCommandPacket(ClientState *cs, CommandPacket *np) |
479 { |
509 { |
480 QueuedCommand *qp; |
510 QueuedCommand *qp; |
481 ClientState *c; |
511 ClientState *c; |
482 AckPacket ap; |
512 AckPacket ap; |
|
513 int i; |
483 |
514 |
484 DEBUG(net, 2) ("[NET] cmd size %d", np->packet_length); |
515 DEBUG(net, 2) ("[NET] cmd size %d", np->packet_length); |
485 |
516 |
486 assert(np->packet_length >= COMMAND_PACKET_BASE_SIZE); |
517 assert(np->packet_length >= COMMAND_PACKET_BASE_SIZE); |
487 |
518 |
488 // put it into the command queue |
519 // put it into the command queue |
489 qp = AllocQueuedCommand(&_command_queue); |
520 qp = AllocQueuedCommand(&_command_queue); |
490 qp->cp = *np; |
521 qp->cp = *np; |
491 |
522 |
492 qp->frame = _frame_counter_max; |
523 i = _frame_counter_max - (_frame_counter + 3); |
|
524 |
|
525 if (i<0) { |
|
526 qp->frame = _frame_counter_max ; |
|
527 } else { |
|
528 qp->frame = _frame_counter + 3; |
|
529 } |
493 |
530 |
494 qp->callback = NULL; |
531 qp->callback = NULL; |
495 |
532 |
496 // extra params |
533 // extra params |
497 memcpy(&qp->cp.dp, np->dp, np->packet_length - COMMAND_PACKET_BASE_SIZE); |
534 memcpy(&qp->cp.dp, np->dp, np->packet_length - COMMAND_PACKET_BASE_SIZE); |
498 |
535 |
499 ap.packet_type = 2; |
536 ap.packet_type = PACKET_TYPE_ACK; |
500 ap.packet_length = 2; |
537 ap.when = _frame_counter_max-(qp->frame); |
|
538 ap.packet_length = sizeof(AckPacket); |
501 |
539 |
502 // send it to the peers |
540 // send it to the peers |
503 if (_networking_server) { |
541 if (_networking_server) { |
504 for(c=_clients; c->socket != INVALID_SOCKET; c++) { |
542 for(c=_clients; c->socket != INVALID_SOCKET; c++) { |
505 if (c == cs) { |
543 if (c == cs) { |
506 SendBytes(c, &ap, 2); |
544 SendDirectBytes(c, &ap, ap.packet_length); |
507 } else { |
545 } else { |
508 if (!cs->inactive) SendBytes(c, &qp->cp, qp->cp.packet_length); |
546 if (!cs->inactive) SendBytes(c, &qp->cp, qp->cp.packet_length); |
509 } |
547 } |
510 } |
548 } |
511 } |
549 } |
538 return; |
576 return; |
539 |
577 |
540 s1 = TO_LE32(sp->random_seed_1); |
578 s1 = TO_LE32(sp->random_seed_1); |
541 s2 = TO_LE32(sp->random_seed_2); |
579 s2 = TO_LE32(sp->random_seed_2); |
542 |
580 |
543 DEBUG(net, 3) ("[NET] sync seeds: [1]=%i rnd[2]=%i", sp->random_seed_1, sp->random_seed_2); |
581 DEBUG(net, 3) ("[NET] sync seeds: frame=%i 1=%i 2=%i",_frame_counter, sp->random_seed_1, sp->random_seed_2); |
544 |
582 |
545 if (_frame_counter_srv <= _frame_counter) { |
583 if (_frame_counter_srv <= _frame_counter) { |
546 // we are ahead of the server check if the seed is in our list. |
584 // we are ahead of the server check if the seed is in our list. |
547 if (_frame_counter_srv + 16 > _frame_counter) { |
585 if (_frame_counter_srv + 16 > _frame_counter) { |
548 // the random seed exists in our array check it. |
586 // the random seed exists in our array check it. |
559 } |
597 } |
560 } |
598 } |
561 |
599 |
562 // sent from server -> client as an acknowledgement that the server received the command. |
600 // sent from server -> client as an acknowledgement that the server received the command. |
563 // the command will be executed at the current value of "max". |
601 // the command will be executed at the current value of "max". |
564 static void HandleAckPacket() |
602 static void HandleAckPacket(AckPacket * ap) |
565 { |
603 { |
566 QueuedCommand *q; |
604 QueuedCommand *q; |
567 // move a packet from the ack queue to the end of this player's queue. |
605 // move a packet from the ack queue to the end of this player's queue. |
568 q = _ack_queue.head; |
606 q = _ack_queue.head; |
569 assert(q); |
607 assert(q); |
570 if (!(_ack_queue.head = q->next)) _ack_queue.last = &_ack_queue.head; |
608 if (!(_ack_queue.head = q->next)) _ack_queue.last = &_ack_queue.head; |
571 q->next = NULL; |
609 q->next = NULL; |
572 q->frame = _frame_counter_max; |
610 q->frame = (_frame_counter_max - (ap->when)); |
573 |
611 |
574 *_command_queue.last = q; |
612 *_command_queue.last = q; |
575 _command_queue.last = &q->next; |
613 _command_queue.last = &q->next; |
576 |
614 |
577 DEBUG(net, 2) ("[NET] ack"); |
615 DEBUG(net, 2) ("[NET] ack [frame=%i]",q->frame); |
578 } |
616 } |
579 |
617 |
580 static void HandleFilePacket(FilePacketHdr *fp) |
618 static void HandleFilePacket(FilePacketHdr *fp) |
581 { |
619 { |
582 int n = fp->packet_length - sizeof(FilePacketHdr); |
620 int n = fp->packet_length - sizeof(FilePacketHdr); |
617 } |
655 } |
618 fwrite( (char*)fp + sizeof(*fp), n, 1, _recv_file); |
656 fwrite( (char*)fp + sizeof(*fp), n, 1, _recv_file); |
619 } |
657 } |
620 } |
658 } |
621 |
659 |
|
660 static void HandleWelcomePacket(WelcomePacket *wp) { |
|
661 int i; |
|
662 for (i=0; i<MAX_PLAYERS; i++) { |
|
663 _player_seeds[i][0]=wp->player_seeds[i][0]; |
|
664 _player_seeds[i][1]=wp->player_seeds[i][1]; |
|
665 } |
|
666 if (wp->frames_srv != 0) { |
|
667 _frame_counter_max = wp->frames_max; |
|
668 _frame_counter_srv = wp->frames_srv; |
|
669 } |
|
670 if (wp->frames_cnt != 0) { |
|
671 _frame_counter = wp->frames_cnt; |
|
672 } |
|
673 } |
|
674 |
|
675 static void HandleReadyPacket(ReadyPacket *rp, ClientState *cs) |
|
676 { |
|
677 cs->ready=true; |
|
678 cs->timeout=_network_client_timeout; |
|
679 } |
|
680 |
|
681 |
622 static void CloseClient(ClientState *cs) |
682 static void CloseClient(ClientState *cs) |
623 { |
683 { |
624 Packet *p, *next; |
684 Packet *p, *next; |
625 |
685 |
626 DEBUG(net, 1) ("[NET][TCP] closed client connection"); |
686 DEBUG(net, 1) ("[NET][TCP] closed client connection"); |
678 // whole packet not there yet? |
738 // whole packet not there yet? |
679 if (size < packet[0]) break; |
739 if (size < packet[0]) break; |
680 size -= packet[0]; |
740 size -= packet[0]; |
681 pos += packet[0]; |
741 pos += packet[0]; |
682 switch(packet[1]) { |
742 switch(packet[1]) { |
683 case 0: |
743 case PACKET_TYPE_WELCOME: |
|
744 HandleWelcomePacket((WelcomePacket *)packet); |
|
745 break; |
|
746 case PACKET_TYPE_COMMAND: |
684 HandleCommandPacket(cs, (CommandPacket*)packet); |
747 HandleCommandPacket(cs, (CommandPacket*)packet); |
685 break; |
748 break; |
686 case 1: |
749 case PACKET_TYPE_SYNC: |
687 assert(_networking_sync || _networking_queuing); |
750 assert(_networking_sync || _networking_queuing); |
688 assert(!_networking_server); |
751 assert(!_networking_server); |
689 HandleSyncPacket((SyncPacket*)packet); |
752 HandleSyncPacket((SyncPacket*)packet); |
690 break; |
753 break; |
691 case 2: |
754 case PACKET_TYPE_ACK: |
692 assert(!_networking_server); |
755 assert(!_networking_server); |
693 HandleAckPacket(); |
756 HandleAckPacket((AckPacket*)packet); |
694 break; |
757 break; |
695 case 3: |
758 case PACKET_TYPE_XMIT: |
696 HandleFilePacket((FilePacketHdr*)packet); |
759 HandleFilePacket((FilePacketHdr*)packet); |
697 break; |
760 break; |
698 case 5: |
761 case PACKET_TYPE_READY: |
699 cs->ready=true; |
762 HandleReadyPacket((ReadyPacket*)packet, cs); |
700 cs->timeout=_network_client_timeout; |
|
701 break; |
763 break; |
702 default: |
764 default: |
703 DEBUG (net,0) ("net: unknown packet type"); |
765 DEBUG (net,0) ("net: unknown packet type"); |
704 } |
766 } |
705 } |
767 } |
781 do { |
843 do { |
782 // compute size of data to xmit |
844 // compute size of data to xmit |
783 n = minu(_transmit_file_size - pos, 248); |
845 n = minu(_transmit_file_size - pos, 248); |
784 |
846 |
785 hdr.packet_length = n + sizeof(hdr); |
847 hdr.packet_length = n + sizeof(hdr); |
786 hdr.packet_type = 3; |
848 hdr.packet_type = PACKET_TYPE_XMIT; |
787 hdr.unused[0] = hdr.unused[1] = 0; |
|
788 SendBytes(cs, &hdr, sizeof(hdr)); |
849 SendBytes(cs, &hdr, sizeof(hdr)); |
789 |
850 |
790 if (n == 0) { |
851 if (n == 0) { |
791 pos = -1; // eof |
852 pos = -1; // eof |
792 break; |
853 break; |
794 SendBytes(cs, _transmit_file + pos, n); |
855 SendBytes(cs, _transmit_file + pos, n); |
795 pos += n; |
856 pos += n; |
796 } while (--p); |
857 } while (--p); |
797 |
858 |
798 cs->xmitpos = pos + 1; |
859 cs->xmitpos = pos + 1; |
|
860 |
|
861 if (cs->xmitpos == 0) { |
|
862 NetworkSendWelcome(cs,false); |
|
863 } |
799 |
864 |
800 DEBUG(net, 2) ("[NET] client xmit at %d", pos + 1); |
865 DEBUG(net, 2) ("[NET] client xmit at %d", pos + 1); |
801 } |
866 } |
802 |
867 |
803 static ClientState *AllocClient(SOCKET s) |
868 static ClientState *AllocClient(SOCKET s) |
817 return cs; |
882 return cs; |
818 } |
883 } |
819 |
884 |
820 void NetworkSendReadyPacket() |
885 void NetworkSendReadyPacket() |
821 { |
886 { |
822 if (!_network_ready_sent) { |
887 if ((!_network_ready_sent) && (_frame_counter + _network_ready_ahead >= _frame_counter_max)) { |
823 ReadyPacket *rp = malloc(sizeof(rp)); |
888 ReadyPacket *rp = malloc(sizeof(rp)); |
824 ClientState *c = _clients; |
889 ClientState *c = _clients; |
825 |
890 |
826 rp->packet_type = 5; |
891 rp->packet_type = PACKET_TYPE_READY; |
827 rp->packet_length = sizeof(rp); |
892 rp->packet_length = sizeof(rp); |
828 SendBytes(c, rp, sizeof(rp)); |
893 SendBytes(c, rp, sizeof(rp)); |
829 _network_ready_sent = true; |
894 _network_ready_sent = true; |
|
895 } |
|
896 } |
|
897 |
|
898 void NetworkSendSyncPackets() |
|
899 { |
|
900 ClientState *cs; |
|
901 uint32 new_max; |
|
902 SyncPacket sp; |
|
903 |
|
904 new_max = _frame_counter + (int)_network_sync_freq; |
|
905 |
|
906 DEBUG(net,3) ("net: serv: sync frame=%i,max=%i, seed1=%i, seed2=%i",new_max,_sync_seed_1,_sync_seed_2); |
|
907 |
|
908 sp.packet_length = sizeof(sp); |
|
909 sp.packet_type = PACKET_TYPE_SYNC; |
|
910 sp.frames = new_max - _frame_counter_max; |
|
911 sp.server = _frame_counter_max - _frame_counter; |
|
912 sp.random_seed_1 = TO_LE32(_sync_seed_1); |
|
913 sp.random_seed_2 = TO_LE32(_sync_seed_2); |
|
914 _frame_counter_max = new_max; |
|
915 |
|
916 // send it to all the clients and mark them unready |
|
917 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
|
918 cs->ready=false; |
|
919 SendBytes(cs, &sp, sizeof(sp)); |
|
920 } |
|
921 |
|
922 } |
|
923 |
|
924 void NetworkSendWelcome(ClientState *cs, bool direct) { |
|
925 WelcomePacket wp; |
|
926 int i; |
|
927 wp.packet_type = PACKET_TYPE_WELCOME; |
|
928 wp.packet_length = sizeof(WelcomePacket); |
|
929 for (i=0; i<MAX_PLAYERS; i++) { |
|
930 wp.player_seeds[i][0]=_player_seeds[i][0]; |
|
931 wp.player_seeds[i][1]=_player_seeds[i][1]; |
|
932 } |
|
933 if (direct) { |
|
934 wp.frames_max=0; |
|
935 wp.frames_srv=0; |
|
936 wp.frames_cnt=_frame_counter; |
|
937 SendDirectBytes(cs,(void *)&wp,wp.packet_length); |
|
938 } else { |
|
939 wp.frames_max=_frame_counter_max; |
|
940 wp.frames_srv=_frame_counter_srv; |
|
941 wp.frames_cnt=0; |
|
942 SendBytes(cs,(void *)&wp,wp.packet_length); |
830 } |
943 } |
831 } |
944 } |
832 |
945 |
833 static void NetworkAcceptClients() |
946 static void NetworkAcceptClients() |
834 { |
947 { |
886 static void SendQueuedCommandsToNewClient(ClientState *cs) |
999 static void SendQueuedCommandsToNewClient(ClientState *cs) |
887 { |
1000 { |
888 // send the commands in the server queue to the new client. |
1001 // send the commands in the server queue to the new client. |
889 QueuedCommand *qp; |
1002 QueuedCommand *qp; |
890 SyncPacket sp; |
1003 SyncPacket sp; |
891 int32 frame; |
1004 uint32 frame; |
892 |
1005 |
893 DEBUG(net, 2) ("[NET] sending queued commands to client"); |
1006 DEBUG(net, 2) ("[NET] sending queued commands to client"); |
894 |
1007 |
895 sp.packet_length = sizeof(sp); |
1008 sp.packet_length = sizeof(sp); |
896 sp.packet_type = 1; |
1009 sp.packet_type = PACKET_TYPE_SYNC; |
897 sp.random_seed_1 = sp.random_seed_2 = 0; |
1010 sp.random_seed_1 = sp.random_seed_2 = 0; |
898 sp.server = 0; |
1011 sp.server = 0; |
899 |
1012 |
900 frame = _frame_counter; |
1013 frame = _frame_counter; |
901 |
1014 |
914 DEBUG(net, 4) ("[NET] sending queued sync %d (%d)", _frame_counter_max, frame); |
1027 DEBUG(net, 4) ("[NET] sending queued sync %d (%d)", _frame_counter_max, frame); |
915 sp.frames = _frame_counter_max - frame; |
1028 sp.frames = _frame_counter_max - frame; |
916 SendBytes(cs, &sp, sizeof(sp)); |
1029 SendBytes(cs, &sp, sizeof(sp)); |
917 } |
1030 } |
918 |
1031 |
|
1032 } |
|
1033 |
|
1034 |
|
1035 bool NetworkCheckClientReady() { |
|
1036 bool ready_all = true; |
|
1037 uint16 count = 0; |
|
1038 ClientState *cs; |
|
1039 |
|
1040 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
|
1041 count++; |
|
1042 ready_all = ready_all && (cs->ready || cs->inactive || (cs->xmitpos>0)); |
|
1043 if (!cs->ready) cs->timeout-=1; |
|
1044 if (cs->timeout == 0) { |
|
1045 SET_DPARAM16(0,count); |
|
1046 ShowErrorMessage(-1,STR_NETWORK_ERR_TIMEOUT,0,0); |
|
1047 CloseClient(cs); |
|
1048 } |
|
1049 } |
|
1050 return ready_all; |
919 } |
1051 } |
920 |
1052 |
921 // ************************** // |
1053 // ************************** // |
922 // * TCP Networking * // |
1054 // * TCP Networking * // |
923 // ************************** // |
1055 // ************************** // |
1075 // and start sending the file.. |
1207 // and start sending the file.. |
1076 cs->xmitpos = 1; |
1208 cs->xmitpos = 1; |
1077 |
1209 |
1078 // send queue of commands to client. |
1210 // send queue of commands to client. |
1079 SendQueuedCommandsToNewClient(cs); |
1211 SendQueuedCommandsToNewClient(cs); |
|
1212 |
|
1213 NetworkSendWelcome(cs, true); |
1080 } |
1214 } |
1081 } |
1215 } |
1082 } |
1216 } |
1083 } |
1217 } |
1084 |
1218 |
1085 void NetworkSend() |
1219 void NetworkSend() |
1086 { |
1220 { |
1087 ClientState *cs; |
1221 ClientState *cs; |
1088 void *free_xmit; |
1222 void *free_xmit; |
1089 uint16 count; |
|
1090 bool ready_all; |
|
1091 |
|
1092 // send sync packets? |
|
1093 if (_networking_server && _networking_sync && !_pause) { |
|
1094 |
|
1095 if (++_not_packet >= _network_sync_freq) { |
|
1096 SyncPacket sp; |
|
1097 uint new_max; |
|
1098 |
|
1099 _network_ahead_frames = _network_sync_freq + 1; |
|
1100 |
|
1101 ready_all=false; |
|
1102 |
|
1103 while (!ready_all) { |
|
1104 // check wether all clients are ready |
|
1105 ready_all=true; |
|
1106 count=0; |
|
1107 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
|
1108 count++; |
|
1109 ready_all = ready_all && (cs->ready || cs->inactive || (cs->xmitpos>0)); |
|
1110 if (!cs->ready) cs->timeout-=5; |
|
1111 if (cs->timeout == 0) { |
|
1112 SET_DPARAM16(0,count); |
|
1113 ShowErrorMessage(-1,STR_NETWORK_ERR_TIMEOUT,0,0); |
|
1114 CloseClient(cs); |
|
1115 } |
|
1116 } |
|
1117 if (!ready_all) { |
|
1118 NetworkReceive(); |
|
1119 CSleep(5); |
|
1120 } |
|
1121 } |
|
1122 |
|
1123 _not_packet = 0; |
|
1124 |
|
1125 new_max = max(_frame_counter + (int)_network_ahead_frames, _frame_counter_max); |
|
1126 |
|
1127 DEBUG(net,3) ("net: serv: sync max=%i, seed1=%i, seed2=%i",new_max,_sync_seed_1,_sync_seed_2); |
|
1128 |
|
1129 sp.packet_length = sizeof(sp); |
|
1130 sp.packet_type = 1; |
|
1131 sp.frames = new_max - _frame_counter_max; |
|
1132 sp.server = _frame_counter_max - _frame_counter; |
|
1133 sp.random_seed_1 = TO_LE32(_sync_seed_1); |
|
1134 sp.random_seed_2 = TO_LE32(_sync_seed_2); |
|
1135 _frame_counter_max = new_max; |
|
1136 |
|
1137 // send it to all the clients and mark them unready |
|
1138 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
|
1139 cs->ready=false; |
|
1140 SendBytes(cs, &sp, sizeof(sp)); |
|
1141 } |
|
1142 } |
|
1143 } |
|
1144 |
1223 |
1145 free_xmit = _transmit_file; |
1224 free_xmit = _transmit_file; |
1146 |
1225 |
1147 // send stuff to all clients |
1226 // send stuff to all clients |
1148 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
1227 for(cs=_clients;cs->socket != INVALID_SOCKET; cs++) { |
1166 |
1245 |
1167 void NetworkInitialize() |
1246 void NetworkInitialize() |
1168 { |
1247 { |
1169 ClientState *cs; |
1248 ClientState *cs; |
1170 |
1249 |
|
1250 QueueClear(&_command_queue); |
|
1251 QueueClear(&_ack_queue); |
1171 _command_queue.last = &_command_queue.head; |
1252 _command_queue.last = &_command_queue.head; |
1172 _ack_queue.last = &_ack_queue.head; |
|
1173 |
1253 |
1174 // invalidate all clients |
1254 // invalidate all clients |
1175 for(cs=_clients; cs != &_clients[MAX_CLIENTS]; cs++) |
1255 for(cs=_clients; cs != &_clients[MAX_CLIENTS]; cs++) |
1176 cs->socket = INVALID_SOCKET; |
1256 cs->socket = INVALID_SOCKET; |
1177 |
1257 |
1629 if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); |
1709 if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); |
1630 if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); |
1710 if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); |
1631 |
1711 |
1632 if (_networking) { |
1712 if (_networking) { |
1633 NetworkReceive(); |
1713 NetworkReceive(); |
1634 NetworkProcessCommands(); // to check if we got any new commands belonging to the current frame before we increase it. |
|
1635 } |
1714 } |
1636 |
1715 |
1637 } else { |
1716 } else { |
1638 |
1717 |
1639 // outgoing |
1718 if ( _udp_client_socket != INVALID_SOCKET ) NetworkUDPReceive(true); |
1640 |
1719 if ( _udp_server_socket != INVALID_SOCKET ) NetworkUDPReceive(false); |
1641 if ((_networking) && (!_networking_server) && (_frame_counter+_network_ready_ahead >= _frame_counter_max)) { |
|
1642 // send the "i" am ready message to the server |
|
1643 // [_network_ready_ahead] frames before "i" reach the frame-limit |
|
1644 NetworkSendReadyPacket(); |
|
1645 } |
|
1646 |
|
1647 |
1720 |
1648 if (_networking) { |
1721 if (_networking) { |
1649 NetworkSend(); |
1722 NetworkSend(); |
1650 } |
1723 } |
1651 |
1724 |