Guarantee that only one connectionTerminated callback will ever happen

This commit is contained in:
Cameron Gutman 2014-10-21 01:14:12 -04:00
parent 39f6631201
commit c8814fad0b

View File

@ -2,7 +2,10 @@
#include "Platform.h" #include "Platform.h"
static int stage = STAGE_NONE; static int stage = STAGE_NONE;
static CONNECTION_LISTENER_CALLBACKS ListenerCallbacks; static CONNECTION_LISTENER_CALLBACKS listenerCallbacks;
static CONNECTION_LISTENER_CALLBACKS originalCallbacks;
static int alreadyTerminated = 0;
static const char* stageNames[STAGE_MAX] = { static const char* stageNames[STAGE_MAX] = {
"none", "none",
@ -87,136 +90,185 @@ void LiStopConnection(void) {
LC_ASSERT(stage == STAGE_NONE); LC_ASSERT(stage == STAGE_NONE);
} }
static void ClStageStarting(int stage)
{
originalCallbacks.stageStarting(stage);
}
static void ClStageComplete(int stage)
{
originalCallbacks.stageComplete(stage);
}
static void ClStageFailed(int stage, long errorCode)
{
originalCallbacks.stageFailed(stage, errorCode);
}
static void ClConnectionStarted(void)
{
originalCallbacks.connectionStarted();
}
static void ClConnectionTerminated(long errorCode)
{
// Avoid recursion and issuing multiple callbacks
if (alreadyTerminated) {
return;
}
alreadyTerminated = 1;
originalCallbacks.connectionTerminated(errorCode);
}
void ClDisplayMessage(char* message)
{
originalCallbacks.displayMessage(message);
}
void ClDisplayTransientMessage(char* message)
{
originalCallbacks.displayTransientMessage(message);
}
int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks, int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags) { PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags) {
int err; int err;
memcpy(&ListenerCallbacks, clCallbacks, sizeof(ListenerCallbacks)); memcpy(&originalCallbacks, clCallbacks, sizeof(originalCallbacks));
listenerCallbacks.stageStarting = ClStageStarting;
listenerCallbacks.stageComplete = ClStageComplete;
listenerCallbacks.stageFailed = ClStageFailed;
listenerCallbacks.connectionStarted = ClConnectionStarted;
listenerCallbacks.connectionTerminated = ClConnectionTerminated;
listenerCallbacks.displayMessage = ClDisplayMessage;
listenerCallbacks.displayTransientMessage = ClDisplayTransientMessage;
Limelog("Initializing platform..."); Limelog("Initializing platform...");
ListenerCallbacks.stageStarting(STAGE_PLATFORM_INIT); listenerCallbacks.stageStarting(STAGE_PLATFORM_INIT);
err = initializePlatformSockets(); err = initializePlatformSockets();
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err); listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
goto Cleanup; goto Cleanup;
} }
err = initializePlatformThreads(); err = initializePlatformThreads();
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err); listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_PLATFORM_INIT); LC_ASSERT(stage == STAGE_PLATFORM_INIT);
ListenerCallbacks.stageComplete(STAGE_PLATFORM_INIT); listenerCallbacks.stageComplete(STAGE_PLATFORM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Starting RTSP handshake..."); Limelog("Starting RTSP handshake...");
ListenerCallbacks.stageStarting(STAGE_RTSP_HANDSHAKE); listenerCallbacks.stageStarting(STAGE_RTSP_HANDSHAKE);
err = performRtspHandshake(host, streamConfig); err = performRtspHandshake(host, streamConfig);
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_RTSP_HANDSHAKE, err); listenerCallbacks.stageFailed(STAGE_RTSP_HANDSHAKE, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_RTSP_HANDSHAKE); LC_ASSERT(stage == STAGE_RTSP_HANDSHAKE);
ListenerCallbacks.stageComplete(STAGE_RTSP_HANDSHAKE); listenerCallbacks.stageComplete(STAGE_RTSP_HANDSHAKE);
Limelog("done\n"); Limelog("done\n");
Limelog("Initializing control stream..."); Limelog("Initializing control stream...");
ListenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_INIT); listenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_INIT);
err = initializeControlStream(host, streamConfig, &ListenerCallbacks); err = initializeControlStream(host, streamConfig, &listenerCallbacks);
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_INIT, err); listenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_INIT, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_CONTROL_STREAM_INIT); LC_ASSERT(stage == STAGE_CONTROL_STREAM_INIT);
ListenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_INIT); listenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Initializing video stream..."); Limelog("Initializing video stream...");
ListenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_INIT); listenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_INIT);
initializeVideoStream(host, streamConfig, drCallbacks, &ListenerCallbacks); initializeVideoStream(host, streamConfig, drCallbacks, &listenerCallbacks);
stage++; stage++;
LC_ASSERT(stage == STAGE_VIDEO_STREAM_INIT); LC_ASSERT(stage == STAGE_VIDEO_STREAM_INIT);
ListenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_INIT); listenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Initializing audio stream..."); Limelog("Initializing audio stream...");
ListenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_INIT); listenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_INIT);
initializeAudioStream(host, arCallbacks, &ListenerCallbacks); initializeAudioStream(host, arCallbacks, &listenerCallbacks);
stage++; stage++;
LC_ASSERT(stage == STAGE_AUDIO_STREAM_INIT); LC_ASSERT(stage == STAGE_AUDIO_STREAM_INIT);
ListenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_INIT); listenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Initializing input stream..."); Limelog("Initializing input stream...");
ListenerCallbacks.stageStarting(STAGE_INPUT_STREAM_INIT); listenerCallbacks.stageStarting(STAGE_INPUT_STREAM_INIT);
initializeInputStream(host, &ListenerCallbacks, initializeInputStream(host, &listenerCallbacks,
streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey), streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey),
streamConfig->remoteInputAesIv, sizeof(streamConfig->remoteInputAesIv)); streamConfig->remoteInputAesIv, sizeof(streamConfig->remoteInputAesIv));
stage++; stage++;
LC_ASSERT(stage == STAGE_INPUT_STREAM_INIT); LC_ASSERT(stage == STAGE_INPUT_STREAM_INIT);
ListenerCallbacks.stageComplete(STAGE_INPUT_STREAM_INIT); listenerCallbacks.stageComplete(STAGE_INPUT_STREAM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Starting control stream..."); Limelog("Starting control stream...");
ListenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_START); listenerCallbacks.stageStarting(STAGE_CONTROL_STREAM_START);
err = startControlStream(); err = startControlStream();
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_START, err); listenerCallbacks.stageFailed(STAGE_CONTROL_STREAM_START, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_CONTROL_STREAM_START); LC_ASSERT(stage == STAGE_CONTROL_STREAM_START);
ListenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_START); listenerCallbacks.stageComplete(STAGE_CONTROL_STREAM_START);
Limelog("done\n"); Limelog("done\n");
Limelog("Starting video stream..."); Limelog("Starting video stream...");
ListenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_START); listenerCallbacks.stageStarting(STAGE_VIDEO_STREAM_START);
err = startVideoStream(renderContext, drFlags); err = startVideoStream(renderContext, drFlags);
if (err != 0) { if (err != 0) {
Limelog("Video stream start failed: %d\n", err); Limelog("Video stream start failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_VIDEO_STREAM_START, err); listenerCallbacks.stageFailed(STAGE_VIDEO_STREAM_START, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_VIDEO_STREAM_START); LC_ASSERT(stage == STAGE_VIDEO_STREAM_START);
ListenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_START); listenerCallbacks.stageComplete(STAGE_VIDEO_STREAM_START);
Limelog("done\n"); Limelog("done\n");
Limelog("Starting audio stream..."); Limelog("Starting audio stream...");
ListenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_START); listenerCallbacks.stageStarting(STAGE_AUDIO_STREAM_START);
err = startAudioStream(); err = startAudioStream();
if (err != 0) { if (err != 0) {
Limelog("Audio stream start failed: %d\n", err); Limelog("Audio stream start failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_AUDIO_STREAM_START, err); listenerCallbacks.stageFailed(STAGE_AUDIO_STREAM_START, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_AUDIO_STREAM_START); LC_ASSERT(stage == STAGE_AUDIO_STREAM_START);
ListenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_START); listenerCallbacks.stageComplete(STAGE_AUDIO_STREAM_START);
Limelog("done\n"); Limelog("done\n");
Limelog("Starting input stream..."); Limelog("Starting input stream...");
ListenerCallbacks.stageStarting(STAGE_INPUT_STREAM_START); listenerCallbacks.stageStarting(STAGE_INPUT_STREAM_START);
err = startInputStream(); err = startInputStream();
if (err != 0) { if (err != 0) {
Limelog("Input stream start failed: %d\n", err); Limelog("Input stream start failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_INPUT_STREAM_START, err); listenerCallbacks.stageFailed(STAGE_INPUT_STREAM_START, err);
goto Cleanup; goto Cleanup;
} }
stage++; stage++;
LC_ASSERT(stage == STAGE_INPUT_STREAM_START); LC_ASSERT(stage == STAGE_INPUT_STREAM_START);
ListenerCallbacks.stageComplete(STAGE_INPUT_STREAM_START); listenerCallbacks.stageComplete(STAGE_INPUT_STREAM_START);
Limelog("done\n"); Limelog("done\n");
ListenerCallbacks.connectionStarted(); listenerCallbacks.connectionStarted();
Cleanup: Cleanup:
return err; return err;