mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	Timout for network operations now configurable in streamdev-client setup
This commit is contained in:
		
							
								
								
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								HISTORY
									
									
									
									
									
								
							@@ -1,6 +1,7 @@
 | 
			
		||||
VDR Plugin 'streamdev' Revision History
 | 
			
		||||
---------------------------------------
 | 
			
		||||
 
 | 
			
		||||
- Timout for network operations now configurable in streamdev-client setup
 | 
			
		||||
- Added timeout to Connect()
 | 
			
		||||
- Report the server-side HTTP status "503 Service unavailable" instead of
 | 
			
		||||
  the client-side error "409 Conflict" when a channel is unavailable
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								README
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
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
 | 
			
		||||
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.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
 | 
			
		||||
"Language-Team: German <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "IP der Gegenseite"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Port der Gegenseite"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr "Timeout (s)"
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Filter-Daten streamen"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Javier Bradineras <jbradi@hotmail.com>\n"
 | 
			
		||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "Indicar IP del Servidor"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Indicar puerto remoto del Servidor"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Filtrar transmisi<73>n"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Rolf Ahrenberg\n"
 | 
			
		||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "Etäkoneen IP-osoite"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Etäkoneen portti"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Suodatetun tiedon suoratoisto"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: micky979 <micky979@free.fr>\n"
 | 
			
		||||
"Language-Team: French <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "Adresse IP du serveur"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Port du serveur"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Filtre streaming"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
 | 
			
		||||
"Language-Team: Italian <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -42,6 +42,9 @@ msgstr "Indirizzo IP del Server"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Porta Server Remoto"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Filtra trasmissione"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
 | 
			
		||||
"Language-Team: Lithuanian <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "Nuotolinis IP adresas"
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Nuotolinis portas"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Filtruoti transliavimą"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev 0.5.0\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"
 | 
			
		||||
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
 | 
			
		||||
"Language-Team: Russian <vdr@linuxtv.org>\n"
 | 
			
		||||
@@ -40,6 +40,9 @@ msgstr "
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: streamdev_SK\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"
 | 
			
		||||
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
 | 
			
		||||
"Language-Team: Slovak <hrala.milan@gmail.com>\n"
 | 
			
		||||
@@ -42,6 +42,9 @@ msgstr "Vzdialen
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Vzdialen<65> port"
 | 
			
		||||
 | 
			
		||||
msgid "Timeout (s)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "filtrova<76> pr<70>dy"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ cStreamdevClientSetup StreamdevClientSetup;
 | 
			
		||||
cStreamdevClientSetup::cStreamdevClientSetup(void) {
 | 
			
		||||
	StartClient   = false;
 | 
			
		||||
	RemotePort    = 2004;
 | 
			
		||||
	Timeout       = 2;
 | 
			
		||||
	StreamFilters = false;
 | 
			
		||||
	HideMenuEntry = false;
 | 
			
		||||
	MinPriority   = -1;
 | 
			
		||||
@@ -31,6 +32,7 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
 | 
			
		||||
			strcpy(RemoteIp, 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, "HideMenuEntry") == 0) HideMenuEntry = 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 cMenuEditIpItem  (tr("Remote IP"),            m_NewSetup.RemoteIp));
 | 
			
		||||
	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 cMenuEditIntItem (tr("Minimum Priority"),    &m_NewSetup.MinPriority, -1, MAXPRIORITY));
 | 
			
		||||
	Add(new cMenuEditIntItem (tr("Maximum Priority"),    &m_NewSetup.MaxPriority, -1, MAXPRIORITY));
 | 
			
		||||
