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