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