Timout for network operations now configurable in streamdev-client setup

This commit is contained in:
Frank Schmirler 2012-03-03 23:24:30 +01:00
parent c1dc1453c5
commit 3da6ae734e
14 changed files with 132 additions and 122 deletions

View File

@ -1,6 +1,7 @@
VDR Plugin 'streamdev' Revision History VDR Plugin 'streamdev' Revision History
--------------------------------------- ---------------------------------------
- Timout for network operations now configurable in streamdev-client setup
- Added timeout to Connect() - Added timeout to Connect()
- Report the server-side HTTP status "503 Service unavailable" instead of - Report the server-side HTTP status "503 Service unavailable" instead of
the client-side error "409 Conflict" when a channel is unavailable the client-side error "409 Conflict" when a channel is unavailable

3
README
View File

@ -387,6 +387,9 @@ during an active transfer. This makes it possible to switch languages, receive
additional channels (for recording on the client) and use plugins that use additional channels (for recording on the client) and use plugins that use
receivers themselves (like osdteletext). receivers themselves (like osdteletext).
The default timeout of 2 seconds for network operations should be sufficient in
most cases. Increase "Timeout" if you get frequent timeout errors in the log.
With "Filter Streaming" enabled, the client will receive meta information like With "Filter Streaming" enabled, the client will receive meta information like
EPG data and service information, just as if the client had its own DVB card. EPG data and service information, just as if the client had its own DVB card.
Link channels and even a client-side EPG scan have been reported to work. Link channels and even a client-side EPG scan have been reported to work.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-02-16 08:49+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n" "Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
"Language-Team: German <vdr@linuxtv.org>\n" "Language-Team: German <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "IP der Gegenseite"
msgid "Remote Port" msgid "Remote Port"
msgstr "Port der Gegenseite" msgstr "Port der Gegenseite"
msgid "Timeout (s)"
msgstr "Timeout (s)"
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Filter-Daten streamen" msgstr "Filter-Daten streamen"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2010-06-19 03:58+0100\n" "PO-Revision-Date: 2010-06-19 03:58+0100\n"
"Last-Translator: Javier Bradineras <jbradi@hotmail.com>\n" "Last-Translator: Javier Bradineras <jbradi@hotmail.com>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n" "Language-Team: Spanish <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "Indicar IP del Servidor"
msgid "Remote Port" msgid "Remote Port"
msgstr "Indicar puerto remoto del Servidor" msgstr "Indicar puerto remoto del Servidor"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Filtrar transmisión" msgstr "Filtrar transmisión"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: Rolf Ahrenberg\n" "Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "Etäkoneen IP-osoite"
msgid "Remote Port" msgid "Remote Port"
msgstr "Etäkoneen portti" msgstr "Etäkoneen portti"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Suodatetun tiedon suoratoisto" msgstr "Suodatetun tiedon suoratoisto"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: micky979 <micky979@free.fr>\n" "Last-Translator: micky979 <micky979@free.fr>\n"
"Language-Team: French <vdr@linuxtv.org>\n" "Language-Team: French <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "Adresse IP du serveur"
msgid "Remote Port" msgid "Remote Port"
msgstr "Port du serveur" msgstr "Port du serveur"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Filtre streaming" msgstr "Filtre streaming"

View File

