diff --git a/server/componentIGMP.c b/server/componentIGMP.c index 223aa3c..7398c67 100644 --- a/server/componentIGMP.c +++ b/server/componentIGMP.c @@ -6,6 +6,7 @@ #include "server/componentIGMP.h" #include "server/connectionIGMP.h" +#include "server/server.h" #include "server/setup.h" #ifndef IGMP_ALL_HOSTS @@ -37,7 +38,6 @@ class cMulticastGroup: public cListObject { public: - cConnectionIGMP *connection; in_addr_t group; in_addr_t reporter; struct timeval timeout; @@ -48,7 +48,6 @@ public: }; cMulticastGroup::cMulticastGroup(in_addr_t Group) : - connection(NULL), group(Group), reporter(0) { @@ -235,10 +234,7 @@ cServerConnection* cComponentIGMP::ProcessMessage(struct igmp *Igmp, in_addr_t G group = new cMulticastGroup(Group); m_Groups.Add(group); } - if (!group->connection) { - IGMPStartMulticast(group); - conn = group->connection; - } + conn = IGMPStartMulticast(group); IGMPStartTimer(group, Sender); if (Igmp->igmp_type == IGMP_V1_MEMBERSHIP_REPORT) IGMPStartV1HostTimer(group); @@ -430,20 +426,36 @@ void cComponentIGMP::IGMPSendGroupQuery(cMulticastGroup* Group) IGMPSendQuery(Group->group, IGMP_LAST_MEMBER_QUERY_INTERVAL_TS); } -void cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group) +cServerConnection* cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group) { + cServerConnection *conn = NULL; in_addr_t g = ntohl(Group->group); if (g > MULTICAST_PRIV_MIN && g <= MULTICAST_PRIV_MAX) { + cThreadLock lock; cChannel *channel = Channels.GetByNumber(g - MULTICAST_PRIV_MIN); - Group->connection = (cConnectionIGMP*) NewClient(); - if (!Group->connection->SetChannel(channel, Group->group)) { - DELETENULL(Group->connection); + const cList& clients = cStreamdevServer::Clients(lock); + cServerConnection *s = clients.First(); + while (s) { + if (s->RemoteIpAddr() == Group->group) + break; + s = clients.Next(s); + } + if (!s) { + conn = NewClient(); + if (!((cConnectionIGMP *)conn)->SetChannel(channel, Group->group)) { + DELETENULL(conn); + } } } + return conn; } void cComponentIGMP::IGMPStopMulticast(cMulticastGroup* Group) { - if (Group->connection) - Group->connection->Stop(); + cThreadLock lock; + const cList& clients = cStreamdevServer::Clients(lock); + for (cServerConnection *s = clients.First(); s; s = clients.Next(s)) { + if (s->RemoteIpAddr() == Group->group) + s->Close(); + } } diff --git a/server/componentIGMP.h b/server/componentIGMP.h index 09d8fde..8f6c027 100644 --- a/server/componentIGMP.h +++ b/server/componentIGMP.h @@ -10,7 +10,6 @@ #include #include "server/component.h" -class cConnectionIGMP; class cMulticastGroup; class cComponentIGMP: public cServerComponent, public cThread { @@ -42,7 +41,7 @@ private: void IGMPStartRetransmitTimer(cMulticastGroup* Group); void IGMPClearRetransmitTimer(cMulticastGroup* Group); void IGMPSendGroupQuery(cMulticastGroup* Group); - void IGMPStartMulticast(cMulticastGroup* Group); + cServerConnection* IGMPStartMulticast(cMulticastGroup* Group); void IGMPStopMulticast(cMulticastGroup* Group); virtual void Action(); diff --git a/server/connectionIGMP.c b/server/connectionIGMP.c index 695c8bc..328fe44 100644 --- a/server/connectionIGMP.c +++ b/server/connectionIGMP.c @@ -64,12 +64,11 @@ void cConnectionIGMP::Welcome() esyslog("streamdev-server IGMP: GetDevice failed"); } -void cConnectionIGMP::Stop() +bool cConnectionIGMP::Close() { - if (m_LiveStreamer) { + if (m_LiveStreamer) m_LiveStreamer->Stop(); - DELETENULL(m_LiveStreamer); - } + return cServerConnection::Close(); } cString cConnectionIGMP::ToText() const diff --git a/server/connectionIGMP.h b/server/connectionIGMP.h index 1faa51d..255379b 100644 --- a/server/connectionIGMP.h +++ b/server/connectionIGMP.h @@ -29,13 +29,13 @@ public: bool SetChannel(cChannel *Channel, in_addr_t Dst); virtual void Welcome(void); virtual cString ToText() const; - void Stop(); /* Not used here */ virtual bool Command(char *Cmd) { return false; } virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); } virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); } + virtual bool Close(void); virtual bool Abort(void) const; };