1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Original author: Paul McCullagh
20
* Continued development: Barry Leslie
29
#include "cslib/CSConfig.h"
33
#include "cslib/CSGlobal.h"
34
#include "cslib/CSLog.h"
36
#include "network_ms.h"
37
#include "connection_handler_ms.h"
39
MSSystemThread *MSNetwork::gSystemThread;
40
time_t MSNetwork::gCurrentTime;
41
time_t MSNetwork::gLastService;
42
CSThreadList *MSNetwork::gHandlerList;
43
CSSync MSNetwork::gListenerLock;
44
CSSocket *MSNetwork::gListenerSocket;
45
MSConnectionHandler *MSNetwork::gListenerThread;
46
uint32_t MSNetwork::gWaitingToListen;
47
int MSNetwork::handlerCount;
50
* -------------------------------------------------------------------------
54
bool MSSystemThread::doWork()
59
MSNetwork::gCurrentTime = time(NULL);
60
if ((MSNetwork::gCurrentTime - MSNetwork::gLastService) >= (MS_IDLE_THREAD_TIMEOUT/2)) {
61
MSNetwork::gLastService = MSNetwork::gCurrentTime;
62
while (!myMustQuit && killed) {
63
killed = MSNetwork::killListener();
64
MSNetwork::gCurrentTime = time(NULL);
71
* -------------------------------------------------------------------------
75
void MSNetwork::startUp(int port)
78
gCurrentTime = time(NULL);
79
gLastService = gCurrentTime;
80
gListenerSocket = NULL;
84
CSL.log(self, CSLog::Protocol, "Media Stream Daemon ");
86
CSL.log(self, CSLog::Protocol, " listening on port ");
87
CSL.log(self, CSLog::Protocol, port);
89
CSL.log(self, CSLog::Protocol, " not published ");
90
CSL.log(self, CSLog::Protocol, "\n");
93
new_(gHandlerList, CSThreadList());
95
gListenerSocket = CSSocket::newSocket();
96
gListenerSocket->publish(NULL, port);
98
gListenerSocket = NULL;
100
new_(gSystemThread, MSSystemThread(1000 /* 1 sec */, NULL));
101
gSystemThread->start();
105
void MSNetwork::shutDown()
110
gSystemThread->stop();
111
gSystemThread->release();
112
gSystemThread = NULL;
115
/* This will set all threads to quiting: */
117
gHandlerList->quitAllThreads();
119
/* Close the socket: */
121
gListenerThread->shuttingDown = true; // Block error messages as a result of the listener being killed
123
lock_(&gListenerLock);
124
if (gListenerSocket) {
126
gListenerSocket->release();
129
self->logException();
133
gListenerSocket = NULL;
134
unlock_(&gListenerLock);
138
/* This will stop any threads remaining: */
139
gHandlerList->release();
142
self->logException();
147
CSL.log(self, CSLog::Protocol, "PrimeBase Media Stream Daemon no longer published\n");
151
void MSNetwork::startConnectionHandler()
154
MSConnectionHandler *thread;
158
snprintf(buffer, 120, "NetworkHandler%d", handlerCount);
160
thread = MSConnectionHandler::newHandler(MSNetwork::gHandlerList);
161
unlock_(gHandlerList);
163
thread->threadName = CSString::newString(buffer);
170
* Return NULL of a connection cannot be openned, and the
173
class OpenConnectioCleanUp : public CSRefObject {
178
OpenConnectioCleanUp(): CSRefObject(),
181
~OpenConnectioCleanUp()
184
MSNetwork::unlockListenerSocket();
201
* Return NULL if a connection cannot be openned, and the
204
CSSocket *MSNetwork::openConnection(MSConnectionHandler *handler)
206
CSSocket *sock = NULL;
207
OpenConnectioCleanUp *cleanup;
211
if(!MSNetwork::gListenerSocket) {
215
sock = CSSocket::newSocket();
218
/* Wait for a connection: */
219
if (!lockListenerSocket(handler)) {
224
new_(cleanup, OpenConnectioCleanUp());
227
cleanup->setCleanUp();
228
sock->open(MSNetwork::gListenerSocket);
229
cleanup->cancelCleanUp();
231
handler->lastUse = gCurrentTime;
233
unlockListenerSocket();
240
void MSNetwork::startNetwork()
243
startConnectionHandler();
247
bool MSNetwork::lockListenerSocket(MSConnectionHandler *handler)
249
bool socket_locked = false;
252
if (handler->myMustQuit)
254
lock_(&gListenerLock);
255
if (gListenerSocket) {
256
/* Wait for the listen socket to be freed: */
257
if (gListenerThread) {
259
handler->amWaitingToListen = true;
260
while (gListenerThread) {
261
if (handler->myMustQuit)
264
gListenerLock.wait(2000);
267
/* Catch any error */;
272
handler->amWaitingToListen = false;
274
if (!handler->myMustQuit) {
275
gListenerThread = handler;
276
socket_locked = true;
279
unlock_(&gListenerLock);
280
return_(socket_locked);
283
void MSNetwork::unlockListenerSocket()
286
lock_(&gListenerLock);
287
gListenerThread = NULL;
288
gListenerLock.wakeup();
289
unlock_(&gListenerLock);
293
/* Kill a listener if possible!
294
* Return true if a thread was killed.
296
bool MSNetwork::killListener()
298
MSConnectionHandler *ptr = NULL;
301
lock_(&gListenerLock);
302
if (gListenerThread && gWaitingToListen > 0) {
305
ptr = (MSConnectionHandler *) gHandlerList->getBack();
307
if (ptr->amWaitingToListen) {
308
if (gCurrentTime > ptr->lastUse && (gCurrentTime - ptr->lastUse) > MS_IDLE_THREAD_TIMEOUT) {
309
ptr->myMustQuit = true;
314
ptr = (MSConnectionHandler *) ptr->getNextLink();
316
unlock_(gHandlerList);
318
unlock_(&gListenerLock);