@ -9,7 +9,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2010-06-19 03:58+0100\n" "PO-Revision-Date: 2010-06-19 03:58+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian <vdr@linuxtv.org>\n" "Language-Team: Italian <vdr@linuxtv.org>\n"
@ -42,6 +42,9 @@ msgstr "Indirizzo IP del Server"
msgid "Remote Port" msgid "Remote Port"
msgstr "Porta Server Remoto" msgstr "Porta Server Remoto"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Filtra trasmissione" msgstr "Filtra trasmissione"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2009-11-26 21:57+0200\n" "PO-Revision-Date: 2009-11-26 21:57+0200\n"
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n" "Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
"Language-Team: Lithuanian <vdr@linuxtv.org>\n" "Language-Team: Lithuanian <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "Nuotolinis IP adresas"
msgid "Remote Port" msgid "Remote Port"
msgstr "Nuotolinis portas" msgstr "Nuotolinis portas"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "Filtruoti transliavimą" msgstr "Filtruoti transliavimą"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev 0.5.0\n" "Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: 2008-06-26 15:36+0100\n" "PO-Revision-Date: 2008-06-26 15:36+0100\n"
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n" "Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
"Language-Team: Russian <vdr@linuxtv.org>\n" "Language-Team: Russian <vdr@linuxtv.org>\n"
@ -40,6 +40,9 @@ msgstr "
msgid "Remote Port" msgid "Remote Port"
msgstr "ÃÔÐÛÕÝÝëÙ ßÞàâ" msgstr "ÃÔÐÛÕÝÝëÙ ßÞàâ"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "ÄØÛìâà ßÞâÞÚÐ" msgstr "ÄØÛìâà ßÞâÞÚÐ"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: streamdev_SK\n" "Project-Id-Version: streamdev_SK\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" "Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-11 10:48+0100\n" "POT-Creation-Date: 2012-03-03 23:12+0100\n"
"PO-Revision-Date: \n" "PO-Revision-Date: \n"
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n" "Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
"Language-Team: Slovak <hrala.milan@gmail.com>\n" "Language-Team: Slovak <hrala.milan@gmail.com>\n"
@ -42,6 +42,9 @@ msgstr "Vzdialen
msgid "Remote Port" msgid "Remote Port"
msgstr "Vzdialený port" msgstr "Vzdialený port"
msgid "Timeout (s)"
msgstr ""
msgid "Filter Streaming" msgid "Filter Streaming"
msgstr "filtrova» prúdy" msgstr "filtrova» prúdy"

View File

@ -12,6 +12,7 @@ cStreamdevClientSetup StreamdevClientSetup;
cStreamdevClientSetup::cStreamdevClientSetup(void) { cStreamdevClientSetup::cStreamdevClientSetup(void) {
StartClient = false; StartClient = false;
RemotePort = 2004; RemotePort = 2004;
Timeout = 2;
StreamFilters = false; StreamFilters = false;
HideMenuEntry = false; HideMenuEntry = false;
MinPriority = -1; MinPriority = -1;
@ -31,6 +32,7 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
strcpy(RemoteIp, Value); strcpy(RemoteIp, Value);
} }
else if (strcmp(Name, "RemotePort") == 0) RemotePort = atoi(Value); else if (strcmp(Name, "RemotePort") == 0) RemotePort = atoi(Value);
else if (strcmp(Name, "Timeout") == 0) Timeout = atoi(Value);
else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value); else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value);
else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value); else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value);
else if (strcmp(Name, "MinPriority") == 0) MinPriority = atoi(Value); else if (strcmp(Name, "MinPriority") == 0) MinPriority = atoi(Value);
@ -49,6 +51,7 @@ cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
Add(new cMenuEditBoolItem(tr("Start Client"), &m_NewSetup.StartClient)); Add(new cMenuEditBoolItem(tr("Start Client"), &m_NewSetup.StartClient));
Add(new cMenuEditIpItem (tr("Remote IP"), m_NewSetup.RemoteIp)); Add(new cMenuEditIpItem (tr("Remote IP"), m_NewSetup.RemoteIp));
Add(new cMenuEditIntItem (tr("Remote Port"), &m_NewSetup.RemotePort, 0, 65535)); Add(new cMenuEditIntItem (tr("Remote Port"), &m_NewSetup.RemotePort, 0, 65535));
Add(new cMenuEditIntItem (tr("Timeout (s)"), &m_NewSetup.Timeout, 1, 15));
Add(new cMenuEditBoolItem(tr("Filter Streaming"), &m_NewSetup.StreamFilters)); Add(new cMenuEditBoolItem(tr("Filter Streaming"), &m_NewSetup.StreamFilters));
Add(new cMenuEditIntItem (tr("Minimum Priority"), &m_NewSetup.MinPriority, -1, MAXPRIORITY)); Add(new cMenuEditIntItem (tr("Minimum Priority"), &m_NewSetup.MinPriority, -1, MAXPRIORITY));
Add(new cMenuEditIntItem (tr("Maximum Priority"), &m_NewSetup.MaxPriority, -1, MAXPRIORITY)); Add(new cMenuEditIntItem (tr("Maximum Priority"), &m_NewSetup.MaxPriority, -1, MAXPRIORITY));
@ -75,6 +78,7 @@ void cStreamdevClientMenuSetupPage::Store(void) {
else else
SetupStore("RemoteIp", m_NewSetup.RemoteIp); SetupStore("RemoteIp", m_NewSetup.RemoteIp);
SetupStore("RemotePort", m_NewSetup.RemotePort); SetupStore("RemotePort", m_NewSetup.RemotePort);
SetupStore("Timeout", m_NewSetup.Timeout);
SetupStore("StreamFilters", m_NewSetup.StreamFilters); SetupStore("StreamFilters", m_NewSetup.StreamFilters);
SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry); SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
SetupStore("MinPriority", m_NewSetup.MinPriority); SetupStore("MinPriority", m_NewSetup.MinPriority);