@@ -75,6 +78,7 @@ void cStreamdevClientMenuSetupPage::Store(void) {
 | 
			
		||||
	else
 | 
			
		||||
		SetupStore("RemoteIp",    m_NewSetup.RemoteIp);
 | 
			
		||||
	SetupStore("RemotePort",    m_NewSetup.RemotePort);
 | 
			
		||||
	SetupStore("Timeout",       m_NewSetup.Timeout);
 | 
			
		||||
	SetupStore("StreamFilters", m_NewSetup.StreamFilters);
 | 
			
		||||
	SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
 | 
			
		||||
	SetupStore("MinPriority",   m_NewSetup.MinPriority);
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ struct cStreamdevClientSetup {
 | 
			
		||||
	int  StartClient;
 | 
			
		||||
	char RemoteIp[20];
 | 
			
		||||
	int  RemotePort;
 | 
			
		||||
	int  Timeout;
 | 
			
		||||
	int  StreamFilters;
 | 
			
		||||
	int  HideMenuEntry;
 | 
			
		||||
	int  MinPriority;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										185
									
								
								client/socket.c
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								client/socket.c
									
									
									
									
									
								
							@@ -11,8 +11,11 @@
 | 
			
		||||
 | 
			
		||||
#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/setup.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
cClientSocket ClientSocket;
 | 
			
		||||
@@ -21,6 +24,7 @@ cClientSocket::cClientSocket(void)
 | 
			
		||||
{
 | 
			
		||||
	memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count);
 | 
			
		||||
	m_Prio = false;
 | 
			
		||||
	m_Abort = false;
 | 
			
		||||
	m_LastSignalUpdate = 0;
 | 
			
		||||
	m_LastSignalStrength = -1;
 | 
			
		||||
	m_LastSignalQuality = -1;
 | 
			
		||||
@@ -45,43 +49,53 @@ cTBSocket *cClientSocket::DataSocket(eSocketId Id) const {
 | 
			
		||||
	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";
 | 
			
		||||
	Dprintf("OUT: |%s|\n", Command.c_str());
 | 
			
		||||
 | 
			
		||||
	cTimeMs starttime;
 | 
			
		||||
	if (!TimedWrite(pkt.c_str(), pkt.size(), TimeoutMs)) {
 | 
			
		||||
		esyslog("Streamdev: Lost connection to %s:%d: %s", RemoteIp().c_str(), RemotePort(), 
 | 
			
		||||
		        strerror(errno));
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	if (!TimedWrite(pkt.c_str(), pkt.size(), WRITE_TIMEOUT_MS)) {
 | 
			
		||||
		esyslog("ERROR: streamdev-client: Failed sending command '%s' to %s:%d: %s",
 | 
			
		||||
			Command.c_str(), RemoteIp().c_str(), RemotePort(), strerror(errno));
 | 
			
		||||
		Close();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint64_t elapsed = starttime.Elapsed();
 | 
			
		||||
	if (Expected != 0) { // XXX+ What if elapsed > TimeoutMs?
 | 
			
		||||
		TimeoutMs -= elapsed;
 | 
			
		||||
		return Expect(Expected, NULL, TimeoutMs);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::Expect(uint Expected, std::string *Result, uint TimeoutMs) {
 | 
			
		||||
	char *endptr;
 | 
			
		||||
#define TIMEOUT_MS 1000
 | 
			
		||||
bool cClientSocket::Receive(const std::string &Command, uint *Code, std::string *Result, uint TimeoutMs) {
 | 
			
		||||
	int bufcount;
 | 
			
		||||
	bool res;
 | 
			
		||||
 | 
			
		||||
	errno = 0;
 | 
			
		||||
 | 
			
		||||
	if ((bufcount = ReadUntil(m_Buffer, sizeof(m_Buffer) - 1, "\012", TimeoutMs)) == -1) {
 | 
			
		||||
		esyslog("Streamdev: Lost connection to %s:%d: %s", RemoteIp().c_str(), RemotePort(), 
 | 
			
		||||
		        strerror(errno));
 | 
			
		||||
		Close();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	do
 | 
			
		||||
	{
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		bufcount = ReadUntil(m_Buffer, sizeof(m_Buffer) - 1, "\012", TimeoutMs < TIMEOUT_MS ? TimeoutMs : TIMEOUT_MS);
 | 
			
		||||
		if (bufcount == -1) {
 | 
			
		||||
			if (m_Abort)
 | 
			
		||||
				return false;
 | 
			
		||||
			if (errno != ETIMEDOUT || TimeoutMs <= TIMEOUT_MS) {
 | 
			
		||||
				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')
 | 
			
		||||
		--bufcount;
 | 
			
		||||
	m_Buffer[bufcount] = '\0';
 | 
			
		||||
@@ -89,9 +103,9 @@ bool cClientSocket::Expect(uint Expected, std::string *Result, uint TimeoutMs) {
 | 
			
		||||
 | 
			
		||||
	if (Result != NULL)
 | 
			
		||||
		*Result = m_Buffer;
 | 
			
		||||
 | 
			
		||||
	res = strtoul(m_Buffer, &endptr, 10) == Expected;
 | 
			
		||||
	return res;
 | 
			
		||||
	if (Code != NULL)
 | 
			
		||||
		*Code = strtoul(m_Buffer, NULL, 10);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::CheckConnection(void) {
 | 
			
		||||
@@ -115,10 +129,10 @@ bool cClientSocket::CheckConnection(void) {
 | 
			
		||||
		Close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!Connect(StreamdevClientSetup.RemoteIp, StreamdevClientSetup.RemotePort)){
 | 
			
		||||
	if (!Connect(StreamdevClientSetup.RemoteIp, StreamdevClientSetup.RemotePort, StreamdevClientSetup.Timeout * 1000)){
 | 
			
		||||
		static time_t lastTime = 0;
 | 
			
		||||
		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,
 | 
			
		||||
				StreamdevClientSetup.RemotePort, strerror(errno));
 | 
			
		||||
			lastTime = time(NULL);
 | 
			
		||||
@@ -126,18 +140,20 @@ bool cClientSocket::CheckConnection(void) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!Expect(220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Didn't receive greeting from %s:%d", 
 | 
			
		||||
			        RemoteIp().c_str(), RemotePort());
 | 
			
		||||
	uint code = 0;
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	if (!Receive("<connect>", &code, &buffer)) {
 | 
			
		||||
		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();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!Command("CAPS TSPIDS", 220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't negotiate capabilities on %s:%d", 
 | 
			
		||||
					RemoteIp().c_str(), RemotePort());
 | 
			
		||||
		Close();
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
@@ -152,7 +168,7 @@ bool cClientSocket::CheckConnection(void) {
 | 
			
		||||
		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);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -164,14 +180,16 @@ bool cClientSocket::ProvidesChannel(const cChannel *Channel, int Priority) {
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)"PROV " + (const char*)itoa(Priority) + " " 
 | 
			
		||||
	                    + (const char*)Channel->GetChannelID().ToString();
 | 
			
		||||
	if (!Command(command))
 | 
			
		||||
	if (!Send(command))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	uint code;
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	if (!Expect(220, &buffer)) {
 | 
			
		||||
		if (buffer.substr(0, 3) != "560" && errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't check if %s:%d provides channel %s",
 | 
			
		||||
			        RemoteIp().c_str(), RemotePort(), Channel->Name());
 | 
			
		||||
	if (!Receive(command, &code, &buffer))
 | 
			
		||||
		return false;
 | 
			
		||||
	if (code != 220 && code != 560) {
 | 
			
		||||
		esyslog("streamdev-client: Unexpected reply to '%s' from %s:%d: %s",
 | 
			
		||||
			command.c_str(), RemoteIp().c_str(), RemotePort(), buffer.c_str());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -186,7 +204,7 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
 | 
			
		||||
		DELETENULL(m_DataSockets[Id]);
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
@@ -201,13 +219,8 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	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());
 | 
			
		||||
	if (!Command(command, 220))
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The server SHOULD do the following:
 | 
			
		||||
	 * - get PORT command
 | 
			
		||||
@@ -217,7 +230,7 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
 | 
			
		||||
 | 
			
		||||
	m_DataSockets[Id] = new cTBSocket;
 | 
			
		||||
	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 ? "" : ": ",
 | 
			
		||||
				errno == 0 ? "" : strerror(errno));
 | 
			
		||||
		DELETENULL(m_DataSockets[Id]);
 | 
			
		||||
@@ -228,18 +241,12 @@ bool cClientSocket::CreateDataConnection(eSocketId Id) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::CloseDataConnection(eSocketId Id) {
 | 
			
		||||
	//if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if(Id == siLive || Id == siLiveFilter)
 | 
			
		||||
		if (m_DataSockets[Id] != NULL) {
 | 
			
		||||
			std::string command = (std::string)"ABRT " + (const char*)itoa(Id);
 | 
			
		||||
			if (!Command(command, 220)) {
 | 
			
		||||
				if (errno == 0)
 | 
			
		||||
					esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
 | 
			
		||||
				//return false;
 | 
			
		||||
			}		
 | 
			
		||||
			Command(command, 220);
 | 
			
		||||
			DELETENULL(m_DataSockets[Id]);
 | 
			
		||||
		}
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -252,12 +259,8 @@ bool cClientSocket::SetChannelDevice(const cChannel *Channel) {
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)"TUNE " 
 | 
			
		||||
				+ (const char*)Channel->GetChannelID().ToString();
 | 
			
		||||
	if (!Command(command, 220, 10000)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't tune %s:%d to channel %s",
 | 
			
		||||
			        RemoteIp().c_str(), RemotePort(), Channel->Name());
 | 
			
		||||
	if (!Command(command, 220))
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_LastSignalUpdate = 0;
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -269,13 +272,7 @@ bool cClientSocket::SetPriority(int Priority) {
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)"PRIO " + (const char*)itoa(Priority);
 | 
			
		||||
	if (!Command(command, 220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("Streamdev: Failed to update priority on %s:%d", RemoteIp().c_str(), 
 | 
			
		||||
			        RemotePort());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
	return Command(command, 220);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality) {
 | 
			
		||||
@@ -284,8 +281,10 @@ bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality) {
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (m_LastSignalUpdate != time(NULL)) {
 | 
			
		||||
		uint code = 0;
 | 
			
		||||
		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) {
 | 
			
		||||
			m_LastSignalStrength = -1;
 | 
			
		||||
			m_LastSignalQuality = -1;
 | 
			
		||||
@@ -305,13 +304,7 @@ bool cClientSocket::SetPid(int Pid, bool On) {
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)(On ? "ADDP " : "DELP ") + (const char*)itoa(Pid);
 | 
			
		||||
	if (!Command(command, 220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("Streamdev: Pid %d not available from %s:%d", Pid, RemoteIp().c_str(), 
 | 
			
		||||
			        RemotePort());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
	return Command(command, 220);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	                    + " " + (const char*)itoa(Tid) + " " + (const char*)itoa(Mask);
 | 
			
		||||
	if (!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;
 | 
			
		||||
	return Command(command, 220);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::CloseDvr(void) {
 | 
			
		||||
@@ -337,27 +324,20 @@ bool cClientSocket::CloseDvr(void) {
 | 
			
		||||
 | 
			
		||||
	if (m_DataSockets[siLive] != NULL) {
 | 
			
		||||
		std::string command = (std::string)"ABRT " + (const char*)itoa(siLive);
 | 
			
		||||
		if (!Command(command, 220)) {
 | 
			
		||||
			if (errno == 0)
 | 
			
		||||
				esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
 | 
			
		||||
		if (!Command(command, 220))
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		DELETENULL(m_DataSockets[siLive]);
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::Quit(void) {
 | 
			
		||||
	bool res;
 | 
			
		||||
	m_Abort = true;
 | 
			
		||||
	if (!IsOpen()) return false;
 | 
			
		||||
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
	if (!(res = Command("QUIT", 221))) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't quit command connection to %s:%d",
 | 
			
		||||
					RemoteIp().c_str(), RemotePort());
 | 
			
		||||
	}
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
	std::string command("QUIT");
 | 
			
		||||
	bool res = Send(command) && Receive(command, NULL, NULL, QUIT_TIMEOUT_MS);
 | 
			
		||||
	Close();
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
@@ -367,10 +347,5 @@ bool cClientSocket::SuspendServer(void) {
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (!Command("SUSP", 220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't suspend server");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
	return Command("SUSP", 220);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#include <tools/socket.h>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "client/setup.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
@@ -21,22 +22,23 @@ private:
 | 
			
		||||
	cMutex        m_Mutex;
 | 
			
		||||
	char          m_Buffer[BUFSIZ + 1]; // various uses
 | 
			
		||||
	bool          m_Prio; // server supports command PRIO
 | 
			
		||||
	bool          m_Abort; // quit command pending
 | 
			
		||||
 | 
			
		||||
	time_t        m_LastSignalUpdate;
 | 
			
		||||
	int           m_LastSignalStrength;
 | 
			
		||||
	int           m_LastSignalQuality;
 | 
			
		||||
protected:
 | 
			
		||||
	/* Send Command, and return true if the command results in Expected. 
 | 
			
		||||
	   Returns false on failure, setting errno appropriately if it has been
 | 
			
		||||
	   a system failure. If Expected is zero, returns immediately after
 | 
			
		||||
		 sending the command. */
 | 
			
		||||
	bool Command(const std::string &Command, uint Expected = 0, uint TimeoutMs = 1500);
 | 
			
		||||
	   Returns false on failure. */
 | 
			
		||||
	bool Command(const std::string &Command, uint Expected);
 | 
			
		||||
 | 
			
		||||
	/* Fetch results from an ongoing Command called with Expected == 0. Returns
 | 
			
		||||
	   true if the response has the code Expected, returning an internal buffer
 | 
			
		||||
		 in the array pointer pointed to by Result. Returns false on failure, 
 | 
			
		||||
		 setting errno appropriately if it has been a system failure. */
 | 
			
		||||
	bool Expect(uint Expected, std::string *Result = NULL, uint TimeoutMs = 1500);
 | 
			
		||||
	/* Send the given command. Returns false on failure. */
 | 
			
		||||
	bool Send(const std::string &Command);
 | 
			
		||||
 | 
			
		||||
	/* Fetch results from an ongoing Command. The status code and the
 | 
			
		||||
	   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:
 | 
			
		||||
	cClientSocket(void);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user