2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "mvpserver.h"
26 extern pthread_mutex_t threadClientMutex;
28 MVPServer::MVPServer()
30 // MH in case anbody has a better position :-)
31 pthread_mutex_init(&threadClientMutex, NULL);
39 MVPServer::~MVPServer()
41 if (logoDir) delete[] logoDir;
42 if (resourceDir) delete[] resourceDir;
43 if (imageDir) delete[] imageDir;
44 if (cacheDir) delete[] cacheDir;
50 if (threadIsActive()) threadCancel();
51 close(listeningSocket);
58 log.log("Main", Log::INFO, "Stopped main server thread");
66 int MVPServer::run(char* tconfigDir)
68 if (threadIsActive()) return 1;
70 configDir = tconfigDir;
74 #define dsyslog(x) std::cout << x << std::endl;
77 char configFileName[PATH_MAX];
78 snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
80 if (config.init(configFileName))
82 dsyslog("VOMP: Config file found");
86 dsyslog("VOMP: Config file not found");
91 char* cfgLogFilename = config.getValueString("General", "Log file");
94 log.init(Log::DEBUG, cfgLogFilename);
95 delete[] cfgLogFilename;
96 log.log("Main", Log::INFO, "Logging started");
100 dsyslog("VOMP: Logging disabled");
103 const char *bigresdir = cPlugin::ResourceDirectory();
104 const char *bigcachedir = cPlugin::CacheDirectory();
105 // get logo directory
106 logoDir = config.getValueString("General", "Channel logo directory");
110 log.log("Main", Log::INFO, "LogoDir set %s", logoDir);
113 logoDir = new char[strlen(bigresdir)+1+7];
114 sprintf(logoDir,"%s/logos/",bigresdir);
115 log.log("Main", Log::INFO, "No LogoDir set, default %s",logoDir);
117 log.log("Main", Log::INFO, "No LogoDir set, no res dir");
122 // get epg Image directory
123 imageDir = config.getValueString("General", "Epg image directory");
127 log.log("Main", Log::INFO, "ImageDir set %s", imageDir);
130 imageDir = new char[strlen(bigcachedir)+1+11+3];
131 sprintf(imageDir,"%s/../epgimages/",bigcachedir);
132 log.log("Main", Log::INFO, "No ImageDir set, default %s",imageDir);
134 log.log("Main", Log::INFO, "No ImageDir set, no cache dir");
139 resourceDir = new char[strlen(bigresdir)+1];
140 strcpy(resourceDir,bigresdir);
141 log.log("Main", Log::INFO, "Resource directory is %s",bigresdir);
143 log.log("Main", Log::INFO, "Resource directory is not set");
147 cacheDir = new char[strlen(bigcachedir)+1];
148 strcpy(cacheDir,bigcachedir);
149 log.log("Main", Log::INFO, "Cache directory is %s",bigcachedir);
151 log.log("Main", Log::INFO, "Cache directory is not set");
153 // Get UDP port number for discovery service
156 int udpport = config.getValueLong("General", "UDP port", &fail);
157 if (fail) udpport = 51051;
159 // Work out a name for this server
163 // Try to get from vomp.conf
164 serverName = config.getValueString("General", "Server name");
165 if (!serverName) // If not, get the hostname
167 serverName = new char[1024];
168 if (gethostname(serverName, 1024)) // if not, set default
170 strcpy(serverName, "VOMP Server");
174 // Get VOMP server TCP port to give to UDP replier to put in packets
176 tcpServerPort = config.getValueLong("General", "TCP port", &fail);
177 if (fail) tcpServerPort = 3024;
179 int udpSuccess = udpr.run(udpport, serverName, tcpServerPort);
185 log.log("Main", Log::CRIT, "Could not start UDP replier");
190 // Read config and start bootp and tftp as appropriate
193 int bootpEnabled = 0;
195 int mvprelayEnabled = 1;
197 configString = config.getValueString("General", "Bootp server enabled");
198 if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1;
199 if (configString) delete[] configString;
201 configString = config.getValueString("General", "TFTP server enabled");
202 if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1;
203 if (configString) delete[] configString;
205 configString = config.getValueString("General", "MVPRelay enabled");
206 if (configString && (strcasecmp(configString, "yes"))) mvprelayEnabled = 0;
207 if (configString) delete[] configString;
212 if (!bootpd.run(configDir))
214 log.log("Main", Log::CRIT, "Could not start Bootpd");
221 log.log("Main", Log::INFO, "Not starting Bootpd");
226 char tftpPath[PATH_MAX];
228 configString = config.getValueString("General", "TFTP directory");
231 snprintf(tftpPath, PATH_MAX, "%s", configString);
233 // this will never happen.. surely.
234 if ((strlen(tftpPath) + 2) >= PATH_MAX)
236 delete[] configString;
237 log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
242 // if there isn't a / at the end of the dir, add one
243 if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
245 delete[] configString;
249 snprintf(tftpPath, PATH_MAX, "%s/", configDir);
252 log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
254 if (!tftpd.run(tftpPath))
256 log.log("Main", Log::CRIT, "Could not start TFTPd");
263 log.log("Main", Log::INFO, "Not starting TFTPd");
266 // Start mvprelay thread
271 log.log("Main", Log::CRIT, "Could not start MVPRelay");
277 log.log("Main", Log::INFO, "MVPRelay started");
282 log.log("Main", Log::INFO, "Not starting MVPRelay");
288 log.log("Main", Log::CRIT, "Could not start MVPServer thread");
293 log.log("Main", Log::DEBUG, "MVPServer run success");
297 void MVPServer::threadMethod()
299 // I want to die as soon as I am cancelled because I'll be in accept()
300 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
301 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
303 struct sockaddr_in address;
304 address.sin_family = AF_INET;
305 address.sin_port = htons(tcpServerPort);
306 address.sin_addr.s_addr = INADDR_ANY;
307 socklen_t length = sizeof(address);
309 listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
310 if (listeningSocket < 0)
312 log.log("MVPServer", Log::CRIT, "Could not get TCP socket in vompserver");
317 setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
319 if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
321 log.log("MVPServer", Log::CRIT, "Could not bind to socket in vompserver");
322 close(listeningSocket);
326 listen(listeningSocket, 5);
332 clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
333 VompClient* m = new VompClient(&config, configDir, logoDir, resourceDir, imageDir, cacheDir, clientSocket);