]> git.vomp.tv Git - vompserver.git/blob - mvpserver.c
Fixes for new compiler with const char*, and fix for vdr 1.5
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "mvpserver.h"
22
23 extern pthread_mutex_t threadClientMutex;
24
25 MVPServer::MVPServer()
26 {
27   // MH in case anbody has a better position :-)
28   pthread_mutex_init(&threadClientMutex, NULL);
29 }
30
31 MVPServer::~MVPServer()
32 {
33   stop();
34 }
35
36 int MVPServer::stop()
37 {
38   if (threadIsActive()) threadCancel();
39   close(listeningSocket);
40
41   udpr.shutdown();
42   bootpd.shutdown();
43   tftpd.shutdown();
44   mvprelay.shutdown();
45
46   log.log("Main", Log::INFO, "Stopped main server thread");
47   log.shutdown();
48
49   config.shutdown();
50
51   return 1;
52 }
53
54 int MVPServer::run(char* tconfigDirExtra)
55 {
56   if (threadIsActive()) return 1;
57
58   configDirExtra = tconfigDirExtra;
59
60   // Start config
61   const char* configDir = cPlugin::ConfigDirectory(configDirExtra);
62   if (!configDir)
63   {
64     dsyslog("VOMP: Could not get config dir from VDR");
65   }
66   else
67   {
68     char configFileName[PATH_MAX];
69     snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
70
71     if (config.init(configFileName))
72     {
73       dsyslog("VOMP: Config file found");
74     }
75     else
76     {
77       dsyslog("VOMP: Config file not found");
78     }
79   }
80
81   // Start logging
82
83   char* cfgLogFilename = config.getValueString("General", "Log file");
84   if (cfgLogFilename)
85   {
86     log.init(Log::DEBUG, cfgLogFilename);
87     delete[] cfgLogFilename;
88     log.log("Main", Log::INFO, "Logging started");
89   }
90   else
91   {
92     dsyslog("VOMP: Logging disabled");
93   }
94
95   // Work out a name for this server
96
97   char* serverName;
98
99   // Try to get from vomp.conf
100   serverName = config.getValueString("General", "Server name");
101   if (!serverName) // If not, get the hostname
102   {
103     serverName = new char[1024];
104     if (gethostname(serverName, 1024)) // if not, just use "-"
105     {
106       strcpy(serverName, "-");
107     }
108   }
109
110   int udpSuccess = udpr.run(serverName);
111
112   delete[] serverName;
113
114   if (!udpSuccess)
115   {
116     log.log("Main", Log::CRIT, "Could not start UDP replier");
117     stop();
118     return 0;
119   }
120
121   // Read config and start bootp and tftp as appropriate
122
123   char* configString;
124   int bootpEnabled = 0;
125   int tftpEnabled = 0;
126
127   configString = config.getValueString("General", "Bootp server enabled");
128   if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1;
129   if (configString) delete[] configString;
130
131   configString = config.getValueString("General", "TFTP server enabled");
132   if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1;
133   if (configString) delete[] configString;
134
135
136   if (bootpEnabled)
137   {
138     if (!bootpd.run())
139     {
140       log.log("Main", Log::CRIT, "Could not start Bootpd");
141       stop();
142       return 0;
143     }
144   }
145   else
146   {
147     log.log("Main", Log::INFO, "Not starting Bootpd");
148   }
149
150   if (tftpEnabled)
151   {
152     char tftpPath[PATH_MAX];
153 //    snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
154
155     configString = config.getValueString("General", "TFTP directory");
156     if (configString)
157     {
158       snprintf(tftpPath, PATH_MAX, "%s", configString);
159
160       // this will never happen.. surely.
161       if ((strlen(tftpPath) + 2) >= PATH_MAX)
162       {
163         delete[] configString;
164         log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
165         stop();
166         return 0;
167       }
168
169       // if there isn't a / at the end of the dir, add one
170       if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
171
172       delete[] configString;
173     }
174     else
175     {
176       snprintf(tftpPath, PATH_MAX, "%s/", configDir);
177     }
178
179     log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
180
181     if (!tftpd.run(tftpPath))
182     {
183       log.log("Main", Log::CRIT, "Could not start TFTPd");
184       stop();
185       return 0;
186     }
187   }
188   else
189   {
190     log.log("Main", Log::INFO, "Not starting TFTPd");
191   }
192
193   // Start mvprelay thread
194   if (!mvprelay.run())
195   {
196     log.log("Main", Log::CRIT, "Could not start MVPRelay");
197     stop();
198     return 0;
199   }
200   else
201   {
202     log.log("Main", Log::INFO, "MVPRelay started");
203   }
204
205   // start thread here
206   if (!threadStart())
207   {
208     log.log("Main", Log::CRIT, "Could not start MVPServer thread");
209     stop();
210     return 0;
211   }
212
213   log.log("Main", Log::DEBUG, "MVPServer run success");
214   return 1;
215 }
216
217 void MVPServer::threadMethod()
218 {
219   // I want to die as soon as I am cancelled because I'll be in accept()
220   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
221   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
222
223   struct sockaddr_in address;
224   address.sin_family = AF_INET;
225   address.sin_port = htons(3024);
226   address.sin_addr.s_addr = INADDR_ANY;
227   socklen_t length = sizeof(address);
228
229   listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
230   if (listeningSocket < 0)
231   {
232     log.log("MVPServer", Log::CRIT, "Could not get TCP socket in vompserver");
233     return;
234   }
235
236   int value=1;
237   setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
238
239   if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
240   {
241     log.log("MVPServer", Log::CRIT, "Could not bind to socket in vompserver");
242     close(listeningSocket);
243     return;
244   }
245
246   listen(listeningSocket, 5);
247
248   int clientSocket;
249
250   while(1)
251   {
252     clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
253     MVPClient* m = new MVPClient(&config, configDirExtra, clientSocket);
254     m->run();
255   }
256 }
257