From 5413b485c681912443b76707941b9665d713fec3 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sun, 11 May 2008 16:53:16 +0000 Subject: [PATCH] Started work on the client side timeouts --- command.cc | 2 +- playerliveradio.cc | 1 + playerlivetv.cc | 1 + vdr.cc | 86 ++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/command.cc b/command.cc index 16fa00a..a2b1968 100644 --- a/command.cc +++ b/command.cc @@ -569,7 +569,7 @@ void Command::connectionLost() Message* m = new Message(); // break into master mutex m->message = Message::CONNECTION_LOST; m->to = this; - postMessageNoLock(m); + postMessageFromOuterSpace(m); } void Command::buildCrashedBox() diff --git a/playerliveradio.cc b/playerliveradio.cc index 5e798ae..e4a5f38 100644 --- a/playerliveradio.cc +++ b/playerliveradio.cc @@ -153,6 +153,7 @@ void PlayerLiveRadio::streamReceive(ULONG flag, void* data, ULONG len) // Flag: // 0 = normal stream packet // 1 = stream end + // 2 = connection lost if (flag == 1) { diff --git a/playerlivetv.cc b/playerlivetv.cc index d0591ea..6295ee9 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -215,6 +215,7 @@ void PlayerLiveTV::streamReceive(ULONG flag, void* data, ULONG len) // Flag: // 0 = normal stream packet // 1 = stream end + // 2 = connection lost // logger->log("PlayerLiveTV", Log::DEBUG, "Received a streamchunk from VDR, flag = %lu", flag); diff --git a/vdr.cc b/vdr.cc index cbab39b..c228fd8 100644 --- a/vdr.cc +++ b/vdr.cc @@ -30,6 +30,7 @@ #include "wol.h" #include "vdrrequestpacket.h" #include "vdrresponsepacket.h" +#include "command.h" VDR* VDR::instance = NULL; @@ -182,7 +183,7 @@ void VDR::setReceiveWindow(size_t size) void VDR::threadMethod() { - threadSetKillable(); + threadSetKillable(); // FIXME - change this to deal with the EDRs ULONG channelID; @@ -195,21 +196,86 @@ void VDR::threadMethod() VDR_ResponsePacket* vresp; + int timeoutCount = 0; + while(1) { - if (!tcp->readData((UCHAR*)&channelID, sizeof(ULONG))) + if (!tcp->readData((UCHAR*)&channelID, sizeof(ULONG))) // 2s timeout atm { + ++timeoutCount; + // Error or timeout. - logger->log("VDR", Log::DEBUG, "Net read timeout"); - - // Do timeouts - //edLock(); - //for(EDRL::iterator i = receivers.begin(); i != receivers.end(); i++) - //{ - - + + // Thsi is the simple version of timeout system until I work out how to make it better + // e.g. different timeout lengths for different requests, a decent keepalive system + // running in parallel etc etc. + + logger->log("VDR", Log::DEBUG, "Net read timeout %i", timeoutCount); + + if (!tcp->isConnected())// FIXME disabled for now until it works ... !! || (timeoutCount > 10)) // 20s + { + // timeout, kill it + + connected = false; // though actually it could still be connected until someone calls vdr->disconnect + + // Need to wake up any waiting channel 1 request-response threads + // Normally this is done by a packet coming in with channelid and requestid + // Instead, go through the list and for each channel 1 edr, make an empty vresp + // An empty vresp will have userData == NULL, which means vresp->noResponse() == true + + // If it's a stream receiver, generate a stream packet with flag == connection_lost + + edLock(); + VDR_PacketReceiver* vdrpr; + while(receivers.size()) + { + vdrpr = (VDR_PacketReceiver*) *(receivers.begin()); + if (vdrpr->receiverChannel == CHANNEL_REQUEST_RESPONSE) + { + vresp = new VDR_ResponsePacket(); + vresp->setResponse(vdrpr->requestSerialNumber, NULL, 0); + logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for request serial %lu", vdrpr->requestSerialNumber); + edUnlock(); + if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) + { + // If edFindAndCall returns true, edr was called and vresp was handed off. + // else, delete vresp here. + logger->log("VDR", Log::ERR, "Timeouts: no waiting thread found for request serial %lu !!!", vdrpr->requestSerialNumber); + delete vresp; + } + edLock(); + } + else if (vdrpr->receiverChannel == CHANNEL_STREAM) + { + vresp->setStream(vdrpr->streamID, 2 /* connection-lost flag */ , NULL, 0); + logger->log("VDR", Log::DEBUG, "Timeouts: created blank response packet for streamid %lu", vdrpr->streamID); + edUnlock(); + if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) + { + // If edFindAndCall returns true, edr was called and vresp was handed off. + // else, delete vresp here. + logger->log("VDR", Log::ERR, "Timeouts: no waiting stream receiver found for streamid %lu !!!", vdrpr->streamID); + delete vresp; + } + edLock(); + } + } + edUnlock(); + // Ok, all event receviers should be dealt with. just in case there weren't any, inform command + + Command::getInstance()->connectionLost(); + + // return and stop this thread + return; + } + continue; } + + // Data was read + + timeoutCount = 0; + channelID = ntohl(channelID); vresp = new VDR_ResponsePacket(); -- 2.39.2