]> git.vomp.tv Git - vompserver.git/blob - mvpserver.c
Raise recording playback get-block limit to 1MB
[vompserver.git] / mvpserver.c
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
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.
10
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.
15
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.
19 */
20
21 #include "mvpserver.h"
22 #ifdef VOMPSTANDALONE
23 #include <iostream>
24 #endif
25
26 extern pthread_mutex_t threadClientMutex;
27
28 MVPServer::MVPServer()
29 {
30   // MH in case anbody has a better position :-)
31   pthread_mutex_init(&threadClientMutex, NULL);
32   tcpServerPort = 0;
33   logoDir = NULL;
34   resourceDir = NULL;
35   imageDir = NULL;
36   cacheDir = NULL;
37 }
38
39 MVPServer::~MVPServer()
40 {
41   if (logoDir) delete[] logoDir;
42   if (resourceDir) delete[] resourceDir;
43   if (imageDir) delete[] imageDir;
44   if (cacheDir) delete[] cacheDir;
45   stop();
46 }
47
48 int MVPServer::stop()
49 {
50   if (threadIsActive()) threadCancel();
51   close(listeningSocket);
52
53   udpr.shutdown();
54   bootpd.shutdown();
55   tftpd.shutdown();
56   mvprelay.shutdown();
57
58   log.log("Main", Log::INFO, "Stopped main server thread");
59   log.shutdown();
60
61   config.shutdown();
62
63   return 1;
64 }
65
66 int MVPServer::run(char* tconfigDir)
67 {
68   if (threadIsActive()) return 1;
69
70   configDir = tconfigDir;
71
72   // Start config
73 #ifdef VOMPSTANDALONE
74 #define dsyslog(x) std::cout << x << std::endl;
75 #endif
76
77   char configFileName[PATH_MAX];
78   snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
79
80   if (config.init(configFileName))
81   {
82     dsyslog("VOMP: Config file found");
83   }
84   else
85   {
86     dsyslog("VOMP: Config file not found");
87   }
88
89   // Start logging
90
91   char* cfgLogFilename = config.getValueString("General", "Log file");
92   if (cfgLogFilename)
93   {
94     log.init(Log::DEBUG, cfgLogFilename);
95     delete[] cfgLogFilename;
96     log.log("Main", Log::INFO, "Logging started");
97   }
98   else
99   {
100     dsyslog("VOMP: Logging disabled");
101   }
102
103   const char *bigresdir = cPlugin::ResourceDirectory();  
104   const char *bigcachedir = cPlugin::CacheDirectory();  
105   // get logo directory
106   logoDir =  config.getValueString("General", "Channel logo directory");
107   
108   if (logoDir) 
109   {
110     log.log("Main", Log::INFO, "LogoDir set %s", logoDir);
111   } else {
112     if (bigresdir) {
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);
116      } else {
117         log.log("Main", Log::INFO, "No LogoDir set, no res dir");
118      }
119         
120   }
121
122   // get epg Image directory
123   imageDir =  config.getValueString("General", "Epg image directory");
124   
125   if (imageDir) 
126   {
127     log.log("Main", Log::INFO, "ImageDir set %s", imageDir);
128   } else {
129     if (bigcachedir) {
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);
133     } else {
134         log.log("Main", Log::INFO, "No ImageDir set, no cache dir");
135     }
136   }
137
138   if (bigresdir) {
139     resourceDir = new char[strlen(bigresdir)+1];
140     strcpy(resourceDir,bigresdir);
141     log.log("Main", Log::INFO, "Resource directory is  %s",bigresdir);
142   } else {
143     log.log("Main", Log::INFO, "Resource directory is  not set");
144   }
145   
146   if (bigcachedir) {
147     cacheDir = new char[strlen(bigcachedir)+1];
148     strcpy(cacheDir,bigcachedir);
149     log.log("Main", Log::INFO, "Cache directory is  %s",bigcachedir);
150   } else {
151     log.log("Main", Log::INFO, "Cache directory is  not set");
152   }
153   // Get UDP port number for discovery service
154
155   int fail = 1;
156   int udpport = config.getValueLong("General", "UDP port", &fail);
157   if (fail) udpport = 51051;  
158   
159   // Work out a name for this server
160
161   char* serverName;
162
163   // Try to get from vomp.conf
164   serverName = config.getValueString("General", "Server name");
165   if (!serverName) // If not, get the hostname
166   {
167     serverName = new char[1024];
168     if (gethostname(serverName, 1024)) // if not, set default
169     {
170       strcpy(serverName, "VOMP Server");
171     }
172   }
173
174   // Get VOMP server TCP port to give to UDP replier to put in packets
175   fail = 1;
176   tcpServerPort = config.getValueLong("General", "TCP port", &fail);
177   if (fail) tcpServerPort = 3024;
178   
179   int udpSuccess = udpr.run(udpport, serverName, tcpServerPort);
180
181   delete[] serverName;
182
183   if (!udpSuccess)
184   {
185     log.log("Main", Log::CRIT, "Could not start UDP replier");
186     stop();
187     return 0;
188   }
189
190   // Read config and start bootp and tftp as appropriate
191
192   char* configString;
193   int bootpEnabled = 0;
194   int tftpEnabled = 0;
195   int mvprelayEnabled = 1;
196
197   configString = config.getValueString("General", "Bootp server enabled");
198   if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1;
199   if (configString) delete[] configString;
200
201   configString = config.getValueString("General", "TFTP server enabled");
202   if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1;
203   if (configString) delete[] configString;
204
205   configString = config.getValueString("General", "MVPRelay enabled");
206   if (configString && (strcasecmp(configString, "yes"))) mvprelayEnabled = 0;
207   if (configString) delete[] configString;
208
209
210   if (bootpEnabled)
211   {
212     if (!bootpd.run(configDir))
213     {
214       log.log("Main", Log::CRIT, "Could not start Bootpd");
215       stop();
216       return 0;
217     }
218   }
219   else
220   {
221     log.log("Main", Log::INFO, "Not starting Bootpd");
222   }
223
224   if (tftpEnabled)
225   {
226     char tftpPath[PATH_MAX];
227
228     configString = config.getValueString("General", "TFTP directory");
229     if (configString)
230     {
231       snprintf(tftpPath, PATH_MAX, "%s", configString);
232
233       // this will never happen.. surely.
234       if ((strlen(tftpPath) + 2) >= PATH_MAX)
235       {
236         delete[] configString;
237         log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
238         stop();
239         return 0;
240       }
241
242       // if there isn't a / at the end of the dir, add one
243       if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
244
245       delete[] configString;
246     }
247     else
248     {
249       snprintf(tftpPath, PATH_MAX, "%s/", configDir);
250     }
251
252     log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
253
254     if (!tftpd.run(tftpPath))
255     {
256       log.log("Main", Log::CRIT, "Could not start TFTPd");
257       stop();
258       return 0;
259     }
260   }
261   else
262   {
263     log.log("Main", Log::INFO, "Not starting TFTPd");
264   }
265
266   // Start mvprelay thread
267   if (mvprelayEnabled)
268   {
269     if (!mvprelay.run())
270     {
271       log.log("Main", Log::CRIT, "Could not start MVPRelay");
272       stop();
273       return 0;
274     }
275     else
276     {
277       log.log("Main", Log::INFO, "MVPRelay started");
278     }
279   }
280   else
281   {
282     log.log("Main", Log::INFO, "Not starting MVPRelay");
283   }
284   
285   // start thread here
286   if (!threadStart())
287   {
288     log.log("Main", Log::CRIT, "Could not start MVPServer thread");
289     stop();
290     return 0;
291   }
292
293   log.log("Main", Log::DEBUG, "MVPServer run success");
294   return 1;
295 }
296
297 void MVPServer::threadMethod()
298 {
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);
302
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);
308
309   listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
310   if (listeningSocket < 0)
311   {
312     log.log("MVPServer", Log::CRIT, "Could not get TCP socket in vompserver");
313     return;
314   }
315
316   int value=1;
317   setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
318
319   if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
320   {
321     log.log("MVPServer", Log::CRIT, "Could not bind to socket in vompserver");
322     close(listeningSocket);
323     return;
324   }
325
326   listen(listeningSocket, 5);
327
328   int clientSocket;
329
330   while(1)
331   {
332     clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
333     VompClient* m = new VompClient(&config, configDir, logoDir, resourceDir, imageDir, cacheDir, clientSocket);
334     m->run();
335   }
336 }
337