View File

@ -15,6 +15,7 @@ struct cStreamdevClientSetup {
int StartClient; int StartClient;
char RemoteIp[20]; char RemoteIp[20];
int RemotePort; int RemotePort;
int Timeout;
int StreamFilters; int StreamFilters;
int HideMenuEntry; int HideMenuEntry;
int MinPriority; int MinPriority;

View File

@ -11,8 +11,11 @@
#define MINLOGREPEAT 10 //don't log connect failures too often (seconds) #define MINLOGREPEAT 10 //don't log connect failures too often (seconds)
// timeout for writing to command socket
#define WRITE_TIMEOUT_MS 200
#define QUIT_TIMEOUT_MS 500
#include "client/socket.h" #include "client/socket.h"
#include "client/setup.h"
#include "common.h" #include "common.h"
cClientSocket ClientSocket; cClientSocket ClientSocket;
@ -21,6 +24,7 @@ cClientSocket::cClientSocket(void)
{ {
memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count); memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count);
m_Prio = false; m_Prio = false;
m_Abort = false;
m_LastSignalUpdate = 0; m_LastSignalUpdate = 0;
m_LastSignalStrength = -1; m_LastSignalStrength = -1;
m_LastSignalQuality = -1; m_LastSignalQuality = -1;
@ -45,43 +49,53 @@ cTBSocket *cClientSocket::DataSocket(eSocketId Id) const {
return m_DataSockets[Id]; return m_DataSockets[Id];
} }
bool cClientSocket::Command(const std::string &Command, uint Expected, uint TimeoutMs) bool cClientSocket::Command(const std::string &Command, uint Expected)
{ {
errno = 0; uint code = 0;
std::string buffer;
if (Send(Command) && Receive(Command, &code, &buffer)) {
if (code == Expected)
return true;
dsyslog("streamdev-client: Command '%s' rejected by %s:%d: %s",
Command.c_str(), RemoteIp().c_str(), RemotePort(), buffer.c_str());
}
return false;
}
bool cClientSocket::Send(const std::string &Command)
{
std::string pkt = Command + "\015\012"; std::string pkt = Command + "\015\012";
Dprintf("OUT: |%s|\n", Command.c_str()); Dprintf("OUT: |%s|\n", Command.c_str());
cTimeMs starttime; errno = 0;
if (!TimedWrite(pkt.c_str(), pkt.size(), TimeoutMs)) { if (!TimedWrite(pkt.c_str(), pkt.size(), WRITE_TIMEOUT_MS)) {
esyslog("Streamdev: Lost connection to %s:%d: %s", RemoteIp().c_str(), RemotePort(), esyslog("ERROR: streamdev-client: Failed sending command '%s' to %s:%d: %s",
strerror(errno)); Command.c_str(), RemoteIp().c_str(), RemotePort(), strerror(errno));
Close(); Close();
return false; return false;
} }
uint64_t elapsed = starttime.Elapsed();
if (Expected != 0) { // XXX+ What if elapsed > TimeoutMs?
TimeoutMs -= elapsed;
return Expect(Expected, NULL, TimeoutMs);
}
return true; return true;
} }
bool cClientSocket::Expect(uint Expected, std::string *Result, uint TimeoutMs) { #define TIMEOUT_MS 1000
char *endptr; bool cClientSocket::Receive(const std::string &Command, uint *Code, std::string *Result, uint TimeoutMs) {
int bufcount; int bufcount;
bool res; do
{
errno = 0; errno = 0;
bufcount = ReadUntil(m_Buffer, sizeof(m_Buffer) - 1, "\012", TimeoutMs < TIMEOUT_MS ? TimeoutMs : TIMEOUT_MS);
if ((bufcount = ReadUntil(m_Buffer, sizeof(m_Buffer) - 1, "\012", TimeoutMs)) == -1) { if (bufcount == -1) {
esyslog("Streamdev: Lost connection to %s:%d: %s", RemoteIp().c_str(), RemotePort(), if (m_Abort)
strerror(errno)); return false;
Close(); if (errno != ETIMEDOUT || TimeoutMs <= TIMEOUT_MS) {
return false; esyslog("ERROR: streamdev-client: Failed reading reply to '%s' from %s:%d: %s",
} Command.c_str(), RemoteIp().c_str(), RemotePort(), strerror(errno));
Close();
return false;
}
TimeoutMs -= TIMEOUT_MS;
}
} while (bufcount == -1);
if (m_Buffer[bufcount - 1] == '\015') if (m_Buffer[bufcount - 1] == '\015')
--bufcount; --bufcount;
m_Buffer[bufcount] = '\0'; m_Buffer[bufcount] = '\0';
@ -89,9 +103,9 @@ bool cClientSocket::Expect(uint Expected, std::string *Result, uint TimeoutMs) {
if (Result != NULL) if (Result != NULL)
*Result = m_Buffer; *Result = m_Buffer;
if (Code != NULL)
res = strtoul(m_Buffer, &endptr, 10) == Expected; *Code = strtoul(m_Buffer, NULL, 10);
return res; return true;
} }
bool cClientSocket::CheckConnection(void) { bool cClientSocket::CheckConnection(void) {
@ -115,10 +129,10 @@ bool cClientSocket::CheckConnection(void) {
Close(); Close();
} }
if (!Connect(StreamdevClientSetup.RemoteIp, StreamdevClientSetup.RemotePort)){ if (!Connect(StreamdevClientSetup.RemoteIp, StreamdevClientSetup.RemotePort, StreamdevClientSetup.Timeout * 1000)){
static time_t lastTime = 0; static time_t lastTime = 0;
if (time(NULL) - lastTime > MINLOGREPEAT) { if (time(NULL) - lastTime > MINLOGREPEAT) {
esyslog("ERROR: Streamdev: Couldn't connect to %s:%d: %s", esyslog("ERROR: streamdev-client: Couldn't connect to %s:%d: %s",
(const char*)StreamdevClientSetup.RemoteIp, (const char*)StreamdevClientSetup.RemoteIp,
StreamdevClientSetup.RemotePort, strerror(errno)); StreamdevClientSetup.RemotePort, strerror(errno));
lastTime = time(NULL); lastTime = time(NULL);
@ -126,18 +140,20 @@ bool cClientSocket::CheckConnection(void) {
return false; return false;
} }
if (!Expect(220)) { uint code = 0;
if (errno == 0) std::string buffer;
esyslog("ERROR: Streamdev: Didn't receive greeting from %s:%d", if (!Receive("<connect>", &code, &buffer)) {
RemoteIp().c_str(), RemotePort()); Close();
return false;
}
if (code != 220) {
esyslog("ERROR: streamdev-client: Didn't receive greeting from %s:%d: %s",
RemoteIp().c_str(), RemotePort(), buffer.c_str());
Close(); Close();
return false; return false;
} }
if (!Command("CAPS TSPIDS", 220)) { if (!Command("CAPS TSPIDS", 220)) {
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't negotiate capabilities on %s:%d",
RemoteIp().c_str(), RemotePort());
Close(); Close();
return false; return false;
} }
@ -152,7 +168,7 @@ bool cClientSocket::CheckConnection(void) {
m_Prio = true; m_Prio = true;
} }
isyslog("Streamdev: Connected to server %s:%d using capabilities TSPIDS%s%s", isyslog("streamdev-client: Connected to server %s:%d using capabilities TSPIDS%s%s",
RemoteIp().c_str(), RemotePort(), Filters, Prio); RemoteIp().c_str(), RemotePort(), Filters, Prio);
return true; return true;
} }
@ -164,14 +180,16 @@ bool cClientSocket::ProvidesChannel(const cChannel *Channel, int Priority) {
std::string command = (std::string)"PROV " + (const char*)itoa(Priority) + " " std::string command = (std::string)"PROV " + (const char*)itoa(Priority) + " "
+ (const char*)Channel->GetChannelID().ToString(); + (const char*)Channel->GetChannelID().ToString();
if (!Command(command)) if (!Send(command))
return false; return false;
uint code;
std::string buffer; std::string buffer;
if (!Expect(220, &buffer)) { if (!Receive(command, &code, &buffer))
if (buffer.substr(0, 3) != "560" && errno == 0) return false;
esyslog("ERROR: Streamdev: Couldn't check if %s:%d provides channel %s", if (code != 220 && code != 560) {
RemoteIp().c_str(), RemotePort(), Channel->Name()); esyslog("streamdev-client: Unexpected reply to '%s' from %s:%d: %s",
command.c_str(), RemoteIp().c_str(), RemotePort(), buffer.c_str());
return false; return false;
} }
return true; return true;
@ -186,7 +204,7 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
DELETENULL(m_DataSockets[Id]); DELETENULL(m_DataSockets[Id]);
if (!listen.Listen(LocalIp(), 0, 1)) { if (!listen.Listen(LocalIp(), 0, 1)) {
esyslog("ERROR: Streamdev: Couldn't create data connection: %s", esyslog("ERROR: streamdev-client: Couldn't create data connection: %s",
strerror(errno)); strerror(errno));
return false; return false;
} }
@ -201,13 +219,8 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
CMD_LOCK; CMD_LOCK;
if (!Command(command, 220)) { if (!Command(command, 220))
Dprintf("error: %m\n");
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't establish data connection to %s:%d",
RemoteIp().c_str(), RemotePort());
return false; return false;
}
/* The server SHOULD do the following: /* The server SHOULD do the following:
* - get PORT command * - get PORT command
@ -217,7 +230,7 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
m_DataSockets[Id] = new cTBSocket; m_DataSockets[Id] = new cTBSocket;
if (!m_DataSockets[Id]->Accept(listen)) { if (!m_DataSockets[Id]->Accept(listen)) {
esyslog("ERROR: Streamdev: Couldn't establish data connection to %s:%d%s%s", esyslog("ERROR: streamdev-client: Couldn't establish data connection to %s:%d%s%s",
RemoteIp().c_str(), RemotePort(), errno == 0 ? "" : ": ", RemoteIp().c_str(), RemotePort(), errno == 0 ? "" : ": ",
errno == 0 ? "" : strerror(errno)); errno == 0 ? "" : strerror(errno));
DELETENULL(m_DataSockets[Id]); DELETENULL(m_DataSockets[Id]);
@ -228,18 +241,12 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
} }
bool cClientSocket::CloseDataConnection(eSocketId Id) { bool cClientSocket::CloseDataConnection(eSocketId Id) {
//if (!CheckConnection()) return false;
CMD_LOCK; CMD_LOCK;
if(Id == siLive || Id == siLiveFilter) if(Id == siLive || Id == siLiveFilter)
if (m_DataSockets[Id] != NULL) { if (m_DataSockets[Id] != NULL) {
std::string command = (std::string)"ABRT " + (const char*)itoa(Id); std::string command = (std::string)"ABRT " + (const char*)itoa(Id);
if (!Command(command, 220)) { Command(command, 220);
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
//return false;
}
DELETENULL(m_DataSockets[Id]); DELETENULL(m_DataSockets[Id]);
} }
return true; return true;
@ -252,12 +259,8 @@ bool cClientSocket::SetChannelDevice(const cChannel *Channel) {
std::string command = (std::string)"TUNE " std::string command = (std::string)"TUNE "
+ (const char*)Channel->GetChannelID().ToString(); + (const char*)Channel->GetChannelID().ToString();
if (!Command(command, 220, 10000)) { if (!Command(command, 220))
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't tune %s:%d to channel %s",
RemoteIp().c_str(), RemotePort(), Channel->Name());
return false; return false;
}
m_LastSignalUpdate = 0; m_LastSignalUpdate = 0;
return true; return true;
@ -269,13 +272,7 @@ bool cClientSocket::SetPriority(int Priority) {
CMD_LOCK; CMD_LOCK;
std::string command = (std::string)"PRIO " + (const char*)itoa(Priority); std::string command = (std::string)"PRIO " + (const char*)itoa(Priority);
if (!Command(command, 220)) { return Command(command, 220);
if (errno == 0)
esyslog("Streamdev: Failed to update priority on %s:%d", RemoteIp().c_str(),
RemotePort());
return false;
}
return true;
} }
bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality) { bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality) {
@ -284,8 +281,10 @@ bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality) {
CMD_LOCK; CMD_LOCK;
if (m_LastSignalUpdate != time(NULL)) { if (m_LastSignalUpdate != time(NULL)) {
uint code = 0;
std::string buffer; std::string buffer;
if (!Command("SGNL") || !Expect(220, &buffer) std::string command("SGNL");
if (!Send(command) || !Receive(command, &code, &buffer) || code != 220
|| sscanf(buffer.c_str(), "%*d %*d %d:%d", &m_LastSignalStrength, &m_LastSignalQuality) != 2) { || sscanf(buffer.c_str(), "%*d %*d %d:%d", &m_LastSignalStrength, &m_LastSignalQuality) != 2) {
m_LastSignalStrength = -1; m_LastSignalStrength = -1;
m_LastSignalQuality = -1; m_LastSignalQuality = -1;
@ -305,13 +304,7 @@ bool cClientSocket::SetPid(int Pid, bool On) {
CMD_LOCK; CMD_LOCK;
std::string command = (std::string)(On ? "ADDP " : "DELP ") + (const char*)itoa(Pid); std::string command = (std::string)(On ? "ADDP " : "DELP ") + (const char*)itoa(Pid);
if (!Command(command, 220)) { return Command(command, 220);
if (errno == 0)
esyslog("Streamdev: Pid %d not available from %s:%d", Pid, RemoteIp().c_str(),
RemotePort());
return false;
}
return true;
} }
bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) { bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
@ -321,13 +314,7 @@ bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
std::string command = (std::string)(On ? "ADDF " : "DELF ") + (const char*)itoa(Pid) std::string command = (std::string)(On ? "ADDF " : "DELF ") + (const char*)itoa(Pid)
+ " " + (const char*)itoa(Tid) + " " + (const char*)itoa(Mask); + " " + (const char*)itoa(Tid) + " " + (const char*)itoa(Mask);
if (!Command(command, 220)) { return Command(command, 220);
if (errno == 0)
esyslog("Streamdev: Filter %hu, %hhu, %hhu not available from %s:%d",
Pid, Tid, Mask, RemoteIp().c_str(), RemotePort());
return false;
}
return true;
} }
bool cClientSocket::CloseDvr(void) { bool cClientSocket::CloseDvr(void) {
@ -337,27 +324,20 @@ bool cClientSocket::CloseDvr(void) {
if (m_DataSockets[siLive] != NULL) { if (m_DataSockets[siLive] != NULL) {
std::string command = (std::string)"ABRT " + (const char*)itoa(siLive); std::string command = (std::string)"ABRT " + (const char*)itoa(siLive);
if (!Command(command, 220)) { if (!Command(command, 220))
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
return false; return false;
}
DELETENULL(m_DataSockets[siLive]); DELETENULL(m_DataSockets[siLive]);
} }
return true; return true;
} }
bool cClientSocket::Quit(void) { bool cClientSocket::Quit(void) {
bool res; m_Abort = true;
if (!IsOpen()) return false;
if (!CheckConnection()) return false; CMD_LOCK;
std::string command("QUIT");
if (!(res = Command("QUIT", 221))) { bool res = Send(command) && Receive(command, NULL, NULL, QUIT_TIMEOUT_MS);
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't quit command connection to %s:%d",
RemoteIp().c_str(), RemotePort());
}
Close(); Close();
return res; return res;
} }
@ -367,10 +347,5 @@ bool cClientSocket::SuspendServer(void) {
CMD_LOCK; CMD_LOCK;
if (!Command("SUSP", 220)) { return Command("SUSP", 220);
if (errno == 0)
esyslog("ERROR: Streamdev: Couldn't suspend server");
return false;
}
return true;
} }

View File

@ -8,6 +8,7 @@
#include <tools/socket.h> #include <tools/socket.h>
#include "common.h" #include "common.h"
#include "client/setup.h"
#include <string> #include <string>
@ -21,22 +22,23 @@ private:
cMutex m_Mutex; cMutex m_Mutex;
char m_Buffer[BUFSIZ + 1]; // various uses char m_Buffer[BUFSIZ + 1]; // various uses
bool m_Prio; // server supports command PRIO bool m_Prio; // server supports command PRIO
bool m_Abort; // quit command pending
time_t m_LastSignalUpdate; time_t m_LastSignalUpdate;
int m_LastSignalStrength; int m_LastSignalStrength;
int m_LastSignalQuality; int m_LastSignalQuality;
protected: protected:
/* Send Command, and return true if the command results in Expected. /* Send Command, and return true if the command results in Expected.
Returns false on failure, setting errno appropriately if it has been Returns false on failure. */
a system failure. If Expected is zero, returns immediately after bool Command(const std::string &Command, uint Expected);
sending the command. */
bool Command(const std::string &Command, uint Expected = 0, uint TimeoutMs = 1500);
/* Fetch results from an ongoing Command called with Expected == 0. Returns /* Send the given command. Returns false on failure. */
true if the response has the code Expected, returning an internal buffer bool Send(const std::string &Command);
in the array pointer pointed to by Result. Returns false on failure,
setting errno appropriately if it has been a system failure. */ /* Fetch results from an ongoing Command. The status code and the
bool Expect(uint Expected, std::string *Result = NULL, uint TimeoutMs = 1500); buffer holding the server's response are stored in Code and Result
if non-NULL. Returns false on failure. */
bool Receive(const std::string &Command, uint *Code = NULL, std::string *Result = NULL, uint TimeoutMs = StreamdevClientSetup.Timeout * 1000);
public: public:
cClientSocket(void); cClientSocket(void);