00001
00025
00026 #if defined(MSG_INF_TRIES) && defined(NDEBUG)
00027 #error Infinite message retries (MSG_INF_TRIES) may only be specified for debugging builds
00028 #endif
00029
00030 #include "aatree.h"
00031 #include "vector.h"
00032 #include "game.h"
00033 #include "gameconfig.h"
00034 #include "playernet.h"
00035 #include "net.h"
00036 #include <assert.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <SDL.h>
00040 #ifndef WIN32
00041 #include <unistd.h>
00042 #include <sys/types.h>
00043 #include <sys/socket.h>
00044 #endif
00045
00050 static AANode *inflightId = AA_ROOT_NODE;
00056 static Vector inflightTime;
00061 static Vector available;
00067 static Vector buffers;
00074 static Uint16 nextMessageId = 0;
00075
00076 extern Uint32 frameTime;
00077
00083 #define INIT_RESEND 192
00084
00090 #define INIT_BUFFERS 16
00091
00097 #define INIT_MESSAGES 32
00098
00103 #define INIT_TRIES 4
00104
00112 #define MIN_POINTERS 64 // half size for buffers
00113
00118 #define MAX_BUFFERS (Uint32)((networkState == NETSTATE_SERVER) ? 32 : 16)
00119
00124 #define MAX_MESSAGES (Uint32)((networkState == NETSTATE_SERVER) ? 128 : 64)
00125
00137 static Bool TimeCompare(MsgDescr **lesser, MsgDescr **greater) {
00138 return (*lesser)->nextSend < (*greater)->nextSend;
00139 }
00140
00148 static void MsgDescrDestructor(MsgDescr **msg) {
00149
00150 if ((*msg)->buffer != NULL) {
00151
00152 BufferFree((*msg)->buffer);
00153 }
00154
00155 free(*msg);
00156 #ifndef NDEBUG
00157
00158 *msg = (MsgDescr*)0xCDCDCDCD;
00159 #endif
00160 }
00161
00162 void CancelAllMessages() {
00163
00164 inflightTime.destructOp = (DestructorOp)MsgDescrDestructor;
00165
00166 if (inflightId != AA_ROOT_NODE) {
00167
00168 AATreeDestroy(inflightId);
00169
00170 inflightId = AA_ROOT_NODE;
00171 }
00172 VectorClear(&inflightTime);
00173
00174 inflightTime.destructOp = NULL;
00175 }
00176
00177 int GetNumOutgoingMessages() {
00178 return inflightTime.items;
00179 }
00180
00181 MsgDescr *MessageNew() {
00182 MsgDescr *msg;
00183 int loop;
00184
00185 if ((msg = (MsgDescr*)VectorLast(&available)) != NULL) {
00186
00187 msg = *(MsgDescr**)msg;
00188
00189 available.items--;
00190 }
00191
00192 else {
00193 msg = malloc(sizeof(MsgDescr));
00194 }
00195 #ifndef NDEBUG
00196
00197 memset(msg, 0xCD, sizeof(MsgDescr));
00198 #endif
00199
00200 msg->flags = 0;
00206 msg->interval = INIT_RESEND;
00207 msg->triesLeft = INIT_TRIES;
00208
00209 loop = DESTMAPLEN;
00210 do {
00211 msg->destMap[--loop] = 0;
00212 } while (loop > 0);
00213
00214 return msg;
00215 }
00216
00217 void MessageFree(MsgDescr *msg) {
00218 #ifndef NDEBUG
00219 int loop;
00220
00221 MsgDescr **ptr = (MsgDescr**)(available.array);
00222 assert(msg != NULL);
00223
00224 for (loop = available.items; loop > 0; loop--, ptr++) {
00225
00226 assert(msg != *ptr);
00227 }
00228 #endif
00229
00230 if ((msg->buffer != NULL) && !msg->buffLifeUnmanaged) {
00231
00232 BufferFree(msg->buffer);
00233 }
00234
00235 if (available.items >= MAX_MESSAGES) {
00236
00237 free(msg);
00238 }
00239 else {
00240
00241 msg->buffer = NULL;
00242
00243 VectorPush(&available, &msg);
00244 }
00245 }
00246
00247 NetBuffer *BufferNew() {
00248 long *spot;
00249 NetBuffer *buff;
00250
00251 if ((spot = (long*)VectorLast(&buffers)) == NULL) {
00252
00253 if ((buff = (NetBuffer*)malloc(sizeof(NetBuffer))) == NULL) {
00254
00255 return NULL;
00256 }
00257 }
00258 else {
00259
00260
00261
00262 buff = *(NetBuffer**)spot;
00263
00264 *spot = 0;
00265
00266 buffers.items--;
00267 }
00268
00269 buff->length = 0;
00270 return (NetBuffer*)buff;
00271 }
00272
00273 void BufferFree(NetBuffer *buff) {
00274 #ifndef NDEBUG
00275 int loop;
00276
00277 NetBuffer **ptr = (NetBuffer**)(buffers.array);
00278 assert(buff != NULL);
00279
00280 for (loop = buffers.items; loop > 0; loop--, ptr++) {
00281
00282 assert(buff != *ptr);
00283 }
00284 #endif
00285
00286 if (buffers.items >= MAX_BUFFERS) {
00287
00288 free(buff);
00289 }
00290 else {
00291
00292 VectorPush(&buffers, &buff);
00293 }
00294 }
00295
00296 void BufferVecDestr(void *buff) {
00297 BufferFree(*(NetBuffer **)buff);
00298 }
00299
00300 extern int sock;
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00458 static Bool Send(MsgDescr *msg, Bool inSys) {
00459 Uint32 now = SDL_GetTicks();
00460
00461
00462 if ((networkState == NETSTATE_RCVCFG) ||
00463 (networkState == NETSTATE_CLIENT) || (networkState == NETSTATE_CLIDISCONN)) {
00464
00465 if (msg->destMap[0] == 0)
00466
00467 goto Send_cancel;
00468
00469 if (msg->triesLeft == 0) {
00470
00471 if (msg->failFunc != NULL) {
00472 (*(msg->failFunc))(msg, NULL);
00473 }
00474 goto Send_cancel;
00475 }
00476
00477 if (!msg->noResend) {
00478
00479 if ((msg->approveFunc != NULL) &&
00480 !(*(msg->approveFunc))(msg, 0)) {
00481
00482 goto Send_cancel;
00483 }
00484
00485 else if (sendto(sock, msg->buffer->data, msg->buffer->length, 0,
00486 &outgoingAddr.addr, outgoingAddr.length) != msg->buffer->length) {
00487
00488 if (msg->failFunc != NULL) {
00489 (*(msg->failFunc))(msg, NULL);
00490 }
00491 goto Send_cancel;
00492 }
00493 msg->inflight = TRUE;
00494 }
00495 }
00496
00497 else {
00498 ClientData *client = clients;
00499 DESTMAPTYPE *sendFlags = &(msg->destMap[0]), sendFlagMask;
00500 int mappos = 0;
00501 int cid = 0;
00502 int processedClients = 0;
00503 Bool bcastSent = FALSE;
00504 for (; mappos < DESTMAPLEN; mappos++, sendFlags++) {
00505
00506 if (*sendFlags == 0) {
00507
00508 cid += sizeof(DESTMAPTYPE) * 8;
00509 client += sizeof(DESTMAPTYPE) * 8;
00510 continue;
00511 }
00512 sendFlagMask = 1;
00513
00514 for (; sendFlagMask && (cid < MAX_PLAYERS);
00515 client++, cid++, sendFlagMask <<= 1) {
00516
00517 if (!client->contact || (client->disconn &&
00518 ((now - client->disconnTime) >= 4096))) {
00519
00520 client->flags = 0;
00521
00522 *sendFlags &= ~sendFlagMask;
00523
00524 continue;
00525 }
00526 else if (client->disconn &&
00527 (msg->buffer->data[0] != MSG_TYPE_CONN_DISCONN))
00528 continue;
00529
00530
00531 if (!(*sendFlags & sendFlagMask) ||
00532
00533 (localPlayer == cid) ||
00534
00535
00536 (bcastSent && client->bcast)) {
00537
00538 continue;
00539 }
00540
00541 if (msg->triesLeft == 0) {
00542
00543
00544 if (msg->failFunc != NULL) {
00545 (*(msg->failFunc))(msg, client);
00546 }
00547 continue;
00548 }
00549
00550 if (!msg->noResend) {
00551
00552 if ((msg->approveFunc != NULL) &&
00553 !(*(msg->approveFunc))(msg, cid)) {
00554
00555 *sendFlags ^= sendFlagMask;
00556
00557 continue;
00558 }
00559
00560 if (msg->bcast && client->bcast) {
00561 assert(outgoingAddr.ipv4.sin_addr.s_addr ==
00562 htonl(INADDR_BROADCAST));
00563
00564 if (sendto(sock, msg->buffer->data, msg->buffer->length,
00565 0, &outgoingAddr.addr, outgoingAddr.length)
00566 != msg->buffer->length) {
00567
00568 goto Send_failure;
00569 }
00570
00571
00572
00573 bcastSent = TRUE;
00574 msg->inflight = TRUE;
00575 }
00576
00577 else {
00578
00579
00580
00581 if (sendto(sock, msg->buffer->data, msg->buffer->length,
00582 0, &(client->addr.addr), client->addr.length)
00583 != msg->buffer->length) {
00584 Send_failure:
00585
00586
00587 *sendFlags ^= sendFlagMask;
00588
00589 if (msg->failFunc != NULL) {
00590 (*(msg->failFunc))(msg, client);
00591 }
00592
00593 continue;
00594 }
00595 msg->inflight = TRUE;
00596
00597 }
00598 }
00599
00600 processedClients++;
00601 }
00602 }
00603
00604 if (processedClients == 0) {
00605
00606 goto Send_cancel;
00607 }
00608 #ifdef MSG_DEBUG
00609 else if (msg->destMap[0] <= 1) {
00610 printf("Message %i has no destination but went somewhere\n",
00611 msg->msgId);
00612 }
00613 #endif
00614 }
00615
00616 msg->nextSend = SDL_GetTicks() + msg->interval;
00617 #ifdef MSG_INF_TRIES
00618
00619 if (--msg->triesLeft == 0) {
00620
00621 msg->triesLeft++;
00622
00623 msg->interval = 16384;
00624 }
00625 else {
00626
00627 msg->interval <<= 1;
00628 }
00629 #else
00630
00631 msg->triesLeft--;
00632
00633 msg->interval <<= 1;
00634 #endif
00635 return TRUE;
00636 Send_cancel:
00637
00638 if (!msg->buffLifeUnmanaged) {
00639
00640 BufferFree(msg->buffer);
00641 msg->buffer = NULL;
00642 }
00643 if (inSys) {
00644 #ifdef MSG_DEBUG
00645 printf("Canceling message %i\n", msg->msgId);
00646 #endif
00647
00648 AATreeRemove(inflightId, msg->msgId);
00649 }
00650 MessageFree(msg);
00651 return FALSE;
00652 }
00653
00654 Bool AddMessage(MsgDescr *msg) {
00655 AANode *node;
00656
00657
00658 assert((msg->buffer != NULL) && (msg->buffer->length > 3));
00659
00660 assert(networkState <= NETSTATE_SERVER);
00661
00662 assert((networkState != NETSTATE_CLIENT) || (msg->destMap[0] == 1));
00663
00664 assert(msg->triesLeft > 0);
00665
00666 if (!msg->doNotAddId) {
00667
00668 if (++nextMessageId == 0xFFFF) {
00669
00670 nextMessageId++;
00671 }
00672
00673 msg->msgId = nextMessageId;
00674
00675 MSG_WRITE_16C(msg->buffer->data, 1, msg->msgId);
00676 }
00677
00678 if (Send(msg, FALSE)) {
00679
00680 node = AATreeAdd(&inflightId, msg->msgId);
00681 assert(node != NULL);
00682 node->data = msg;
00683
00684 VectorHeapPush(&inflightTime, &msg);
00685
00686 return TRUE;
00687 }
00688
00689 return FALSE;
00690 }
00691
00692 void ServiceMessages() {
00693 MsgDescr *msg;
00694 Uint32 now = SDL_GetTicks();
00695
00696 assert((networkState >= NETSTATE_CONNECTING) ||
00697 (networkState <= NETSTATE_SERVER));
00698
00699 while (1) {
00700
00701
00702 if (((msg = VectorFirst(&inflightTime)) == NULL) ||
00703 (msg = *(MsgDescr**)msg, msg->nextSend > now)) {
00704
00705 return;
00706 }
00707
00708 VectorHeapPop(&inflightTime);
00709 #ifdef MSG_DEBUG
00710 printf("Send message %d, ", msg->msgId);
00711
00712 {
00713 AANode *node;
00714 node = AATreeFind(inflightId, msg->msgId);
00715 if (node == NULL) {
00716 printf("***** Message not in tree *****\n");
00717 }
00718 else if (node->data != msg) {
00719 printf("***** Different message in tree, ID = %i *****\n",
00720 node->key);
00721 }
00722 else if (node->key != msg->msgId) {
00723 printf("***** Message in tree had different ID: %i *****\n",
00724 node->key);
00725 }
00726 }
00727
00728 #endif
00729
00730 if (Send(msg, TRUE)) {
00731
00732 VectorHeapPush(&inflightTime, &msg);
00733 #ifdef MSG_DEBUG
00734 printf("keeping for later\n");
00735 #endif
00736 }
00737 #ifdef MSG_DEBUG
00738 else printf("done with it\n");
00739 #endif
00740 }
00741 }
00742
00743 Bool ValidateClient(SocketAddr *origin, Uint8 clientId) {
00744 ClientData *client;
00745
00746 if ((clientId == localPlayer) ||
00747 #if (MAX_PLAYERS < 256)
00748
00749 (clientId > MAX_PLAYERS) ||
00750 #endif
00751
00752 (!(client = &(clients[clientId]))->contact) ||
00753
00754 !EqualAddresses(origin, &(client->addr))) {
00755 return FALSE;
00756 }
00757
00758 return TRUE;
00759 }
00760
00761 Bool ValidateServer(SocketAddr *origin) {
00762
00763
00764 if (((networkState == NETSTATE_RCVCFG) ||
00765 (networkState == NETSTATE_CLIENT) || (networkState == NETSTATE_CLIDISCONN)) &&
00766 EqualAddresses(origin, &outgoingAddr)) {
00767
00768 return TRUE;
00769 }
00770 return FALSE;
00771 }
00772
00820 static Bool HandleAck(SocketAddr *origin, NetBuffer *buff, Uint8 *unused,
00821 Uint16 noid) {
00822 AANode *node;
00823 Uint8 *ptr = &(buff->data[3]);
00824 int loop;
00825 DESTMAPTYPE *map, flag;
00826 Uint16 msgId;
00827 Uint8 clientId;
00828
00829 clientId = buff->data[1];
00830
00831 if (((((networkState == NETSTATE_RCVCFG) ||
00832 (networkState == NETSTATE_CLIENT) || (networkState == NETSTATE_CLIDISCONN))
00833 && !ValidateServer(origin)) || (((networkState == NETSTATE_SERVER) ||
00834 (networkState == NETSTATE_SRVDISCONN)) &&
00835 !ValidateClient(origin, clientId))) ||
00836
00837 (buff->length != (3 + buff->data[2] * 2))) {
00838 return FALSE;
00839 }
00840
00841 for (loop = buff->data[2]; loop > 0; loop--) {
00842
00843 MSG_READ_16(ptr, msgId);
00844
00845 if ((node = AATreeFind(inflightId, msgId)) != NULL) {
00846 #ifdef MSG_DEBUG
00847 if (node->key != msgId) {
00848 printf("***** Find got a node for a different key *****\n");
00849 printf("\tLooking for %i, got %i\n", msgId, node->key);
00850 }
00851 if (((MsgDescr*)(node->data))->msgId != msgId) {
00852 printf("***** Node's key differs from message ID *****\n");
00853 printf("\tNode key is %i, ID is %i\n", node->key,
00854 ((MsgDescr*)(node->data))->msgId);
00855 }
00856 #endif
00857
00858 map = &(((MsgDescr*)(node->data))->destMap[
00859 GetDestMapIndex(clientId)]);
00860 flag = GetDestMapFlag(clientId);
00861
00862 if (*map & flag) {
00863
00864 if ((*(((MsgDescr*)(node->data))->ackFunc)) != NULL) {
00865 (*(((MsgDescr*)(node->data))->ackFunc))((MsgDescr*)
00866 (node->data), clientId);
00867 }
00868
00869 *map &= ~flag;
00870 #ifdef MSG_DEBUG
00871 printf("Client #%d ack'ed message %d\n",
00872 clientId, msgId);
00873 #endif
00874 }
00875 #ifdef MSG_DEBUG
00876 else {
00877 int ind;
00878 DESTMAPTYPE bit;
00879 printf("Client #%d RE-ack'ed message %d\nDest: ",
00880 clientId, msgId);
00881 for (ind = 0; ind < DESTMAPLEN; ind++) {
00882 for (bit = 1; bit > 0; bit <<= 1) {
00883 if (((MsgDescr*)(node->data))->destMap[ind] & bit)
00884 putchar('1');
00885 else
00886 putchar('0');
00887 }
00888 }
00889 putchar('\n');
00890 }
00891 #endif
00892 }
00893 #ifdef MSG_DEBUG
00894 else {
00895 printf("Client #%d ack'ed CANCELED message %d\n",
00896 clientId, msgId);
00897 }
00898 #endif
00899 }
00900
00901 return FALSE;
00902 }
00903
00912 static void AckConnAccept(MsgDescr *msg, int cid) {
00913
00914 clients[cid].active = TRUE;
00915
00916 clients[cid].randId = 0;
00917
00918 AddToConfigList(&(clients[cid]));
00919 #ifndef NDEBUG
00920
00921
00922
00923
00924
00925
00926 #ifdef USE_GETTEXT
00927 wprintf(L"Accepted new client, ID = %d, broadcast = %d\n", cid,
00928 clients[cid].bcast);
00929 #else
00930 printf("Accepted new client, ID = %d, broadcast = %d\n", cid,
00931 clients[cid].bcast);
00932 #endif
00933 #endif
00934 }
00935
00945 static void FailConnAccept(MsgDescr *msg, ClientData *client) {
00946
00947 char outbuff[5];
00948
00949 outbuff[0] = MSG_TYPE_CONN_DENY;
00950
00951 MSG_WRITE_32C(outbuff, 1, client->randId);
00952
00953 sendto(sock, outbuff, 5, 0, &(client->addr.addr), client->addr.length);
00954
00955 client->flags = 0;
00956 #ifndef NDEBUG
00957
00958
00959
00960
00961
00962 #ifdef USE_GETTEXT
00963 wprintf(L"Attempted connection failed for client, ID = %d\n", client->cid);
00964 #else
00965 printf("Attempted connection failed for client, ID = %d\n", client->cid);
00966 #endif
00967 #endif
00968 }
00969
01019 static Bool HandleConnReq(SocketAddr *origin, NetBuffer *buff, Uint8 *unused,
01020 Uint16 noid) {
01021 MsgDescr *msg;
01022 ClientData *client = NULL, *spot = clients;
01023 int clientId, loop;
01024 Uint32 randId, now = SDL_GetTicks();
01025
01026 MSG_READ_32C(buff->data, 2, randId);
01027
01028 for (loop = 0; loop < MAX_PLAYERS; loop++, spot++) {
01029
01030 if ((spot->randId == randId) && EqualAddresses(&(spot->addr), origin)) {
01031
01032 return FALSE;
01033 }
01034
01035 if ((client == NULL) && (!spot->contact || (spot->disconn &&
01036 ((now - spot->disconnTime) >= 4096)))) {
01037
01038 spot->flags = 0;
01039
01040 client = spot;
01041 client->cid = clientId = loop;
01042 }
01043 }
01044
01045
01046 if ((client == NULL) || ((msg = MessageNew()) == NULL) ||
01047 ((msg->buffer = BufferNew()) == NULL)) {
01048
01049 char outbuff[5];
01050
01051 outbuff[0] = MSG_TYPE_CONN_DENY;
01052
01053 outbuff[1] = buff->data[2];
01054 outbuff[2] = buff->data[3];
01055 outbuff[3] = buff->data[4];
01056 outbuff[4] = buff->data[5];
01057
01058 sendto(sock, outbuff, 5, 0, &(origin->addr), origin->length);
01059
01060 if (msg != NULL) {
01061 MessageFree(msg);
01062 }
01063
01064 return FALSE;
01065 }
01066
01067 client->contact = TRUE;
01068
01069 client->bcast = 0;
01070
01071 client->randId = randId;
01072
01073 client->addr = *origin;
01074
01075 msg->approveFunc = NULL;
01076 msg->ackFunc = AckConnAccept;
01077 msg->failFunc = FailConnAccept;
01078 msg->interval <<= 1;
01079
01080 msg->buffer->length = 8;
01081 msg->buffer->data[0] = MSG_TYPE_CONN_ACCEPT;
01082 msg->buffer->data[3] = clientId;
01083
01084 MSG_WRITE_32C(msg->buffer->data, 4, client->randId);
01085
01086 msg->destMap[GetDestMapIndex(clientId)] = GetDestMapFlag(clientId);
01087
01088 if (networkState == NETSTATE_SERVER) {
01089
01090 AddMessage(msg);
01091 }
01092
01093 return FALSE;
01094 }
01095
01107 static Bool HandleConnDeny(SocketAddr *origin, NetBuffer *buff, Uint8 *unused,
01108 Uint16 noid) {
01109
01110 if ((networkState == NETSTATE_CONNECTING) && (buff->length == 5) &&
01111 ValidateServer(origin)) {
01112
01113 networkState = NETSTATE_SRVDENY;
01114 }
01115 return FALSE;
01116 }
01117
01136 static Bool HandleConnAccept(SocketAddr *origin, NetBuffer *buff, Uint8 *unused,
01137 Uint16 noid) {
01138 Uint32 randId;
01139 Uint8 cid;
01140
01141
01142 if ((networkState == NETSTATE_INIT) || (networkState >= NETSTATE_RCVCFG) ||
01143
01144 (buff->length != 8)) {
01145
01146 return FALSE;
01147 }
01148
01149 cid = buff->data[3];
01150 #if (MAX_PLAYERS < 256)
01151
01152 if (cid >= MAX_PLAYERS) {
01153
01154 return FALSE;
01155 }
01156 #endif
01157
01158 MSG_READ_32C(buff->data, 4,randId);
01159
01160 if (clientRandId == randId) {
01161 int bcast = 0;
01162
01163 localPlayer = cid;
01164
01165 networkState = NETSTATE_RCVCFG;
01166
01167 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&bcast,
01168 sizeof(int));
01169
01170 outgoingAddr = *origin;
01171
01172 return TRUE;
01173 }
01174
01175 return FALSE;
01176 }
01177
01178 extern int timeSyncState;
01179
01180 void MsgFailDropConnection(MsgDescr *descr, ClientData *client) {
01181
01182 if ((networkState == NETSTATE_RCVCFG) ||
01183 (networkState == NETSTATE_CLIENT) || (networkState == NETSTATE_CLIDISCONN)) {
01184
01185 CloseSocket(sock);
01186 #ifndef NDEBUG
01187 if (networkState < NETSTATE_CLIDISCONN) {
01188 #ifndef NDEBUG
01189 #ifdef USE_GETTEXT
01190 wprintf(L"Lost connection to the server\n");
01191 #else
01192 printf("Lost connection to the server\n");
01193 #endif
01194 #endif
01195 }
01196 #endif
01197 networkState = timeSyncState = NETSTATE_INIT;
01198 }
01199
01200 if (networkState == NETSTATE_SERVER) {
01201
01202
01203 if ((descr->buffer->length == 4) &&
01204 (descr->buffer->data[0] == MSG_TYPE_CONN_DISCONN) &&
01205 (descr->buffer->data[3] == client->cid)) {
01206
01207 client->flags = 0;
01208 players[client->cid].flags = 0;
01209
01210 RemoveFromConfigList(client);
01211 #ifndef NDEBUG
01212 #ifdef USE_GETTEXT
01213 wprintf(L"Client #%d disconnected and stopped responding\n",
01214 client->cid);
01215 #else
01216 printf("Client #%d disconnected and stopped responding\n",
01217 client->cid);
01218 #endif
01219 #endif
01220 }
01221
01222 else {
01223 #ifndef NDEBUG
01224 #ifdef USE_GETTEXT
01225 wprintf(L"Client #%d did not respond to a disconnect message\n",
01226 client->cid);
01227 #else
01228 printf("Client #%d did not respond to a disconnect message\n",
01229 client->cid);
01230 #endif
01231 #endif
01232
01233 SendDisconnectMessage(client->cid);
01234
01235 RemoveFromConfigList(client);
01236 }
01237 }
01238
01239
01240
01241
01242 }
01243
01244 void MsgFailDisconnect(MsgDescr *descr, ClientData *client) {
01245
01246 if ((networkState == NETSTATE_RCVCFG) ||
01247 (networkState == NETSTATE_CLIENT)) {
01248 #ifndef NDEBUG
01249 #ifdef USE_GETTEXT
01250 wprintf(L"The server stopped responding\n");
01251 #else
01252 printf("The server stopped responding\n");
01253 #endif
01254 #endif
01255
01256 SendDisconnectMessage(localPlayer);
01257 networkState = NETSTATE_CLIDISCONN;
01258 }
01259 else if (networkState == NETSTATE_SERVER) {
01260 #ifndef NDEBUG
01261 #ifdef USE_GETTEXT
01262 wprintf(L"Client #%d stopped responding; no ack to message %d\n",
01263 client->cid, descr->msgId);
01264 #else
01265 printf("Client #%d stopped responding; no ack to message %d\n",
01266 client->cid, descr->msgId);
01267 #endif
01268 #endif
01269
01270 RemovePlayer(&players[client->cid]);
01271 client->active = FALSE;
01272
01273 client->disconn = TRUE;
01274 client->disconnTime = SDL_GetTicks();
01275 assert(client->contact == TRUE);
01276
01277 RemoveFromConfigList(client);
01278
01279 SendDisconnectMessage(client->cid);
01280 }
01281 }
01282
01296 static Bool HandleConnDisconn(SocketAddr *origin, NetBuffer *buff,
01297 Uint8 *clientId, Uint16 noid) {
01298
01299 if (((networkState == NETSTATE_RCVCFG) || (networkState == NETSTATE_CLIENT))
01300 && ValidateServer(origin)) {
01301
01302 if (buff->data[3] == 0) {
01303 #ifndef NDEBUG
01304 #ifdef USE_GETTEXT
01305 wprintf(L"Server disconnected\n");
01306 #else
01307 printf("Server disconnected\n");
01308 #endif
01309 #endif
01310
01311 networkState = NETSTATE_DISCONN;
01312
01313 return TRUE;
01314 }
01315
01316 if (buff->data[3] == localPlayer) {
01317 #ifndef NDEBUG
01318 #ifdef USE_GETTEXT
01319 wprintf(L"Server terminated connection\n");
01320 #else
01321 printf("Server terminated connection\n");
01322 #endif
01323 #endif
01324
01325 networkState++;
01326
01327 return TRUE;
01328 }
01329 #if (MAX_PLAYERS < 256)
01330
01331 if (buff->data[3] >= MAX_PLAYERS) return FALSE;
01332 #endif
01333
01334 RemovePlayer(&players[buff->data[3]]);
01335
01336 return TRUE;
01337 }
01338
01339 if ((networkState == NETSTATE_SERVER) &&
01340 ValidateClient(origin, buff->data[3])) {
01341
01342 RemovePlayer(&players[buff->data[3]]);
01343 clients[buff->data[3]].active = FALSE;
01344
01345 clients[buff->data[3]].disconn = TRUE;
01346 clients[buff->data[3]].disconnTime = SDL_GetTicks();
01347 assert(clients[buff->data[3]].contact == TRUE);
01348
01349 *clientId = buff->data[3];
01350
01351 RemoveFromConfigList(&clients[buff->data[3]]);
01352 #ifndef NDEBUG
01353 #ifdef USE_GETTEXT
01354 wprintf(L"Client #%d disconnected\n", buff->data[3]);
01355 #else
01356 printf("Client #%d disconnected\n", buff->data[3]);
01357 #endif
01358 #endif
01359
01360 SendDisconnectMessage(buff->data[3]);
01361
01362 return TRUE;
01363 }
01364 return FALSE;
01365 }
01366
01367 Bool SendDisconnectMessage(Uint8 id) {
01368 MsgDescr *msg;
01369
01370
01371 if ((msg = MessageNew()) == NULL) {
01372
01373 return FALSE;
01374 }
01375
01376 if ((msg->buffer = BufferNew()) == NULL) {
01377
01378 MessageFree(msg);
01379 return FALSE;
01380 }
01381
01382 msg->approveFunc = NULL;
01383 msg->ackFunc = NULL;
01384 msg->failFunc = MsgFailDropConnection;
01385 msg->buffer->length = 4;
01386
01387 msg->triesLeft = INIT_TRIES << 1;
01388
01389 msg->buffer->data[0] = MSG_TYPE_CONN_DISCONN;
01390 msg->buffer->data[3] = id;
01391 msg->bcast = TRUE;
01392
01393 if (networkState == NETSTATE_SERVER) {
01394
01395
01396 SetDestToAll(msg);
01397 }
01398 else {
01399
01400 msg->destMap[0] = 1;
01401 #ifndef NDEBUG
01402 #ifdef USE_GETTEXT
01403 wprintf(L"Disconnecting from server\n");
01404 #else
01405 printf("Disconnecting from server\n");
01406 #endif
01407 #endif
01408 }
01409
01410 return AddMessage(msg);
01411 }
01412
01417 static const HandleMsg messageHandlers[MSG_TYPE_MAX] = {
01418 HandleAck,
01419 HandleConnReq,
01420 HandleConnDeny,
01421 HandleConnAccept,
01422 HandleConnDisconn,
01423 HandleGameOption,
01424 HandleObstacle,
01425 HandleArea,
01426 HandleArea,
01427
01428
01429 HandleScoreUpdate,
01430 HandlePlayerUpdate,
01431 HandlePlayerSpawn
01432 };
01433
01438 #define MSG_MAX_ACK 15
01439
01444 #define MSG_ACK_SIZE ((MSG_MAX_ACK + 1) << 1)
01445
01450 static NetBuffer inbuff;
01451
01458 static Uint8 *ackbuff = NULL;
01459
01467 static void SendAck(Uint8 *ack) {
01468 SocketAddr *dest;
01469
01470 if (networkState == NETSTATE_SERVER) {
01471 dest = &(clients[ack[1]].addr);
01472 }
01473 else {
01474 dest = &outgoingAddr;
01475 }
01476
01477 ack[0] = MSG_TYPE_ACK;
01478 ack[1] = localPlayer;
01479
01480 sendto(sock, ack, (ack[2] << 1) + 3, 0, &(dest->addr), dest->length);
01481
01482 ack[2] = 0;
01483 }
01484
01485 Bool ReceiveMessages() {
01486 Uint8 *ack = ackbuff;
01487 SocketAddr origin;
01488 int error = 0;
01489 Uint16 msgId;
01490 Uint8 list[rounddivup(MAX_PLAYERS, 8)] = { 0 };
01491 Uint8 msgType, clientId = 0;
01492
01493 assert(networkState <= NETSTATE_SRVDISCONN);
01494
01495 while ((origin.length = sizeof(struct sockaddr_in6),
01496
01497 (inbuff.length = recvfrom(sock, inbuff.data, MSG_MAX_SIZE, 0, &origin.addr,
01498 &origin.length)) > 0) || ((error = GetNetErrorVal()) == ECONNREFUSED)) {
01499
01500 if (error == ECONNREFUSED) {
01501
01502 error = 0;
01503
01504 continue;
01505 }
01506
01507 msgType = inbuff.data[0];
01508
01509 if (msgType < MSG_TYPE_MAX) {
01510 assert(messageHandlers[msgType] != NULL);
01511
01512 if (msgType >= MSG_TYPE_CONN_ACCEPT) {
01513
01514 MSG_READ_16C(inbuff.data, 1, msgId);
01515 }
01516
01517 if ((*(messageHandlers[msgType]))(&origin, &inbuff, &clientId,
01518 msgId)) {
01519
01520 if (networkState == NETSTATE_SERVER) {
01521
01522 assert(clientId < MAX_PLAYERS);
01523
01524 ack = &(ackbuff[clientId * MSG_ACK_SIZE]);
01525 }
01526
01527 assert((networkState != NETSTATE_CLIENT) || (clientId == 0));
01528
01529 MSG_WRITE_16C(ack, 3 + (ack[2] << 1), msgId);
01530
01531 ack[1] = clientId;
01532
01533 if (++ack[2] == MSG_MAX_ACK) {
01534
01535 SendAck(ack);
01536
01537 list[clientId >> 3] &= ~(1 << (clientId & 7));
01538 }
01539 else {
01540
01541 list[clientId >> 3] |= 1 << (clientId & 7);
01542 }
01543 }
01544 #ifdef MSG_DEBUG
01545 else if (msgType >= MSG_TYPE_CONN_ACCEPT) {
01546 printf("Not ack'ing message #%i, type %i\n", msgId, msgType);
01547 }
01548 #endif
01549 }
01550
01551 #ifdef MSG_DEBUG
01552 else {
01553 printf("Got bad message type\n");
01554 }
01555 #endif
01556 }
01557
01558 if (networkState == NETSTATE_SERVER) {
01559 int byteLoop = 0, bitLoop;
01560 clientId = 0;
01561
01562 for (byteLoop = 0; byteLoop < rounddivup(MAX_PLAYERS, 8); byteLoop++) {
01563
01564 if (list[byteLoop] == 0) {
01565
01566 clientId += 8;
01567
01568 continue;
01569 }
01570
01571 for (bitLoop = 0; list[byteLoop] && (bitLoop < 8);
01572 bitLoop++, list[byteLoop] >>= 1, clientId++) {
01573
01574 if (list[byteLoop] & 1) {
01575
01576 SendAck(&(ackbuff[clientId * MSG_ACK_SIZE]));
01577 }
01578 }
01579 }
01580 }
01581
01582 else if (ack[2]) {
01583
01584 SendAck(ack);
01585 }
01586
01587 if ((error > 0) && (error != EWOULDBLOCK)) {
01588 #ifndef NDEBUG
01589
01590 #ifdef USE_GETTEXT
01591 printf("Error while trying to recive data:\n\t%ls\n",
01592 GetNetErrorString(error));
01593 #else
01594 printf("Error while trying to recive data:\n\t%s\n",
01595 GetNetErrorString(error));
01596 #endif
01597 #endif
01598 return FALSE;
01599 }
01600 return TRUE;
01601 }
01602
01603 Bool MessageInit() {
01604 int loop;
01605
01606 available.destructOp = inflightTime.destructOp = NULL;
01607 buffers.destructOp = GenericPointerFree;
01608 inflightTime.lessOp = (LessThanOp)TimeCompare;
01609 available.itemSize = inflightTime.itemSize =
01610 buffers.itemSize = sizeof(void *);
01611 available.minSize = inflightTime.minSize = MIN_POINTERS;
01612 buffers.minSize = MIN_POINTERS >> 1;
01613
01614 if (!VectorInit(&inflightTime, MIN_POINTERS))
01615 return FALSE;
01616
01617 if (!VectorInit(&available, MIN_POINTERS))
01618 return FALSE;
01619
01620 if (!VectorInit(&buffers, MIN_POINTERS >> 1))
01621 return FALSE;
01622
01623 for (loop = INIT_BUFFERS; loop > 0; loop--) {
01624 char **buff = VectorAdd(&buffers);
01625 if ((*buff = malloc(sizeof(NetBuffer))) == NULL) {
01626 return FALSE;
01627 }
01628 }
01629
01630 for (loop = INIT_MESSAGES; loop > 0; loop--) {
01631 MsgDescr **msg = VectorAdd(&available);
01632 if ((*msg = malloc(sizeof(MsgDescr))) == NULL) {
01633 return FALSE;
01634 }
01635
01636 (*msg)->flags = 0;
01637
01638 (*msg)->buffer = NULL;
01639 }
01640
01641 if ((ackbuff = calloc(1, MSG_ACK_SIZE)) == NULL) {
01642 return FALSE;
01643 }
01644 return TRUE;
01645 }
01646
01647 void MessageUninit() {
01648
01649 available.destructOp = inflightTime.destructOp =
01650 (DestructorOp)MsgDescrDestructor;
01651
01652 if (inflightId != AA_ROOT_NODE) {
01653
01654 AATreeDestroy(inflightId);
01655
01656 inflightId = AA_ROOT_NODE;
01657 }
01658 VectorDestroy(&available);
01659 VectorDestroy(&inflightTime);
01660
01661 VectorDestroy(&buffers);
01662 free(ackbuff);
01663 }
01664
01672 Bool MessageCliToSrv() {
01673 Uint8 *buff;
01674
01675 if ((buff = realloc(ackbuff, MSG_ACK_SIZE * MAX_PLAYERS)) == NULL) {
01676 return FALSE;
01677 }
01678
01679 memset(ackbuff = buff, 0, MSG_ACK_SIZE * MAX_PLAYERS);
01680
01681 CancelAllMessages();
01682 return TRUE;
01683 }
01684
01691 Bool MessageSrvToCli() {
01692 Uint8 *buff;
01693
01694
01695 if ((buff = realloc(ackbuff, MSG_ACK_SIZE)) == NULL) {
01696 return FALSE;
01697 }
01698
01699 memset(ackbuff = buff, 0, MSG_ACK_SIZE);
01700
01701 CancelAllMessages();
01702
01703 gameOpts.totalMsgs = -1;
01704 gameOpts.rcvdMsgs = 0;
01705 return TRUE;
01706 }
01707
01708 void ProcessNetworkMessages() {
01709
01710 if ((networkState >= NETSTATE_RCVCFG) &&
01711 (networkState <= NETSTATE_SERVER)) {
01712
01713 ReceiveMessages();
01714
01715 UpdatePlayers(frameTime);
01716 if (networkState == NETSTATE_SERVER) {
01717
01718 ServiceGameConfig();
01719 }
01720
01721 ServiceMessages();
01722 }
01723 }
01724