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