GVOHub.cpp
1 |
/***************************************************************************
|
---|---|
2 |
* GVOHub.hpp - VO SAMP Hub class *
|
3 |
* ----------------------------------------------------------------------- *
|
4 |
* copyright (C) 2014 by Juergen Knoedlseder & Thierry Louge *
|
5 |
* ----------------------------------------------------------------------- *
|
6 |
* *
|
7 |
* This program is free software: you can redistribute it and/or modify *
|
8 |
* it under the terms of the GNU General Public License as published by *
|
9 |
* the Free Software Foundation, either version 3 of the License, or *
|
10 |
* (at your option) any later version. *
|
11 |
* *
|
12 |
* This program is distributed in the hope that it will be useful, *
|
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15 |
* GNU General Public License for more details. *
|
16 |
* *
|
17 |
* You should have received a copy of the GNU General Public License *
|
18 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
19 |
* *
|
20 |
***************************************************************************/
|
21 |
/**
|
22 |
* @file GVOHub.cpp
|
23 |
* @brief VO SAMP Hub class implementation
|
24 |
* @author Juergen Knoedlseder, Thierry Louge
|
25 |
*/
|
26 |
|
27 |
/* __ Includes ___________________________________________________________ */
|
28 |
#ifdef HAVE_CONFIG_H
|
29 |
#include <config.h> |
30 |
#endif
|
31 |
#include <cstdlib> // std::getenv() function |
32 |
#include <cstdio> // std::fopen(), etc. functions |
33 |
#include <cstring> // std::memset() function |
34 |
#include <unistd.h> // close() function |
35 |
#include <netdb.h> // getaddrinfo() function |
36 |
#include <sys/socket.h> // socket(), connect() functions |
37 |
#include "GVOHub.hpp" |
38 |
#include "GException.hpp" |
39 |
#include "GTools.hpp" |
40 |
/*==========================================================================
|
41 |
= =
|
42 |
= Constructors/destructors =
|
43 |
= =
|
44 |
==========================================================================*/
|
45 |
|
46 |
/***********************************************************************//** |
47 |
* @brief Void constructor
|
48 |
***************************************************************************/
|
49 |
GVOHub::GVOHub(void)
|
50 |
{ |
51 |
// Initialise members
|
52 |
init_members(); |
53 |
|
54 |
// Creates Hub
|
55 |
init_hub(); |
56 |
|
57 |
// Starts the hub
|
58 |
start_hub(); |
59 |
// Return
|
60 |
return;
|
61 |
} |
62 |
|
63 |
|
64 |
|
65 |
/***********************************************************************//** |
66 |
* @brief Destructor
|
67 |
***************************************************************************/
|
68 |
GVOHub::~GVOHub(void)
|
69 |
{ |
70 |
|
71 |
// Return
|
72 |
return;
|
73 |
} |
74 |
|
75 |
|
76 |
/*==========================================================================
|
77 |
= =
|
78 |
= Public methods =
|
79 |
= =
|
80 |
==========================================================================*/
|
81 |
|
82 |
/***********************************************************************//** |
83 |
* @brief
|
84 |
*
|
85 |
*
|
86 |
***************************************************************************/
|
87 |
void GVOHub::register_service(void) |
88 |
{ |
89 |
|
90 |
// Return
|
91 |
return;
|
92 |
} |
93 |
|
94 |
/***********************************************************************//** |
95 |
* @brief
|
96 |
*
|
97 |
*
|
98 |
***************************************************************************/
|
99 |
void GVOHub::unregister(void) |
100 |
{ |
101 |
|
102 |
// Return
|
103 |
return;
|
104 |
} |
105 |
|
106 |
/*==========================================================================
|
107 |
= =
|
108 |
= Private methods =
|
109 |
= =
|
110 |
==========================================================================*/
|
111 |
/***********************************************************************//** |
112 |
* @brief Initialise class members
|
113 |
***************************************************************************/
|
114 |
void GVOHub::init_members(void) |
115 |
{ |
116 |
// Initialise members
|
117 |
m_name = "GammaLib";
|
118 |
m_secret = "mysupersecret#0032557sentence";
|
119 |
m_hub_url = "http://localhost:8001";
|
120 |
m_hub_host = "127.0.0.1";
|
121 |
m_hub_port = "8001";
|
122 |
m_version = "1.3";
|
123 |
//m_client_key.clear();
|
124 |
m_hub_id = "b79884e0";
|
125 |
//m_client_id.clear();
|
126 |
//m_socket = -1; // Signals no socket
|
127 |
|
128 |
// Return
|
129 |
return;
|
130 |
} |
131 |
/***********************************************************************//** |
132 |
* @brief Creates the lockfile, fill it
|
133 |
*
|
134 |
*
|
135 |
* Implements IVOA standard REC-SAMP-1.3-20120411.
|
136 |
***************************************************************************/
|
137 |
void GVOHub::init_hub(void) |
138 |
{ |
139 |
// Get lockfile URL
|
140 |
std::string lockurl = get_hub_lockfile();
|
141 |
|
142 |
// Open SAMP lockfile. Continue only if opening was successful
|
143 |
FILE* fptr = fopen(lockurl.c_str(), "w");
|
144 |
if (fptr != NULL) { |
145 |
//If successfull writes basic hub configuration to the lockfile
|
146 |
fputs ("# SAMP lockfile \n # Required keys:\n",fptr);
|
147 |
fputs (strcat(strcat("samp.secret= ",m_secret.c_str()),"\n"),fptr); |
148 |
fputs (strcat(strcat("samp.hub.xmlrpc.url=%s",m_hub_url.c_str()),"\n"),fptr); |
149 |
fputs (strcat(strcat("samp.profile.version=%s",m_version.c_str()),"\n"),fptr); |
150 |
fputs ("# Info stored by hub for some private reason:\n",fptr);
|
151 |
fputs (strcat(strcat("com.yoyodyne.hubid=%s",m_hub_id.c_str()),"\n"),fptr); |
152 |
} |
153 |
// Close SAMP lockfile
|
154 |
fclose(fptr); |
155 |
} |
156 |
|
157 |
/***********************************************************************//** |
158 |
* @brief Returns SAMP Hub lockfile URL
|
159 |
*
|
160 |
* @return SAMP Hub lockfile URL (empty if no lockfile was found).
|
161 |
*
|
162 |
* Implements IVOA standard REC-SAMP-1.3-20120411.
|
163 |
***************************************************************************/
|
164 |
std::string GVOHub::get_hub_lockfile(void) const |
165 |
{ |
166 |
// Initialise result
|
167 |
std::string url = ""; |
168 |
|
169 |
// Check for existence of the SAMP_HUB environment variable first
|
170 |
char* hub_ptr = std::getenv("SAMP_HUB"); |
171 |
if (hub_ptr != NULL) { |
172 |
|
173 |
// Check for mandatory std-lockurl: prefix (no other prefixe is
|
174 |
// supported so far)
|
175 |
std::string lockurl = std::string(hub_ptr); |
176 |
if (lockurl.compare(0, 12, "std-lockurl:") == 0) { |
177 |
|
178 |
// Extract URL
|
179 |
url = lockurl.substr(12, std::string::npos); |
180 |
|
181 |
} // endif: std-lockurl: prefix found
|
182 |
|
183 |
} |
184 |
|
185 |
// ... otherwise the lockfile should be $HOME/.samp
|
186 |
else {
|
187 |
|
188 |
// Get user's HOME directory path as the prefix of the full
|
189 |
// path. If the HOME environment variable is not set we
|
190 |
// expect that .samp is in the local directory. This is non
|
191 |
// standard, but prevents for creating an exception here.
|
192 |
std::string prefix = ""; |
193 |
char* home_ptr = std::getenv("HOME"); |
194 |
if (home_ptr != NULL) { |
195 |
prefix = std::string(home_ptr) + "/"; |
196 |
} |
197 |
|
198 |
// Set filename
|
199 |
url = prefix + ".samp";
|
200 |
|
201 |
} // endelse: no SAMP_HUB environment variable found
|
202 |
|
203 |
// Return URL
|
204 |
return url;
|
205 |
} |
206 |
/***********************************************************************//** |
207 |
* @brief Starts the SAMP hub socket and listens on it
|
208 |
*
|
209 |
* @return 1 if error comes out, nothing if everything is right (infinite listening loop)
|
210 |
*
|
211 |
***************************************************************************/
|
212 |
int GVOHub::start_hub(void) |
213 |
{ |
214 |
struct sockaddr_in serv_addr,cli_addr;
|
215 |
int clilen,portno,newsocket,pid,sockfd;
|
216 |
|
217 |
// Prepare TCP/IP structure
|
218 |
bzero((char *) &serv_addr, sizeof(serv_addr)); |
219 |
portno = 8001;
|
220 |
serv_addr.sin_family = AF_INET; |
221 |
serv_addr.sin_addr.s_addr = INADDR_ANY; |
222 |
serv_addr.sin_port = htons(portno); |
223 |
m_socket = socket(AF_INET, SOCK_STREAM, 0);
|
224 |
if (m_socket < 0) |
225 |
{ |
226 |
return(1); |
227 |
} |
228 |
|
229 |
//Server socket is opened. Now, bind it to the port, with family etc.
|
230 |
if (bind(m_socket, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) |
231 |
{ |
232 |
return(1); |
233 |
} |
234 |
|
235 |
//Now start listening for the clients: 5 requests simultaneously maximum
|
236 |
listen(m_socket,5);
|
237 |
clilen = sizeof(cli_addr);
|
238 |
while (1) |
239 |
{ |
240 |
// Accept actual connection from the client
|
241 |
newsocket = accept(m_socket, (struct sockaddr *)&cli_addr,
|
242 |
&clilen); |
243 |
if (newsocket < 0) |
244 |
{ |
245 |
return(1); |
246 |
} |
247 |
// Create child process to handle the request
|
248 |
pid = fork(); |
249 |
if (pid < 0) |
250 |
{ |
251 |
return(1); |
252 |
} |
253 |
if (pid == 0) |
254 |
{ |
255 |
// Child process: client process
|
256 |
close(sockfd); |
257 |
handle_request(newsocket); |
258 |
exit(0);
|
259 |
} |
260 |
else
|
261 |
{ |
262 |
close(newsocket); |
263 |
} |
264 |
} |
265 |
} |
266 |
|
267 |
/***********************************************************************//** |
268 |
* @brief reads the
|
269 |
*
|
270 |
* @return 0 if no problem, 1 if error comes out.
|
271 |
*
|
272 |
***************************************************************************/
|
273 |
void GVOHub::handle_request (int sock) |
274 |
{ |
275 |
int n;
|
276 |
char buffer[256]; |
277 |
|
278 |
bzero(buffer,256);
|
279 |
|
280 |
n = read(sock,buffer,255);
|
281 |
if (n < 0) |
282 |
{ |
283 |
return(1); |
284 |
} |
285 |
printf("Here is the message: %s\n",buffer);
|
286 |
|
287 |
//Here, obviously not simple string matching but xml parsing to be done with
|
288 |
//help of GXml object. This is only for architectural purpose.
|
289 |
if (strcmp(buffer,"register") == 0) { |
290 |
register_service(); |
291 |
} |
292 |
//Same for writing, we'll use GXml
|
293 |
n = write(sock,"I got your message",18); |
294 |
if (n < 0) |
295 |
{ |
296 |
return(1); |
297 |
} |
298 |
return(0); |
299 |
} |