]> git.vomp.tv Git - vompserver.git/blob - mvpserver.c
Merge branch '0-4-1-dev' of git.vomp.tv:/vompserver
[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 }
34
35 MVPServer::~MVPServer()
36 {
37   stop();
38 }
39
40 int MVPServer::stop()
41 {
42   if (threadIsActive()) threadCancel();
43   close(listeningSocket);
44
45   udpr.shutdown();
46   bootpd.shutdown();
47   tftpd.shutdown();
48   mvprelay.shutdown();
49
50   log.log("Main", Log::INFO, "Stopped main server thread");
51   log.shutdown();
52
53   config.shutdown();
54
55   return 1;
56 }
57
58 int MVPServer::run(char* tconfigDir)
59 {
60   if (threadIsActive()) return 1;
61
62   configDir = tconfigDir;
63
64   // Start config
65 #ifdef VOMPSTANDALONE
66 #define dsyslog(x) std::cout << x << std::endl;
67 #endif
68
69   char configFileName[PATH_MAX];
70   snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir);
71
72   if (config.init(configFileName))
73   {
74     dsyslog("VOMP: Config file found");
75   }
76   else
77   {
78     dsyslog("VOMP: Config file not found");
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   // Get UDP port number for discovery service
96
97   int fail = 1;
98   int udpport = config.getValueLong("General", "UDP port", &fail);
99   if (fail) udpport = 51051;  
100   
101   // Work out a name for this server
102
103   char* serverName;
104
105   // Try to get from vomp.conf
106   serverName = config.getValueString("General", "Server name");
107   if (!serverName) // If not, get the hostname
108   {
109     serverName = new char[1024];
110     if (gethostname(serverName, 1024)) // if not, set default
111     {
112       strcpy(serverName, "VOMP Server");
113     }
114   }
115
116   // Get VOMP server TCP port to give to UDP replier to put in packets
117   fail = 1;
118   tcpServerPort = config.getValueLong("General", "TCP port", &fail);
119   if (fail) tcpServerPort = 3024;
120   
121   int udpSuccess = udpr.run(udpport, serverName, tcpServerPort);
122
123   delete[] serverName;
124
125   if (!udpSuccess)
126   {
127     log.log("Main", Log::CRIT, "Could not start UDP replier");
128     stop();
129     return 0;
130   }
131
132   // Read config and start bootp and tftp as appropriate
133
134   char* configString;
135   int bootpEnabled = 0;
136   int tftpEnabled = 0;
137   int mvprelayEnabled = 1;
138
139   configString = config.getValueString("General", "Bootp server enabled");
140   if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1;
141   if (configString) delete[] configString;
142
143   configString = config.getValueString("General", "TFTP server enabled");
144   if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1;
145   if (configString) delete[] configString;
146
147   configString = config.getValueString("General", "MVPRelay enabled");
148   if (configString && (strcasecmp(configString, "yes"))) mvprelayEnabled = 0;
149   if (configString) delete[] configString;
150
151
152   if (bootpEnabled)
153   {
154     if (!bootpd.run(configDir))
155     {
156       log.log("Main", Log::CRIT, "Could not start Bootpd");
157       stop();
158       return 0;
159     }
160   }
161   else
162   {
163     log.log("Main", Log::INFO, "Not starting Bootpd");
164   }
165
166   if (tftpEnabled)
167   {
168     char tftpPath[PATH_MAX];
169
170     configString = config.getValueString("General", "TFTP directory");
171     if (configString)
172     {
173       snprintf(tftpPath, PATH_MAX, "%s", configString);
174
175       // this will never happen.. surely.
176       if ((strlen(tftpPath) + 2) >= PATH_MAX)
177       {
178         delete[] configString;
179         log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
180         stop();
181         return 0;
182       }
183
184       // if there isn't a / at the end of the dir, add one
185       if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
186
187       delete[] configString;
188     }
189     else
190     {
191       snprintf(tftpPath, PATH_MAX, "%s/", configDir);
192     }
193
194     log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
195
196     if (!tftpd.run(tftpPath))
197     {
198       log.log("Main", Log::CRIT, "Could not start TFTPd");
199       stop();
200       return 0;
201     }
202   }
203   else
204   {
205     log.log("Main", Log::INFO, "Not starting TFTPd");
206   }
207
208   // Start mvprelay thread
209   if (mvprelayEnabled)
210   {
211     if (!mvprelay.run())
212     {
213       log.log("Main", Log::CRIT, "Could not start MVPRelay");
214       stop();
215       return 0;
216     }
217     else
218     {
219       log.log("Main", Log::INFO, "MVPRelay started");
220     }
221   }
222   else
223   {
224     log.log("Main", Log::INFO, "Not starting MVPRelay");
225   }
226   
227   // start thread here
228   if (!threadStart())
229   {
230     log.log("Main", Log::CRIT, "Could not start MVPServer thread");
231     stop();
232     return 0;
233   }
234
235   log.log("Main", Log::DEBUG, "MVPServer run success");
236   return 1;
237 }
238
239 void MVPServer::threadMethod()
240 {
241   // I want to die as soon as I am cancelled because I'll be in accept()
242   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
243   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
244
245   struct sockaddr_in address;
246   address.sin_family = AF_INET;
247   address.sin_port = htons(tcpServerPort);
248   address.sin_addr.s_addr = INADDR_ANY;
249   socklen_t length = sizeof(address);
250
251   listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
252   if (listeningSocket < 0)
253   {
254     log.log("MVPServer", Log::CRIT, "Could not get TCP socket in vompserver");
255     return;
256   }
257
258   int value=1;
259   setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
260
261   if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
262   {
263     log.log("MVPServer", Log::CRIT, "Could not bind to socket in vompserver");
264     close(listeningSocket);
265     return;
266   }
267
268   listen(listeningSocket, 5);
269
270   int clientSocket;
271
272   while(1)
273   {
274     clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
275     VompClient* m = new VompClient(&config, configDir, clientSocket);
276     m->run();
277   }
278 }
279