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