Uploading scores is working now. Add timeouts for reads and the close operation so we don't end up stuck in any one state forever. Improve the error handling and provide an error code for debugging purposes if there is a problem.

This commit is contained in:
Jeremy Rand 2021-06-05 23:34:30 -04:00
parent 2c511fe33a
commit abe5f0c72b
3 changed files with 156 additions and 82 deletions

View File

@ -246,6 +246,7 @@ startGame_singlePlayer anop
jsl spiderInitGame jsl spiderInitGame
jsl levelInit jsl levelInit
jsl soundInit jsl soundInit
jsl disconnectNetwork
; Fall through intentionally here... ; Fall through intentionally here...
startLevel entry startLevel entry
jsl segmentsInitLevel jsl segmentsInitLevel

View File

@ -13,6 +13,7 @@
#include <tcpip.h> #include <tcpip.h>
#include <types.h> #include <types.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "game.h" #include "game.h"
@ -30,8 +31,8 @@
#define RESPONSE_TYPE_STATUS 2 #define RESPONSE_TYPE_STATUS 2
#define GLOBAL_SCORE_REFRESH_TIME (15 * 60 * 60) #define GLOBAL_SCORE_REFRESH_TIME (15 * 60 * 60)
#define SET_SCORE_TIMEOUT (20 * 60) #define SHUTDOWN_NETWORK_TIMEOUT (2 * 60)
#define SHUTDOWN_NETWORK_TIMEOUT (60 / 2) #define READ_NETWORK_TIMEOUT (5 * 60)
// Types // Types
@ -85,6 +86,20 @@ typedef struct tStatusResponse {
} tStatusResponse; } tStatusResponse;
typedef enum tProtocolErrors {
HELLO_TIMEOUT_ERROR = 1,
HELLO_TOO_BIG_ERROR,
HELLO_UNEXPECTED_RESPONSE_ERROR,
HIGH_SCORE_TIMEOUT_ERROR,
HIGH_SCORE_TOO_BIG_ERROR,
HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR,
SET_SCORE_TIMEOUT_ERROR,
SET_SCORE_TOO_BIG_ERROR,
SET_SCORE_UNEXPECTED_RESPONSE_ERROR,
SET_SCORE_FAILED_ERROR,
} tProtocolErrors;
typedef enum tGameNetworkState { typedef enum tGameNetworkState {
GAME_NETWORK_CONNECT_FAILED = 0, GAME_NETWORK_CONNECT_FAILED = 0,
GAME_NETWORK_UNCONNECTED, GAME_NETWORK_UNCONNECTED,
@ -119,6 +134,7 @@ typedef enum tGameNetworkState {
GAME_NETWORK_CLOSING_TCP, GAME_NETWORK_CLOSING_TCP,
} tGameNetworkState; } tGameNetworkState;
typedef struct tGameNetworkGlobals { typedef struct tGameNetworkGlobals {
Boolean networkStartedConnected; Boolean networkStartedConnected;
tGameNetworkState gameNetworkState; tGameNetworkState gameNetworkState;
@ -133,6 +149,8 @@ typedef struct tGameNetworkGlobals {
tHighScoreRequestWithHash highScoreRequest; tHighScoreRequestWithHash highScoreRequest;
Boolean hasHighScoreToSend; Boolean hasHighScoreToSend;
tStatusResponse setHighScoreResponse; tStatusResponse setHighScoreResponse;
uint16_t errorCode;
uint16_t timeout;
} tGameNetworkGlobals; } tGameNetworkGlobals;
@ -217,34 +235,6 @@ void initNetwork(void)
void shutdownNetwork(void) void shutdownNetwork(void)
{ {
if (networkGlobals == NULL)
return;
if (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
int timeout = SHUTDOWN_NETWORK_TIMEOUT;
TCPIPCloseTCP(networkGlobals->ipid);
while (timeout > 0) {
waitForVbl();
TCPIPPoll();
if (TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus)) != tcperrOK) {
timeout = 0;
break;
}
if (networkGlobals->tcpStatus.srState == TCPSCLOSED)
break;
timeout--;
}
if (timeout == 0) {
TCPIPAbortTCP(networkGlobals->ipid);
}
TCPIPLogout(networkGlobals->ipid);
}
if ((!networkGlobals->networkStartedConnected) && if ((!networkGlobals->networkStartedConnected) &&
(networkGlobals->gameNetworkState > GAME_NETWORK_UNCONNECTED)) { (networkGlobals->gameNetworkState > GAME_NETWORK_UNCONNECTED)) {
TCPIPDisconnect(TRUE, NULL); TCPIPDisconnect(TRUE, NULL);
@ -259,6 +249,46 @@ void shutdownNetwork(void)
} }
static void abortConnection(void)
{
TCPIPAbortTCP(networkGlobals->ipid);
TCPIPLogout(networkGlobals->ipid);
}
void disconnectNetwork(void)
{
if (networkGlobals == NULL)
return;
if (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
if (networkGlobals->gameNetworkState < GAME_NETWORK_CLOSING_TCP) {
TCPIPCloseTCP(networkGlobals->ipid);
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
}
while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
waitForVbl();
pollNetwork();
}
}
}
static char hexDigitToAscii(Word digit)
{
digit &= 0xf;
if (digit < 10)
return '0' + digit;
if (digit > 15)
return 'X';
return 'A' + digit - 10;
}
static void displayString(Word row, char * string) static void displayString(Word row, char * string)
{ {
strcpy(&(highScoreResponse.highScores[row].scoreText[2]), string); strcpy(&(highScoreResponse.highScores[row].scoreText[2]), string);
@ -290,6 +320,17 @@ static void displayNetworkError(char * line1, char * line2)
displayString(4, line1); displayString(4, line1);
displayString(5, line2); displayString(5, line2);
highScoreResponse.highScores[7].scoreText[0] = 'C';
highScoreResponse.highScores[7].scoreText[1] = 'O';
highScoreResponse.highScores[7].scoreText[2] = 'D';
highScoreResponse.highScores[7].scoreText[3] = 'E';
highScoreResponse.highScores[7].scoreText[4] = ':';
highScoreResponse.highScores[7].scoreText[5] = ' ';
highScoreResponse.highScores[7].scoreText[6] = hexDigitToAscii(networkGlobals->errorCode >> 12);
highScoreResponse.highScores[7].scoreText[7] = hexDigitToAscii(networkGlobals->errorCode >> 8);
highScoreResponse.highScores[7].scoreText[8] = hexDigitToAscii(networkGlobals->errorCode >> 4);
highScoreResponse.highScores[7].scoreText[9] = hexDigitToAscii(networkGlobals->errorCode);
globalScoreAge = 0; globalScoreAge = 0;
hasGlobalHighScores = TRUE; hasGlobalHighScores = TRUE;
} }
@ -316,10 +357,8 @@ void pollNetwork(void)
break; break;
case GAME_NETWORK_PROTOCOL_FAILED: case GAME_NETWORK_PROTOCOL_FAILED:
TCPIPCloseTCP(networkGlobals->ipid); abortConnection();
displayNetworkError("PROTOCOL", "FAILED"); displayNetworkError("PROTOCOL", "FAILED");
globalScoreAge = GLOBAL_SCORE_REFRESH_TIME;
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
break; break;
case GAME_NETWORK_FAILURE: case GAME_NETWORK_FAILURE:
@ -339,9 +378,10 @@ void pollNetwork(void)
case GAME_NETWORK_CONNECTED: case GAME_NETWORK_CONNECTED:
TCPIPDNRNameToIP("\p" NETWORK_SERVER, &(networkGlobals->domainNameResolution)); TCPIPDNRNameToIP("\p" NETWORK_SERVER, &(networkGlobals->domainNameResolution));
if (toolerror()) if (toolerror()) {
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
else networkGlobals->errorCode = toolerror();
} else
networkGlobals->gameNetworkState = GAME_NETWORK_RESOLVING_NAME; networkGlobals->gameNetworkState = GAME_NETWORK_RESOLVING_NAME;
break; break;
@ -351,6 +391,7 @@ void pollNetwork(void)
if (networkGlobals->domainNameResolution.DNRstatus != DNR_OK) { if (networkGlobals->domainNameResolution.DNRstatus != DNR_OK) {
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
networkGlobals->errorCode = networkGlobals->domainNameResolution.DNRstatus;
break; break;
} }
@ -366,10 +407,12 @@ void pollNetwork(void)
networkGlobals->ipid = TCPIPLogin(myUserId, networkGlobals->domainNameResolution.DNRIPaddress, NETWORK_SERVERPORT, 0, 64); networkGlobals->ipid = TCPIPLogin(myUserId, networkGlobals->domainNameResolution.DNRIPaddress, NETWORK_SERVERPORT, 0, 64);
if (toolerror()) { if (toolerror()) {
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
networkGlobals->errorCode = toolerror();
break; break;
} }
if (TCPIPOpenTCP(networkGlobals->ipid) != tcperrOK) { networkGlobals->errorCode = TCPIPOpenTCP(networkGlobals->ipid);
if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); TCPIPLogout(networkGlobals->ipid);
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
@ -378,9 +421,9 @@ void pollNetwork(void)
break; break;
case GAME_NETWORK_WAITING_FOR_TCP: case GAME_NETWORK_WAITING_FOR_TCP:
if (TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus)) != tcperrOK) { networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
@ -389,38 +432,48 @@ void pollNetwork(void)
break; break;
if (networkGlobals->tcpStatus.srState != TCPSESTABLISHED) { if (networkGlobals->tcpStatus.srState != TCPSESTABLISHED) {
TCPIPAbortTCP(networkGlobals->ipid); abortConnection();
TCPIPLogout(networkGlobals->ipid); networkGlobals->errorCode = networkGlobals->tcpStatus.srState | 0x8000;
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_HELLO; networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_HELLO;
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
networkGlobals->bytesRead = 0; networkGlobals->bytesRead = 0;
break; break;
case GAME_NETWORK_WAITING_FOR_HELLO: case GAME_NETWORK_WAITING_FOR_HELLO:
if (TCPIPReadTCP(networkGlobals->ipid, 0, networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
((uint32_t)(&(networkGlobals->helloResponse))) + networkGlobals->bytesRead, ((uint32_t)(&(networkGlobals->helloResponse))) + networkGlobals->bytesRead,
sizeof(networkGlobals->helloResponse) - networkGlobals->bytesRead, sizeof(networkGlobals->helloResponse) - networkGlobals->bytesRead,
&(networkGlobals->readResponseBuf)) != tcperrOK) { &(networkGlobals->readResponseBuf));
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount; networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
if (networkGlobals->bytesRead < sizeof(networkGlobals->helloResponse)) if (networkGlobals->bytesRead < sizeof(networkGlobals->helloResponse)) {
if (networkGlobals->timeout > 0) {
networkGlobals->timeout--;
} else {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HELLO_TIMEOUT_ERROR;
}
break; break;
}
if (networkGlobals->bytesRead > sizeof(networkGlobals->helloResponse)) { if (networkGlobals->bytesRead > sizeof(networkGlobals->helloResponse)) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HELLO_TOO_BIG_ERROR;
break; break;
} }
if (networkGlobals->helloResponse.responseType != RESPONSE_TYPE_HELLO) { if (networkGlobals->helloResponse.responseType != RESPONSE_TYPE_HELLO) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HELLO_UNEXPECTED_RESPONSE_ERROR;
break; break;
} }
@ -431,7 +484,9 @@ void pollNetwork(void)
(globalScoreAge == 0)) { (globalScoreAge == 0)) {
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES; networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
} else { } else {
TCPIPCloseTCP(networkGlobals->ipid);
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP; networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
} }
break; break;
@ -443,39 +498,49 @@ void pollNetwork(void)
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.highScoreRequest), sizeof(networkGlobals->highScoreRequest.highScoreRequest)); md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.highScoreRequest), sizeof(networkGlobals->highScoreRequest.highScoreRequest));
md5Finish(&(networkGlobals->hashWorkBlock), &(networkGlobals->highScoreRequest.md5Digest[0])); md5Finish(&(networkGlobals->hashWorkBlock), &(networkGlobals->highScoreRequest.md5Digest[0]));
if (TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->highScoreRequest), sizeof(networkGlobals->highScoreRequest), FALSE, FALSE) != tcperrOK) { networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->highScoreRequest), sizeof(networkGlobals->highScoreRequest), FALSE, FALSE);
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORES; networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORES;
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
networkGlobals->bytesRead = 0; networkGlobals->bytesRead = 0;
break; break;
case GAME_NETWORK_WAITING_FOR_SCORES: case GAME_NETWORK_WAITING_FOR_SCORES:
if (TCPIPReadTCP(networkGlobals->ipid, 0, networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
((uint32_t)(&highScoreResponse)) + networkGlobals->bytesRead, ((uint32_t)(&highScoreResponse)) + networkGlobals->bytesRead,
sizeof(highScoreResponse) - networkGlobals->bytesRead, sizeof(highScoreResponse) - networkGlobals->bytesRead,
&(networkGlobals->readResponseBuf)) != tcperrOK) { &(networkGlobals->readResponseBuf));
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount; networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
if (networkGlobals->bytesRead < sizeof(highScoreResponse)) if (networkGlobals->bytesRead < sizeof(highScoreResponse)) {
if (networkGlobals->timeout > 0) {
networkGlobals->timeout--;
} else {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HIGH_SCORE_TIMEOUT_ERROR;
}
break; break;
}
if (networkGlobals->bytesRead > sizeof(highScoreResponse)) { if (networkGlobals->bytesRead > sizeof(highScoreResponse)) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HIGH_SCORE_TOO_BIG_ERROR;
break; break;
} }
if (highScoreResponse.responseType != RESPONSE_TYPE_SCORES) { if (highScoreResponse.responseType != RESPONSE_TYPE_SCORES) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR;
break; break;
} }
@ -484,6 +549,7 @@ void pollNetwork(void)
TCPIPCloseTCP(networkGlobals->ipid); TCPIPCloseTCP(networkGlobals->ipid);
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP; networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
break; break;
case GAME_NETWORK_SET_HIGH_SCORE: case GAME_NETWORK_SET_HIGH_SCORE:
@ -495,44 +561,55 @@ void pollNetwork(void)
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(setHighScoreRequest.setHighScoreRequest), sizeof(setHighScoreRequest.setHighScoreRequest)); md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(setHighScoreRequest.setHighScoreRequest), sizeof(setHighScoreRequest.setHighScoreRequest));
md5Finish(&(networkGlobals->hashWorkBlock), &(setHighScoreRequest.md5Digest[0])); md5Finish(&(networkGlobals->hashWorkBlock), &(setHighScoreRequest.md5Digest[0]));
if (TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&setHighScoreRequest, sizeof(setHighScoreRequest), FALSE, FALSE) != tcperrOK) { networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&setHighScoreRequest, sizeof(setHighScoreRequest), FALSE, FALSE);
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORE_ACK; networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORE_ACK;
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
networkGlobals->bytesRead = 0; networkGlobals->bytesRead = 0;
break; break;
case GAME_NETWORK_WAITING_FOR_SCORE_ACK: case GAME_NETWORK_WAITING_FOR_SCORE_ACK:
if (TCPIPReadTCP(networkGlobals->ipid, 0, networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
((uint32_t)(&(networkGlobals->setHighScoreResponse))) + networkGlobals->bytesRead, ((uint32_t)(&(networkGlobals->setHighScoreResponse))) + networkGlobals->bytesRead,
sizeof(networkGlobals->setHighScoreResponse) - networkGlobals->bytesRead, sizeof(networkGlobals->setHighScoreResponse) - networkGlobals->bytesRead,
&(networkGlobals->readResponseBuf)) != tcperrOK) { &(networkGlobals->readResponseBuf));
TCPIPAbortTCP(networkGlobals->ipid); if (networkGlobals->errorCode != tcperrOK) {
TCPIPLogout(networkGlobals->ipid); abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
break; break;
} }
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount; networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
if (networkGlobals->bytesRead < sizeof(networkGlobals->setHighScoreResponse)) if (networkGlobals->bytesRead < sizeof(networkGlobals->setHighScoreResponse)) {
if (networkGlobals->timeout > 0) {
networkGlobals->timeout--;
} else {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = SET_SCORE_TIMEOUT_ERROR;
}
break; break;
}
if (networkGlobals->bytesRead > sizeof(networkGlobals->setHighScoreResponse)) { if (networkGlobals->bytesRead > sizeof(networkGlobals->setHighScoreResponse)) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = SET_SCORE_TOO_BIG_ERROR;
break; break;
} }
if (networkGlobals->setHighScoreResponse.responseType != RESPONSE_TYPE_STATUS) { if (networkGlobals->setHighScoreResponse.responseType != RESPONSE_TYPE_STATUS) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = SET_SCORE_UNEXPECTED_RESPONSE_ERROR;
break; break;
} }
if (!networkGlobals->setHighScoreResponse.success) { if (!networkGlobals->setHighScoreResponse.success) {
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED; networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
networkGlobals->errorCode = SET_SCORE_FAILED_ERROR;
break; break;
} }
@ -542,15 +619,17 @@ void pollNetwork(void)
break; break;
case GAME_NETWORK_CLOSING_TCP: case GAME_NETWORK_CLOSING_TCP:
if (TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus)) != tcperrOK) { networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
TCPIPAbortTCP(networkGlobals->ipid); if ((networkGlobals->tcpStatus.srState != TCPSCLOSED) &&
TCPIPLogout(networkGlobals->ipid); (networkGlobals->tcpStatus.srState != TCPSTIMEWAIT)) {
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR; if (networkGlobals->timeout > 0) {
networkGlobals->timeout--;
} else {
abortConnection();
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
}
break; break;
} }
if ((networkGlobals->tcpStatus.srState != TCPSCLOSED) &&
(networkGlobals->tcpStatus.srState != TCPSTIMEWAIT))
break;
TCPIPLogout(networkGlobals->ipid); TCPIPLogout(networkGlobals->ipid);
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED; networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
@ -561,8 +640,6 @@ void pollNetwork(void)
void sendHighScore(void) void sendHighScore(void)
{ {
int timeout = SET_SCORE_TIMEOUT;
if (networkGlobals == NULL) if (networkGlobals == NULL)
return; return;
@ -574,12 +651,7 @@ void sendHighScore(void)
do { do {
waitForVbl(); waitForVbl();
pollNetwork(); pollNetwork();
timeout--;
if (timeout == 0)
return;
// TODO - Provide some feedback that the score is being uploaded here. // TODO - Provide some feedback that the score is being uploaded here.
// TODO - If there is a timeout, or a failure of some kind, perhaps ask the user if they would like to retry. // TODO - If there is a timeout, or a failure of some kind, perhaps ask the user if they would like to retry.
} while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED); } while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED);
} }

View File

@ -20,6 +20,7 @@ typedef struct tHighScore
extern unsigned int myUserId; extern unsigned int myUserId;
extern void initNetwork(void); extern void initNetwork(void);
extern void disconnectNetwork(void);
extern void pollNetwork(void); extern void pollNetwork(void);
extern void shutdownNetwork(void); extern void shutdownNetwork(void);