diff options
Diffstat (limited to 'server/connection.c')
-rw-r--r-- | server/connection.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/server/connection.c b/server/connection.c new file mode 100644 index 0000000..b4dd091 --- /dev/null +++ b/server/connection.c @@ -0,0 +1,172 @@ +/* + * $Id: connection.c,v 1.1 2004/12/30 22:44:19 lordjaxom Exp $ + */ + +#include "server/connection.h" +#include "server/setup.h" +#include "server/suspend.h" +#include "common.h" + +#include <vdr/tools.h> +#include <string.h> +#include <errno.h> + +cServerConnection::cServerConnection(const char *Protocol) { + m_RdBytes = 0; + m_WrBytes = 0; + m_WrOffs = 0; + m_DeferClose = false; + m_Protocol = Protocol; +} + +cServerConnection::~cServerConnection() { +} + +bool cServerConnection::CanAct(const cTBSelect &Select) { + if (Select.CanRead(*this)) { + int b; + if ((b = Read(m_RdBuf + m_RdBytes, sizeof(m_RdBuf) - m_RdBytes - 1)) < 0) { + esyslog("Streamdev: Read from client (%s) %s:%d failed: %s", m_Protocol, + (const char*)RemoteIp(), RemotePort(), strerror(errno)); + return false; + } + + if (b == 0) { + isyslog("Streamdev: Client (%s) %s:%d closed connection", m_Protocol, + (const char*)RemoteIp(), RemotePort()); + return false; + } + + m_RdBytes += b; + m_RdBuf[m_RdBytes] = '\0'; + return ParseBuffer(); + } + + if (Select.CanWrite(*this)) { + int b; + if ((b = Write(m_WrBuf + m_WrOffs, m_WrBytes - m_WrOffs)) < 0) { + esyslog("Streamdev: Write to client (%s) %s:%d failed: %s", m_Protocol, + (const char*)RemoteIp(), RemotePort(), strerror(errno)); + return false; + } + + m_WrOffs += b; + if (m_WrOffs == m_WrBytes) { + m_WrBytes = 0; + m_WrOffs = 0; + } + } + + if (m_WrBytes == 0) { + if (m_DeferClose) + return false; + Flushed(); + } + return true; +} + +bool cServerConnection::ParseBuffer(void) { + char *ep; + bool res; + + while ((ep = strchr(m_RdBuf, '\012')) != NULL) { + *ep = '\0'; + if (ep > m_RdBuf && *(ep-1) == '\015') + *(ep-1) = '\0'; + + Dprintf("IN: |%s|\n", m_RdBuf); + res = Command(m_RdBuf); + m_RdBytes -= ++ep - m_RdBuf; + if (m_RdBytes > 0) + memmove(m_RdBuf, ep, m_RdBytes); + if (res == false) + return false; + } + return true; +} + +bool cServerConnection::Respond(const char *Message) { + uint len = strlen(Message); + if (m_WrBytes + len + 2 > sizeof(m_WrBuf)) { + esyslog("Streamdev: Output buffer overflow (%s) for %s:%d", m_Protocol, + (const char*)RemoteIp(), RemotePort()); + return false; + } + Dprintf("OUT: |%s|\n", Message); + memcpy(m_WrBuf + m_WrBytes, Message, len); + m_WrBuf[m_WrBytes + len] = '\015'; + m_WrBuf[m_WrBytes + len + 1] = '\012'; + m_WrBytes += len + 2; + return true; +} + +cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority) { + cDevice *device = NULL; + + /*Dprintf("+ Statistics:\n"); + Dprintf("+ Current Channel: %d\n", cDevice::CurrentChannel()); + Dprintf("+ Current Device: %d\n", cDevice::ActualDevice()->CardIndex()); + Dprintf("+ Transfer Mode: %s\n", cDevice::ActualDevice() + == cDevice::PrimaryDevice() ? "false" : "true"); + Dprintf("+ Replaying: %s\n", cDevice::PrimaryDevice()->Replaying() ? "true" + : "false");*/ + + Dprintf(" * GetDevice(const cChannel*, int)\n"); + Dprintf(" * -------------------------------\n"); + + device = cDevice::GetDevice(Channel, Priority); + + Dprintf(" * Found following device: %p (%d)\n", device, + device ? device->CardIndex() + 1 : 0); + if (device == cDevice::ActualDevice()) + Dprintf(" * is actual device\n"); + if (!cSuspendCtl::IsActive() && StreamdevServerSetup.SuspendMode != smAlways) + Dprintf(" * NOT suspended\n"); + + if (!device || (device == cDevice::ActualDevice() + && !cSuspendCtl::IsActive() + && StreamdevServerSetup.SuspendMode != smAlways)) { + // mustn't switch actual device + // maybe a device would be free if THIS connection did turn off its streams? + Dprintf(" * trying again...\n"); + const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel()); + isyslog("streamdev-server: Detaching current receiver"); + Detach(); + device = cDevice::GetDevice(Channel, Priority); + Attach(); + Dprintf(" * Found following device: %p (%d)\n", device, + device ? device->CardIndex() + 1 : 0); + if (device == cDevice::ActualDevice()) + Dprintf(" * is actual device\n"); + if (!cSuspendCtl::IsActive() + && StreamdevServerSetup.SuspendMode != smAlways) + Dprintf(" * NOT suspended\n"); + if (current && !TRANSPONDER(Channel, current)) + Dprintf(" * NOT same transponder\n"); + if (device && (device == cDevice::ActualDevice() + && !cSuspendCtl::IsActive() + && StreamdevServerSetup.SuspendMode != smAlways + && current != NULL + && !TRANSPONDER(Channel, current))) { + // now we would have to switch away live tv...let's see if live tv + // can be handled by another device + cDevice *newdev = NULL; + for (int i = 0; i < cDevice::NumDevices(); ++i) { + cDevice *dev = cDevice::GetDevice(i); + if (dev->ProvidesChannel(current, 0) && dev != device) { + newdev = dev; + break; + } + } + Dprintf(" * Found device for live tv: %p (%d)\n", newdev, + newdev ? newdev->CardIndex() + 1 : 0); + if (newdev == NULL || newdev == device) + // no suitable device to continue live TV, giving up... + device = NULL; + else + newdev->SwitchChannel(current, true); + } + } + + return device; +} |