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