]> git.vomp.tv Git - vompserver.git/blob - mvpserver.c
Async server protocol
[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   int mvprelayEnabled = 1;
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   configString = config.getValueString("General", "MVPRelay enabled");
136   if (configString && (strcasecmp(configString, "yes"))) mvprelayEnabled = 0;
137   if (configString) delete[] configString;
138
139
140   if (bootpEnabled)
141   {
142     if (!bootpd.run(configDir))
143     {
144       log.log("Main", Log::CRIT, "Could not start Bootpd");
145       stop();
146       return 0;
147     }
148   }
149   else
150   {
151     log.log("Main", Log::INFO, "Not starting Bootpd");
152   }
153
154   if (tftpEnabled)
155   {
156     char tftpPath[PATH_MAX];
157
158     configString = config.getValueString("General", "TFTP directory");
159     if (configString)
160     {
161       snprintf(tftpPath, PATH_MAX, "%s", configString);
162
163       // this will never happen.. surely.
164       if ((strlen(tftpPath) + 2) >= PATH_MAX)
165       {
166         delete[] configString;
167         log.log("Main", Log::CRIT, "Could not understand TFTP directory from config");
168         stop();
169         return 0;
170       }
171
172       // if there isn't a / at the end of the dir, add one
173       if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/");
174
175       delete[] configString;
176     }
177     else
178     {
179       snprintf(tftpPath, PATH_MAX, "%s/", configDir);
180     }
181
182     log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath);
183
184     if (!tftpd.run(tftpPath))
185     {
186       log.log("Main", Log::CRIT, "Could not start TFTPd");
187       stop();
188       return 0;
189     }
190   }
191   else
192   {
193     log.log("Main", Log::INFO, "Not starting TFTPd");
194   }
195
196   // Start mvprelay thread
197   if (mvprelayEnabled)
198   {
199     if (!mvprelay.run())
200     {
201       log.log("Main", Log::CRIT, "Could not start MVPRelay");
202       stop();
203       return 0;
204     }
205     else
206     {
207       log.log("Main", Log::INFO, "MVPRelay started");
208     }
209   }
210   else
211   {
212     log.log("Main", Log::INFO, "Not starting MVPRelay");
213   }
214   
215   // start thread here
216   if (!threadStart())
217   {
218     log.log("Main", Log::CRIT, "Could not start MVPServer thread");
219     stop();
220     return 0;
221   }
222
223   log.log("Main", Log::DEBUG, "MVPServer run success");
224   return 1;
225 }
226
227 void MVPServer::threadMethod()
228 {
229   // I want to die as soon as I am cancelled because I'll be in accept()
230   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
231   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
232
233   struct sockaddr_in address;
234   address.sin_family = AF_INET;
235   address.sin_port = htons(3024);
236   address.sin_addr.s_addr = INADDR_ANY;
237   socklen_t length = sizeof(address);
238
239   listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
240   if (listeningSocket < 0)
241   {
242     log.log("MVPServer", Log::CRIT, "Could not get TCP socket in vompserver");
243     return;
244   }
245
246   int value=1;
247   setsockopt(listeningSocket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(value));
248
249   if (bind(listeningSocket,(struct sockaddr *)&address,sizeof(address)) < 0)
250   {
251     log.log("MVPServer", Log::CRIT, "Could not bind to socket in vompserver");
252     close(listeningSocket);
253     return;
254   }
255
256   listen(listeningSocket, 5);
257
258   int clientSocket;
259
260   while(1)
261   {
262     clientSocket = accept(listeningSocket,(struct sockaddr *)&address, &length);
263     VompClient* m = new VompClient(&config, configDir, clientSocket);
264     m->run();
265   }
266 }
267