napa-baselibs / ALTOclient / ALTOclient.c @ 5f3adef4
History | View | Annotate | Download (35.8 KB)
1 |
/*
|
---|---|
2 |
============================================================================
|
3 |
Name : ALTOclient.c
|
4 |
Author : T. Ewald <ewald@nw.neclab.eu>
|
5 |
Version : 243
|
6 |
Proprietary : NEC Europe Ltd. PROPRIETARY INFORMATION
|
7 |
This software is supplied under the terms of a license
|
8 |
agreement or nondisclosure agreement with NEC Europe Ltd. and
|
9 |
may not be copied or disclosed except in accordance with the
|
10 |
terms of that agreement. The software and its source code
|
11 |
contain valuable trade secrets and confidential information
|
12 |
which have to be maintained in confidence.
|
13 |
Any unauthorized publication, transfer to third parties or
|
14 |
duplication of the object or source code - either totally or in
|
15 |
part - is prohibited.
|
16 |
Copyright : Copyright (c) 2004 NEC Europe Ltd. All Rights Reserved.
|
17 |
NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR
|
18 |
IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF
|
19 |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND THE
|
20 |
WARRANTY AGAINST LATENT DEFECTS, WITH RESPECT TO THE PROGRAM
|
21 |
AND THE ACCOMPANYING DOCUMENTATION.
|
22 |
No Liability For Consequential Damages IN NO EVENT SHALL NEC
|
23 |
Europe Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE
|
24 |
LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
|
25 |
DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS
|
26 |
OF INFORMATION, OR OTHER PECUNIARY LOSS AND INDIRECT,
|
27 |
CONSEQUENTIAL, INCIDENTAL, ECONOMIC OR PUNITIVE DAMAGES) ARISING
|
28 |
OUT OF THE USE OF OR INABILITY TO USE THIS PROGRAM, EVEN IF NEC
|
29 |
Europe Ltd. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
30 |
Modification: THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
|
31 |
Description : First try of the ALTO client
|
32 |
============================================================================
|
33 |
*/
|
34 |
|
35 |
#include "ALTOclient.h" |
36 |
#include "ALTOclient_impl.h" |
37 |
|
38 |
#include <stdarg.h> |
39 |
#include <pthread.h> |
40 |
|
41 |
/*
|
42 |
* Here the reference to the accessible DBs is set
|
43 |
*/
|
44 |
static altoDbPtr ALTO_DB_req = NULL; // Pointer to the ALTO DB for the Request |
45 |
static altoDbPtr ALTO_DB_res = NULL; // Pointer to the ALTO DB for the Resposne |
46 |
|
47 |
static xmlDocPtr ALTO_XML_req = NULL; // Pointer to the XML for the Request |
48 |
static xmlDocPtr ALTO_XML_res = NULL; // Pointer to the XML for the Request |
49 |
|
50 |
|
51 |
// This is the varaiable where the ALTO server can be found
|
52 |
static char alto_server_url[256]; |
53 |
|
54 |
// And this is the struct where the XML buffer for CURL is cached
|
55 |
#ifdef USE_CURL
|
56 |
static struct curl_reply_buffer_t alto_rep_buf = {ALTO_REP_BUF_SIZE,0,""}; |
57 |
#endif
|
58 |
|
59 |
static char alto_reply_buf_nano[ALTO_REP_BUF_SIZE]; |
60 |
|
61 |
static void alto_debugf(const char* str, ...) { |
62 |
char msg[1024]; |
63 |
va_list args; |
64 |
va_start(args, str); |
65 |
//#ifdef USE_DEBUG_OUTPUT
|
66 |
vsprintf(msg, str, args); |
67 |
//printf("[ALTOclient] %s", msg);
|
68 |
fprintf(stderr, "[ALTOclient] %s", msg);
|
69 |
//#endif
|
70 |
va_end(args); |
71 |
} |
72 |
|
73 |
static void alto_errorf(const char* str, ...) { |
74 |
char msg[1024]; |
75 |
va_list args; |
76 |
va_start(args, str); |
77 |
vsprintf(msg, str, args); |
78 |
fprintf(stderr, "[ALTOclient] *** ERROR: %s", msg);
|
79 |
va_end(args); |
80 |
} |
81 |
|
82 |
#define assertCheck(expr, msg) if(!(expr)) { alto_errorf("%s - Assertion failed: '"#expr"' (%s, line: %d) -- %s\n", __FUNCTION__, __FILE__, __LINE__, msg); exit(-1); } |
83 |
|
84 |
#define returnIf(expr, msg, retval) if(expr) { alto_errorf("%s - Condition check: '"#expr"' (%s, line: %d) -- %s\n", __FUNCTION__, __FILE__, __LINE__, msg); return retval; } |
85 |
|
86 |
/*
|
87 |
* Function to set the actual ALTO server for configuration
|
88 |
*/
|
89 |
int set_ALTO_server(char * string){ |
90 |
// Sanity check
|
91 |
returnIf(string == NULL, "Nothing to set here\n", -1); |
92 |
|
93 |
strncpy(alto_server_url, string, strlen(string)); |
94 |
return 1; |
95 |
} |
96 |
|
97 |
/*
|
98 |
* get the address from the actual set ALTO server;
|
99 |
*/
|
100 |
char *get_ALTO_server(void){ |
101 |
alto_debugf("%s: The ALTO server is set to: %s \n", __FUNCTION__, alto_server_url);
|
102 |
return (char *) alto_server_url; |
103 |
} |
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
/*
|
113 |
* Func: Convert the "Baschtl" notation into a readable
|
114 |
* format (get IP address)
|
115 |
* in: *host_string Pointer to the string to convert
|
116 |
* return: IP Struct where the IP and prefix is encoded
|
117 |
*/
|
118 |
struct in_addr get_ALTO_host_IP(char * host_string){ |
119 |
struct in_addr IP;
|
120 |
#ifdef WIN32
|
121 |
char * str_buff = new char[strlen(host_string)]; |
122 |
#else
|
123 |
char str_buff[strlen(host_string)];
|
124 |
#endif
|
125 |
strncpy(str_buff,host_string,strlen(host_string)); |
126 |
char *result = NULL; |
127 |
result = strchr(str_buff, '/');
|
128 |
if(result != NULL) { |
129 |
*result = 0;
|
130 |
IP.s_addr = inet_addr(str_buff); |
131 |
return IP;
|
132 |
}if(inet_addr(host_string) != (-1)){ |
133 |
IP.s_addr = inet_addr(host_string); |
134 |
return IP;
|
135 |
} |
136 |
alto_debugf("%s: No IP found\n!!!", __FUNCTION__);
|
137 |
#ifdef WIN32
|
138 |
delete [] str_buff; |
139 |
#endif
|
140 |
return IP;
|
141 |
} |
142 |
|
143 |
|
144 |
|
145 |
|
146 |
/*
|
147 |
* Func: Convert the "Baschtl" notation into a readable format
|
148 |
* (get prefix)
|
149 |
* in: *host Pointer to the string to convert
|
150 |
* return: port struct where the IP and prefix is encoded
|
151 |
*/
|
152 |
int16_t get_ALTO_host_mask(char * host_string){
|
153 |
int16_t res; |
154 |
char *result = NULL; |
155 |
char str_buff[256]; |
156 |
|
157 |
memset(str_buff, 0, 256); |
158 |
strncpy(str_buff,host_string,strlen(host_string)); |
159 |
result = strchr(str_buff, '/');
|
160 |
if(result != NULL) { |
161 |
result++; |
162 |
res = atoi(result); |
163 |
return res;
|
164 |
} |
165 |
// if it can't be found, it was a single host so mask is 32 bit
|
166 |
return 32; |
167 |
} |
168 |
|
169 |
|
170 |
/*
|
171 |
* Func: Create an ALTO XML request from a given DB
|
172 |
*
|
173 |
* in: *db the pointer to the DB with the elements
|
174 |
rc_host the in_addr of the requesting host
|
175 |
* ret: XML_doc the XML where the request is stored in
|
176 |
*/
|
177 |
xmlDocPtr alto_create_request_XML(struct alto_db_t * db, struct in_addr rc_host, int pri_rat, int sec_rat){ |
178 |
assertCheck(db, "internal db ptr is NULL!");
|
179 |
|
180 |
// Creates a new document
|
181 |
// <?xml version="1.0" encoding="UTF-8"?>
|
182 |
xmlDocPtr doc = NULL; /* document pointer */ |
183 |
doc = xmlNewDoc(BAD_CAST "1.0");
|
184 |
|
185 |
assertCheck(doc, "xmlNewDoc failed! Out of memory?");
|
186 |
|
187 |
// Create the root node and name it with the correct name space
|
188 |
// <alto xmlns='urn:ietf:params:xml:ns:p2p:alto'>
|
189 |
// Dirty!!! Because NS is here an attribute
|
190 |
// [TODO namespace declaration]
|
191 |
xmlNodePtr root_node = NULL;
|
192 |
root_node = xmlNewNode(NULL, BAD_CAST "alto"); |
193 |
xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:p2p:alto",NULL); |
194 |
|
195 |
// link it to the document
|
196 |
xmlDocSetRootElement(doc, root_node); |
197 |
|
198 |
// Creates a DTD declaration. Isn't mandatory.
|
199 |
// [TODO introduce DTDs by time]
|
200 |
// xmlDtdPtr dtd = NULL; /* DTD pointer */
|
201 |
// dtd = xmlCreateIntSubset(doc, BAD_CAST "root", NULL, BAD_CAST "tree2.dtd");
|
202 |
|
203 |
// Here create the group rating request (node_GRR)
|
204 |
// <group_rating_request db_version='1234'>\n"
|
205 |
xmlNodePtr node_GRR = NULL;
|
206 |
node_GRR = xmlNewChild(root_node, NULL, BAD_CAST "group_rating_request", NULL); |
207 |
xmlNewProp(node_GRR, BAD_CAST "db_version", BAD_CAST "1234"); |
208 |
|
209 |
// Now create the primary rating criteria
|
210 |
// <pri_ratcrit crit='pref'/>
|
211 |
xmlNodePtr node_PRI = NULL;
|
212 |
node_PRI = xmlNewChild(node_GRR, NULL, BAD_CAST "pri_ratcrit", NULL); |
213 |
if(pri_rat == REL_PREF){
|
214 |
xmlNewProp(node_PRI, BAD_CAST "crit", BAD_CAST "pref"); |
215 |
}else if(pri_rat == TOP_DIST){ |
216 |
xmlNewProp(node_PRI, BAD_CAST "crit", BAD_CAST "dist"); |
217 |
}else if(pri_rat == MIN_BOUN){ |
218 |
xmlNewProp(node_PRI, BAD_CAST "crit", BAD_CAST "lat"); |
219 |
} |
220 |
|
221 |
|
222 |
// Add the additional rating criteria
|
223 |
if((sec_rat & REL_PREF) == REL_PREF){
|
224 |
xmlNodePtr node_SEC1 = NULL;
|
225 |
node_SEC1 = xmlNewChild(node_GRR, NULL, BAD_CAST "fur_ratcrit", NULL); |
226 |
xmlNewProp(node_SEC1, BAD_CAST "crit", BAD_CAST "pref"); |
227 |
} |
228 |
if((sec_rat & TOP_DIST) == TOP_DIST){
|
229 |
xmlNodePtr node_SEC2 = NULL;
|
230 |
node_SEC2 = xmlNewChild(node_GRR, NULL, BAD_CAST "fur_ratcrit", NULL); |
231 |
xmlNewProp(node_SEC2, BAD_CAST "crit", BAD_CAST "dist"); |
232 |
} |
233 |
if((sec_rat & MIN_BOUN) == MIN_BOUN){
|
234 |
xmlNodePtr node_SEC4 = NULL;
|
235 |
node_SEC4 = xmlNewChild(node_GRR, NULL, BAD_CAST "fur_ratcrit", NULL); |
236 |
xmlNewProp(node_SEC4, BAD_CAST "crit", BAD_CAST "lat"); |
237 |
} |
238 |
|
239 |
|
240 |
// Now create the source of the request
|
241 |
// <rc_hla><ipprefix version='4' prefix='195.37.70.39/32'/></rc_hla>
|
242 |
xmlNodePtr node_RC_HLA = NULL;
|
243 |
node_RC_HLA = xmlNewChild(node_GRR, NULL, BAD_CAST "rc_hla", NULL); |
244 |
|
245 |
// and within the actual source
|
246 |
// <ipprefix version='4' prefix='195.37.70.39/32'/>
|
247 |
xmlNodePtr node_IPP = NULL;
|
248 |
node_IPP = xmlNewChild(node_RC_HLA, NULL, BAD_CAST "ipprefix", NULL); |
249 |
xmlNewProp(node_IPP, BAD_CAST "version", BAD_CAST "4"); |
250 |
// xmlNewProp(node_IPP, BAD_CAST "prefix", BAD_CAST "195.37.70.39/32");
|
251 |
char rc_host_str[256]; |
252 |
strcpy(rc_host_str, inet_ntoa(rc_host)); |
253 |
// TODO: really dirty, but it should work
|
254 |
strcat(rc_host_str,"/32");
|
255 |
xmlNewProp(node_IPP, BAD_CAST "prefix", BAD_CAST rc_host_str);
|
256 |
|
257 |
// Now prepare the request
|
258 |
// <cnd_hla>
|
259 |
xmlNodePtr node_HLA = NULL;
|
260 |
node_HLA = xmlNewChild(node_GRR, NULL, BAD_CAST "cnd_hla", NULL); |
261 |
|
262 |
// So far it went quite well, now try to create the host list
|
263 |
// from the given ALTO_LIST
|
264 |
// so create something like this:
|
265 |
// <ipprefix version='4' prefix='195.37.70.39/32'/>
|
266 |
char tmp_buff[256]; |
267 |
struct alto_db_element_t * cur;
|
268 |
cur = db->first; |
269 |
//while(cur->next != NULL){ // armin 12-jul-2010, bug reported by Andrzej
|
270 |
while(cur != NULL){ |
271 |
node_IPP = xmlNewChild(node_HLA, NULL, BAD_CAST "ipprefix", NULL); |
272 |
xmlNewProp(node_IPP, BAD_CAST "version", BAD_CAST "4"); |
273 |
sprintf(tmp_buff,"%s/%d",inet_ntoa(cur->host), cur->host_mask);
|
274 |
xmlNewProp(node_IPP, BAD_CAST "prefix", BAD_CAST tmp_buff);
|
275 |
cur = cur->next; |
276 |
} |
277 |
|
278 |
// Dump for checking
|
279 |
#ifdef USE_DEBUG_OUTPUT
|
280 |
xmlDocDump(stdout, doc); |
281 |
#endif
|
282 |
|
283 |
|
284 |
// Free the global variables that may have been allocated by the parser.
|
285 |
//xmlCleanupParser(); // armin 22-jul-2010: Should only be done upon exit
|
286 |
// see libxml2 docu
|
287 |
|
288 |
// return the finsihed XML
|
289 |
return doc;
|
290 |
} |
291 |
|
292 |
/*==================================
|
293 |
libCURL-based POST code
|
294 |
==================================*/
|
295 |
|
296 |
// libcurl is now obsolete!
|
297 |
#ifdef USE_CURL
|
298 |
|
299 |
// this function will be registered with curl as a handler, which
|
300 |
// copies the http reply to a the buffer
|
301 |
size_t curl_copy_reply_to_buf(void *ptr,size_t size,size_t nmemb,void *stream){ |
302 |
size_t realsize = size * nmemb; |
303 |
struct curl_reply_buffer_t *crb = (struct curl_reply_buffer_t *)stream; |
304 |
// error: new chunk plus trailing zero would not fit into remaining buffer
|
305 |
if( (realsize+1) > (crb->size - crb->fill) ) return 0; |
306 |
memcpy( &crb->buffer[crb->fill], ptr, realsize ); |
307 |
crb->fill += realsize; |
308 |
crb->buffer[crb->fill] = 0;
|
309 |
return realsize;
|
310 |
} |
311 |
uint16_t prefixes = 0;
|
312 |
|
313 |
|
314 |
|
315 |
xmlDocPtr query_ALTO_server_curl(xmlDocPtr doc, char* ALTO_server_URL){
|
316 |
xmlDocPtr ALTO_XML_response; |
317 |
|
318 |
// starting here the ALTO list will be send out.....
|
319 |
CURL *curl; |
320 |
CURLcode res; |
321 |
struct curl_httppost *formpost=NULL; |
322 |
struct curl_httppost *lastptr=NULL; |
323 |
|
324 |
curl = curl_easy_init(); |
325 |
assertCheck(curl, "Couldn't get a handle from curl_easy_init(). abort.");
|
326 |
|
327 |
// printf("Will send HTTP POST to %s\nwith form data:\n\n%s\n", alto_server_url, ALTO_XML_query);
|
328 |
|
329 |
// prepare the buffer to be send
|
330 |
xmlChar* doctxt; |
331 |
int doclen;
|
332 |
xmlDocDumpFormatMemoryEnc(doc,&doctxt,&doclen,"utf-8",1); |
333 |
|
334 |
// URL that receives this POST
|
335 |
curl_easy_setopt(curl, CURLOPT_URL, ALTO_server_URL); |
336 |
|
337 |
// add form data
|
338 |
curl_formadd(&formpost, |
339 |
&lastptr, |
340 |
CURLFORM_COPYNAME, "alto_xml_request",
|
341 |
// CURLFORM_COPYCONTENTS, ALTO_XML_query,
|
342 |
CURLFORM_COPYCONTENTS, doctxt, |
343 |
CURLFORM_END); |
344 |
|
345 |
curl_formadd(&formpost, |
346 |
&lastptr, |
347 |
CURLFORM_COPYNAME, "action",
|
348 |
CURLFORM_COPYCONTENTS, "submit",
|
349 |
CURLFORM_END); |
350 |
|
351 |
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
352 |
|
353 |
// we do not want the reply written to stdout but to our buffer
|
354 |
alto_rep_buf.fill = 0; // reset buffer (armin 12-jul-2010, reported by Andrzej) |
355 |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_copy_reply_to_buf); |
356 |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &alto_rep_buf); |
357 |
|
358 |
// do it!
|
359 |
res = curl_easy_perform(curl); |
360 |
|
361 |
// always cleanup
|
362 |
curl_easy_cleanup(curl); |
363 |
|
364 |
// then cleanup the form post chain
|
365 |
curl_formfree(formpost); |
366 |
|
367 |
// printf("result of curl_easy_perform() is: %i\n", res);
|
368 |
// printf("received %i octetts. the buffer is:\n\n%s\nthat's all. bye.\n",alto_rep_buf.fill,alto_rep_buf.buffer);
|
369 |
|
370 |
|
371 |
// and last but nor least, transform it into an XML doc
|
372 |
ALTO_XML_response = xmlRecoverMemory(alto_rep_buf.buffer,sizeof(alto_rep_buf.buffer)); // <- for getting XML from memory |
373 |
|
374 |
return ALTO_XML_response;
|
375 |
} |
376 |
|
377 |
#endif // USE_CURL |
378 |
|
379 |
/*==================================
|
380 |
libxml2 nanohttp based POST code
|
381 |
==================================*/
|
382 |
|
383 |
#define POST_BOUNDARY "---------------------------12408751047121013601852724877" |
384 |
|
385 |
void POST_add(char* buf, const char* name, const char* value) { |
386 |
sprintf(buf+strlen(buf), "--"POST_BOUNDARY"\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", name, value); |
387 |
} |
388 |
|
389 |
void POST_end(char* buf) { |
390 |
sprintf(buf+strlen(buf), "--"POST_BOUNDARY"--\r\n\r\n"); |
391 |
} |
392 |
|
393 |
void* POST_send(const char* url, const char* data) { |
394 |
int i;
|
395 |
void* ctx = NULL; |
396 |
char header[] = "Connection: close\r\n"; |
397 |
char contentType[] = "multipart/form-data; boundary="POST_BOUNDARY; |
398 |
char* ct = contentType;
|
399 |
|
400 |
assertCheck(url, "ALTO server URL is NULL!");
|
401 |
assertCheck(data, "POST data is NULL!");
|
402 |
|
403 |
//ctx = xmlNanoHTTPMethod(url, "POST", data, &ct, NULL, strlen(data));
|
404 |
for (i=0; i < 3; i++) { |
405 |
ctx = xmlNanoHTTPMethod(url, "POST", data, &ct, header, strlen(data)+1); |
406 |
if (ctx) break; |
407 |
} |
408 |
|
409 |
if (!ctx) {
|
410 |
alto_debugf("*** WARNING: xmlNanoHTTPMethod failed! Make sure ALTO server is reachable (NAT issue?)..");
|
411 |
fprintf(stderr, "URL was '%s'.", url);
|
412 |
return NULL; |
413 |
} |
414 |
assertCheck(ctx, "xmlNanoHTTPMethod failed! Make sure ALTO server is reachable (NAT issue?)..");
|
415 |
|
416 |
free(ct); |
417 |
return ctx;
|
418 |
} |
419 |
|
420 |
// nano
|
421 |
xmlDocPtr ALTO_request_to_server(xmlDocPtr doc, char* endPoint){
|
422 |
xmlDocPtr result = NULL;
|
423 |
xmlChar* doctxt = NULL;
|
424 |
int size = 0; |
425 |
int doclen = 0; |
426 |
int bytesRead = 0; |
427 |
int bytesSum = 0; |
428 |
char* data = NULL; |
429 |
size_t dataLen = 0;
|
430 |
void* ctx = NULL; |
431 |
char* alto_reply_buffer_ptr = alto_reply_buf_nano;
|
432 |
// int errorcode = 0;
|
433 |
// FILE* f = NULL;
|
434 |
|
435 |
assertCheck(doc, "xml doc ptr is NULL!");
|
436 |
assertCheck(endPoint, "ALTO server URL is NULL!");
|
437 |
|
438 |
xmlNanoHTTPInit(); |
439 |
xmlDocDumpFormatMemoryEnc(doc,&doctxt,&doclen,"utf-8",1); |
440 |
|
441 |
dataLen = doclen + 2048;
|
442 |
data = malloc(dataLen); |
443 |
assertCheck(data, "Couldn't allocate data buffer! Out of memory?");
|
444 |
memset(data, 0, dataLen);
|
445 |
|
446 |
// build the mime multipart contents
|
447 |
POST_add(data, "alto_xml_request", doctxt);
|
448 |
POST_add(data, "action", "submit"); |
449 |
POST_end(data); |
450 |
|
451 |
//printf("data:\n\n%s", data);
|
452 |
xmlFree(doctxt); // free temp buffer
|
453 |
|
454 |
alto_debugf("%s: POST begin...\n", __FUNCTION__);
|
455 |
|
456 |
// send it
|
457 |
ctx = POST_send(endPoint, data); |
458 |
|
459 |
free(data); |
460 |
data = NULL;
|
461 |
|
462 |
if (!ctx) return NULL; |
463 |
|
464 |
alto_debugf("%s: POST ok.\n", __FUNCTION__);
|
465 |
|
466 |
memset(alto_reply_buf_nano, 0, ALTO_REP_BUF_SIZE);
|
467 |
|
468 |
// bytesSum = xmlNanoHTTPRead(ctx, &alto_reply_buf_nano, ALTO_REP_BUF_SIZE);
|
469 |
#define BLOCK_SIZE 4096 |
470 |
bytesRead = xmlNanoHTTPRead(ctx, alto_reply_buffer_ptr, BLOCK_SIZE); |
471 |
bytesSum += bytesRead; |
472 |
while (bytesRead) {
|
473 |
alto_reply_buffer_ptr += bytesRead; |
474 |
bytesRead = xmlNanoHTTPRead(ctx, alto_reply_buffer_ptr, BLOCK_SIZE); |
475 |
bytesSum += bytesRead; |
476 |
} |
477 |
|
478 |
#ifdef USE_DEBUG_OUTPUT
|
479 |
// printf("xmlNanoHTTPRead: %d bytes read.\n", bytesRead);
|
480 |
printf("ALTO reply (%d bytes):\n\n%s", bytesSum, alto_reply_buf_nano);
|
481 |
#endif
|
482 |
|
483 |
// dump to file
|
484 |
/* f = fopen("http_reply.txt", "wt");
|
485 |
fwrite(output, 1, strlen(output), f);
|
486 |
fclose(f);*/
|
487 |
|
488 |
result = xmlRecoverMemory(alto_reply_buf_nano, bytesSum); |
489 |
//
|
490 |
// TODO: PushParser doesn't work yet somehow..
|
491 |
//
|
492 |
/*
|
493 |
xmlParserCtxtPtr pushCtx = NULL;
|
494 |
pushCtx = xmlCreatePushParserCtxt(NULL, NULL, output, bytesRead, NULL);
|
495 |
// xmlInitParserCtxt(pushCtx);
|
496 |
|
497 |
if (!pushCtx) {
|
498 |
printf("ERROR: xmlCreatePushParserCtxt failed!\n");
|
499 |
} else {
|
500 |
printf("xmlCreatePushParserCtxt ok.\n");
|
501 |
}
|
502 |
|
503 |
while (bytesRead) {
|
504 |
if(xmlParseChunk(pushCtx, output, bytesRead, 0) != 0) {
|
505 |
printf("ERROR: xmlParseChunk failed!\n");
|
506 |
} else {
|
507 |
printf("xmlParseChunk ok.\n");
|
508 |
}
|
509 |
bytesRead = xmlNanoHTTPRead(ctx,&output,10024);
|
510 |
printf("xmlNanoHTTPRead: %d bytes read.\n", bytesRead);
|
511 |
}
|
512 |
|
513 |
printf("Finalizing...\n");
|
514 |
errorcode = xmlParseChunk(pushCtx, output, 0, 1);
|
515 |
if(errorcode) {
|
516 |
printf("ERROR: Final xmlParseChunk failed! errorcode=%d\n", errorcode);
|
517 |
} else {
|
518 |
printf("Final xmlParseChunk ok.\n");
|
519 |
}
|
520 |
|
521 |
result = pushCtx->myDoc;
|
522 |
xmlFreeParserCtxt(pushCtx);
|
523 |
*/
|
524 |
|
525 |
if (!result) {
|
526 |
printf("*** ERROR: ALTO XML reply (%d bytes):\n\n%s", bytesSum, alto_reply_buf_nano);
|
527 |
alto_errorf("%s - XML parsing failed (result == NULL)!\n", __FUNCTION__);
|
528 |
} else {
|
529 |
alto_debugf("%s: XML parsing ok.\n", __FUNCTION__);
|
530 |
} |
531 |
|
532 |
xmlNanoHTTPClose(ctx); |
533 |
xmlNanoHTTPCleanup(); |
534 |
return result;
|
535 |
} |
536 |
|
537 |
|
538 |
|
539 |
|
540 |
/*
|
541 |
*
|
542 |
* HERE is the magic for the internal DB management
|
543 |
*
|
544 |
*/
|
545 |
|
546 |
/*
|
547 |
* Initialize a ALTO DB structure
|
548 |
*/
|
549 |
struct alto_db_t * alto_db_init(void){ |
550 |
alto_debugf("%s: Initialize an ALTO database! \n", __FUNCTION__);
|
551 |
struct alto_db_t * db;
|
552 |
db = malloc(sizeof(struct alto_db_t)); |
553 |
// db = (alto_db_t *)malloc(sizeof(struct alto_db_element_t));
|
554 |
assertCheck(db, "Couldn't allocate internal db! Out of memory?");
|
555 |
|
556 |
db->first = NULL;
|
557 |
db->last = NULL;
|
558 |
db->num_of_elements = 0;
|
559 |
return db;
|
560 |
} |
561 |
|
562 |
/*
|
563 |
* Kill the DB structure
|
564 |
*/
|
565 |
int alto_free_db(struct alto_db_t * db){ |
566 |
int res = 1; |
567 |
alto_debugf("%s: Clean and free ALTO database (%p)! \n", __FUNCTION__, db);
|
568 |
returnIf(db == NULL, "No DB to be free'd.", -1); |
569 |
|
570 |
res = alto_purge_db(db); |
571 |
|
572 |
// Free the DB struct & Goodby!
|
573 |
free(db); |
574 |
return res;
|
575 |
} |
576 |
|
577 |
/*
|
578 |
* Clean/Remove all elements from the DB structure
|
579 |
*/
|
580 |
int alto_purge_db(struct alto_db_t * db){ |
581 |
// alto_debugf("%s: Purge the ALTO database (%p)! \n", __FUNCTION__, db);
|
582 |
returnIf(db == NULL, "No DB to be purged.", -1); |
583 |
|
584 |
// Now kill every single element
|
585 |
struct alto_db_element_t * cur;
|
586 |
cur = db->first; |
587 |
while(cur != NULL){ |
588 |
alto_rem_element(cur); |
589 |
cur = db->first; //cur->next; // armin 12-jul-2010, bug reported by Andrzej
|
590 |
} |
591 |
|
592 |
return 1; |
593 |
} |
594 |
|
595 |
|
596 |
|
597 |
/*
|
598 |
* Helper function to print values of one ALTO DB element
|
599 |
*/
|
600 |
void alto_dump_element(struct alto_db_element_t * cur){ |
601 |
// Sanity check
|
602 |
assertCheck(cur == NULL, "No element to print values from! ABORT"); |
603 |
|
604 |
// normal case, print everything
|
605 |
// fprintf(stdout, "---> Internal Data\t");
|
606 |
// fprintf(stdout, "Element ptr : %p \t", cur);
|
607 |
// fprintf(stdout, "DB pointer : %p \t", cur->alto_db);
|
608 |
// fprintf(stdout, "next pointer : %p \t", cur->next);
|
609 |
// fprintf(stdout, "prev pointer : %p \t", cur->prev);
|
610 |
alto_debugf("---> User Data\t");
|
611 |
alto_debugf("host : %s \t", inet_ntoa(cur->host));
|
612 |
alto_debugf("prefix: %d \t", cur->host_mask);
|
613 |
alto_debugf("rating: %d \t", cur->rating);
|
614 |
// fprintf(stdout, "---> Additional Data\n");
|
615 |
// fprintf(stdout, "Subnet : %s \t", inet_ntoa(cur->subnet));
|
616 |
// fprintf(stdout, "bit mask : %d \t", cur->subnet_mask);
|
617 |
alto_debugf("\n");
|
618 |
return;
|
619 |
} |
620 |
|
621 |
/*
|
622 |
* Helper function to print values of one ALTO DB element
|
623 |
*/
|
624 |
void alto_dump_db(struct alto_db_t *db){ |
625 |
alto_debugf("Dump what's in the DB \n");
|
626 |
|
627 |
// Security Check
|
628 |
assertCheck(db, "Failure in DB structure! ABORT");
|
629 |
|
630 |
// General Data
|
631 |
alto_debugf("Number of elements in DB: %d \n", db->num_of_elements);
|
632 |
alto_debugf("DB->first: %p \n", db->first);
|
633 |
alto_debugf("DB->last: %p \n", db->last);
|
634 |
|
635 |
// List the elements
|
636 |
struct alto_db_element_t * cur;
|
637 |
cur = db->first; |
638 |
while(cur != NULL){ |
639 |
alto_dump_element(cur); |
640 |
cur = cur->next; |
641 |
} |
642 |
|
643 |
// Success!?
|
644 |
return;
|
645 |
} |
646 |
|
647 |
|
648 |
|
649 |
|
650 |
/*
|
651 |
* Adds one ALTO entry to the DB
|
652 |
*/
|
653 |
int alto_add_element(struct alto_db_t * db, struct alto_db_element_t * element){ |
654 |
// fprintf(stdout, "Add an element to the ALTO DB! \n");
|
655 |
|
656 |
// Error handling
|
657 |
returnIf((db == NULL || element == NULL), "Error in appending element on the DB! ABORT", -1); |
658 |
|
659 |
// Special case, first element in DB
|
660 |
if(db->first == NULL && db->last == NULL){ |
661 |
|
662 |
// Update DB
|
663 |
db->first = element; |
664 |
db->last = element; |
665 |
db->num_of_elements = 1;
|
666 |
|
667 |
// Update element
|
668 |
element->next = NULL;
|
669 |
element->prev = NULL;
|
670 |
element->alto_db = db; |
671 |
element->stamp = time(NULL);
|
672 |
|
673 |
// And success
|
674 |
return 1; |
675 |
} |
676 |
|
677 |
// Normal case, append element at the end of the list
|
678 |
// Update predecessor
|
679 |
db->last->next = element; |
680 |
|
681 |
// Update element
|
682 |
element->prev = db->last; |
683 |
element->next = NULL;
|
684 |
element->alto_db = db; |
685 |
element->stamp = time(NULL);
|
686 |
|
687 |
// Update DB
|
688 |
db->last = element; |
689 |
db->num_of_elements++; |
690 |
|
691 |
// This should be it
|
692 |
return 1; |
693 |
} |
694 |
|
695 |
int alto_rem_element(struct alto_db_element_t * element){ |
696 |
|
697 |
// Sanity Check
|
698 |
returnIf(element == NULL, "element == NULL! ABORT", -1); |
699 |
|
700 |
// Now get the DB where the element is in
|
701 |
struct alto_db_t *db;
|
702 |
db = element->alto_db; |
703 |
|
704 |
// Special case, last and only element in DB
|
705 |
if(db->first == element && db->last == element){
|
706 |
// update main DB
|
707 |
db->first = NULL;
|
708 |
db->last = NULL;
|
709 |
db->num_of_elements = 0;
|
710 |
// free element
|
711 |
free(element); |
712 |
// exit
|
713 |
return 1; |
714 |
} |
715 |
|
716 |
// Special case, first element in chain
|
717 |
if(db->first == element && db->last != element){
|
718 |
// Update successor
|
719 |
element->next->prev = NULL;
|
720 |
// Update DB
|
721 |
db->first = element->next; |
722 |
db->num_of_elements--; |
723 |
// free element
|
724 |
free(element); |
725 |
// exit
|
726 |
return 1; |
727 |
} |
728 |
|
729 |
// Special case, last element in chain
|
730 |
if(db->first != element && db->last == element){
|
731 |
// Update predecessor
|
732 |
element->prev->next = NULL;
|
733 |
// Update DB
|
734 |
db->last = element->prev; |
735 |
db->num_of_elements--; |
736 |
// free element
|
737 |
free(element); |
738 |
// exit
|
739 |
return 1; |
740 |
} |
741 |
|
742 |
|
743 |
// normal handling, somwhere in the DB
|
744 |
else {
|
745 |
// update predecessor
|
746 |
element->prev->next = element->next; |
747 |
element->next->prev = element->prev; |
748 |
// Update DB
|
749 |
db->num_of_elements--; |
750 |
// free element
|
751 |
free(element); |
752 |
// exit
|
753 |
return 1; |
754 |
} |
755 |
|
756 |
// Just in case something went wrong
|
757 |
// what NEVER will happen
|
758 |
alto_errorf("%s - Error in removing element function!\n", __FUNCTION__);
|
759 |
return -1; |
760 |
} |
761 |
|
762 |
|
763 |
struct in_addr compute_subnet(struct in_addr host, int prefix){ |
764 |
struct in_addr subn;
|
765 |
uint32_t match_host = host.s_addr; |
766 |
uint32_t match_mask = 0xFFFFFFFF;
|
767 |
match_mask <<= 32 - prefix;
|
768 |
match_mask = ntohl(match_mask); |
769 |
uint32_t match_merg = match_host & match_mask; |
770 |
// printf("host : %s/%d \t", inet_ntoa(host), prefix);
|
771 |
// subn.s_addr = match_mask;
|
772 |
// printf("mask : %s \t", inet_ntoa(subn));
|
773 |
subn.s_addr = match_merg; |
774 |
// printf("net : %s \n", inet_ntoa(subn));
|
775 |
return subn;
|
776 |
} |
777 |
|
778 |
|
779 |
|
780 |
/*
|
781 |
* Search in an ALTO DB for the match of an host
|
782 |
*
|
783 |
* value: add Address of the host to search for
|
784 |
* db The ALTO DB to search in
|
785 |
* return: value/0 The found value / 0 in case of nothing
|
786 |
*/
|
787 |
int get_ALTO_rating_for_host(struct in_addr add, ALTO_DB_T * db){ |
788 |
|
789 |
// Sanity checks
|
790 |
returnIf(add.s_addr == 0, "Couldn't read the ALTO host IP to query! ABORT", 0); |
791 |
returnIf(db == NULL, "Couldn't access the DB! ABORT", 0); |
792 |
|
793 |
// walk through the DB until you find the element
|
794 |
struct alto_db_element_t * cur;
|
795 |
cur = db->first; |
796 |
while(cur != NULL){ |
797 |
if(cur->host.s_addr == add.s_addr){
|
798 |
return cur->rating;
|
799 |
} |
800 |
cur = cur->next; |
801 |
} |
802 |
|
803 |
// Here you come in case of error/not found!
|
804 |
return 0; |
805 |
} |
806 |
|
807 |
|
808 |
|
809 |
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
|
815 |
int ask_helper_func(struct in_addr subnet, ALTO_DB_T * db){ |
816 |
ALTO_DB_ELEMENT_T * cur = db->first; |
817 |
while(cur != NULL){ |
818 |
if(subnet.s_addr == cur->host.s_addr){
|
819 |
// printf("Subnet : %s \t", inet_ntoa(subnet));
|
820 |
// printf("rating : %d \n", cur->rating);
|
821 |
return cur->rating;
|
822 |
} |
823 |
cur = cur->next; |
824 |
} |
825 |
return 0; |
826 |
} |
827 |
|
828 |
|
829 |
|
830 |
int get_alto_rating(ALTO_DB_ELEMENT_T * element, ALTO_DB_T * db){
|
831 |
|
832 |
int mask = element->host_mask;
|
833 |
struct in_addr subnet = compute_subnet(element->host, mask);
|
834 |
// printf("Host: %s/%d \n", inet_ntoa(element->host), mask);
|
835 |
|
836 |
int i, check;
|
837 |
for(i=mask;i>0;i--){ |
838 |
check = ask_helper_func(subnet, db); |
839 |
if(check == 0){ |
840 |
subnet = compute_subnet(element->host, mask--); |
841 |
}else{
|
842 |
// printf("Found rating, with value: %d \n", check);
|
843 |
return check;
|
844 |
} |
845 |
} |
846 |
return 0; |
847 |
} |
848 |
|
849 |
|
850 |
|
851 |
int get_alto_subnet_mask(ALTO_DB_ELEMENT_T * element, ALTO_DB_T * db){
|
852 |
int mask = element->host_mask;
|
853 |
struct in_addr subnet = compute_subnet(element->host, mask);
|
854 |
// printf("Host: %s/%d \n", inet_ntoa(element->host), mask);
|
855 |
int i;
|
856 |
for(i=mask;i>0;i--){ |
857 |
if((ask_helper_func(subnet, db)) == 0){ |
858 |
return mask;
|
859 |
}else{
|
860 |
mask--; |
861 |
} |
862 |
} |
863 |
return 0; |
864 |
} |
865 |
|
866 |
|
867 |
|
868 |
|
869 |
|
870 |
|
871 |
|
872 |
|
873 |
/*
|
874 |
* Here the matching between the requested IPs and the delivered
|
875 |
* list will be done
|
876 |
*
|
877 |
* in: db_req Pointer to the DB where the IPs are
|
878 |
* db_res Pointer to the DB where the ALTO response is
|
879 |
* return: 1 Success
|
880 |
*/
|
881 |
int alto_do_the_magic(ALTO_DB_T * ALTO_db_req, ALTO_DB_T * ALTO_db_res){
|
882 |
alto_debugf("%s: Find the rating and assign to IPs\n", __FUNCTION__);
|
883 |
|
884 |
// Sanity check
|
885 |
returnIf((ALTO_db_req == NULL || ALTO_db_res == NULL), "Errors in accessing the DBs! ABORT", 0); |
886 |
|
887 |
// Now iterate through the hosts and find the corresponding rating
|
888 |
ALTO_DB_ELEMENT_T * cur; |
889 |
cur = ALTO_db_req->first; |
890 |
while(cur != NULL){ |
891 |
|
892 |
// store the rating in the asking element
|
893 |
cur->rating = get_alto_rating(cur, ALTO_db_res); |
894 |
|
895 |
// next DB item to query
|
896 |
cur = cur->next; |
897 |
} |
898 |
|
899 |
// Aaaaaand finished!
|
900 |
return 1; |
901 |
} |
902 |
|
903 |
|
904 |
|
905 |
|
906 |
|
907 |
|
908 |
int alto_parse_from_file(altoDbPtr db, char *file_name){ |
909 |
alto_debugf("%s: Read hosts from file (%s) and store it in the Request-DB\n", __FUNCTION__, file_name);
|
910 |
|
911 |
FILE *file; |
912 |
char line[256]; |
913 |
file = fopen(file_name, "r");
|
914 |
char * ptr;
|
915 |
|
916 |
// Sanity checks
|
917 |
returnIf(db == NULL, "No DB selected! ABORT", 0); |
918 |
returnIf(file == NULL, "Can't open the file! ABORT", 0); |
919 |
|
920 |
// Now read the lines in
|
921 |
while(fgets(line, sizeof(line), file) != NULL ) { |
922 |
// parse the line, remove the comments
|
923 |
ptr = strtok(line, " ");
|
924 |
// create the ALTO element
|
925 |
struct alto_db_element_t *element;
|
926 |
element = malloc(sizeof(ALTO_DB_ELEMENT_T));
|
927 |
element->host = get_ALTO_host_IP(ptr); |
928 |
element->host_mask = get_ALTO_host_mask(ptr); |
929 |
// and add this element to the db
|
930 |
alto_add_element(db, element); |
931 |
} |
932 |
return 1; |
933 |
} |
934 |
|
935 |
|
936 |
|
937 |
int alto_parse_from_XML(altoDbPtr db, xmlDocPtr doc){
|
938 |
alto_debugf("%s: Parse an XML element into the DB structure\n", __FUNCTION__);
|
939 |
|
940 |
// Sanity check
|
941 |
returnIf((db == NULL || doc == NULL), "Couldn't access XML or DB! ABORT", -1); |
942 |
|
943 |
xmlNode *cur = NULL;
|
944 |
cur = xmlDocGetRootElement(doc); |
945 |
xmlChar *overall_rating = NULL;
|
946 |
xmlChar *ipprefix = NULL;
|
947 |
xmlChar *status_code = NULL;
|
948 |
int ratings_done = 0; |
949 |
|
950 |
while(cur!=NULL){ |
951 |
if (!xmlStrcmp(cur->name, BAD_CAST "group_rating_reply")) { |
952 |
status_code = xmlGetProp(cur, BAD_CAST "statuscode");
|
953 |
if (status_code) alto_debugf("*** ALTO reply statuscode = %s\n", status_code); |
954 |
} |
955 |
if (!xmlStrcmp(cur->name, BAD_CAST "statustext")) { |
956 |
xmlChar* str; |
957 |
str = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
|
958 |
alto_debugf("***********************************************************************\n");
|
959 |
alto_debugf("*** ALTO reply statustext = '%s'\n", str);
|
960 |
alto_debugf("***********************************************************************\n");
|
961 |
xmlFree(str); |
962 |
} |
963 |
if (!xmlStrcmp(cur->name, BAD_CAST "cnd_hla")) { |
964 |
overall_rating = xmlGetProp(cur, BAD_CAST "overall_rating");
|
965 |
} |
966 |
if (!xmlStrcmp(cur->name, BAD_CAST "ipprefix")) { |
967 |
ipprefix = xmlGetProp(cur, BAD_CAST "prefix");
|
968 |
if (!ipprefix) {
|
969 |
alto_debugf("Couldn't find ipprefix!\n");
|
970 |
break;
|
971 |
} |
972 |
|
973 |
// create the ALTO element
|
974 |
struct alto_db_element_t *element;
|
975 |
element = malloc(sizeof(ALTO_DB_ELEMENT_T));
|
976 |
element->host = get_ALTO_host_IP((char*) ipprefix);
|
977 |
element->host_mask = get_ALTO_host_mask((char*) ipprefix);
|
978 |
if (overall_rating) {
|
979 |
element->rating = atoi(overall_rating); |
980 |
alto_debugf("rating %s = %d\n", ipprefix, element->rating);
|
981 |
} else {
|
982 |
element->rating = 0;
|
983 |
alto_debugf("rating %s = %d (DEFAULT, host not in DB!)\n", ipprefix, element->rating);
|
984 |
} |
985 |
ratings_done = 1;
|
986 |
|
987 |
// and add this element to the db
|
988 |
alto_add_element(db, element); |
989 |
|
990 |
} |
991 |
if (cur->children != NULL) { |
992 |
// printf("cur->children == NULL \n");
|
993 |
cur = cur->children; |
994 |
} |
995 |
if (cur->children == NULL && cur->next != NULL) { |
996 |
// printf("cur->children == NULL && cur->next != NULL \n");
|
997 |
cur = cur->next; |
998 |
} |
999 |
if (cur->children == NULL && cur->next == NULL) { |
1000 |
// printf("cur->children == NULL && cur->next == NULL \n");
|
1001 |
cur = cur->parent->next; |
1002 |
} |
1003 |
} |
1004 |
|
1005 |
if (!ratings_done) {
|
1006 |
alto_debugf("WARNING: ALTO XML reply didn't contain rating info, no peers were rated!\n");
|
1007 |
xmlChar* text = NULL;
|
1008 |
int sz = 0; |
1009 |
xmlDocDumpMemory(doc, &text, &sz); |
1010 |
//fprintf(stderr, "ALTO XML reply was: (%d bytes)\n%s", sz, text);
|
1011 |
} |
1012 |
|
1013 |
return 1; |
1014 |
} |
1015 |
|
1016 |
|
1017 |
|
1018 |
/*
|
1019 |
* Converts a given alto_list_t structure into the internal DB structure
|
1020 |
*
|
1021 |
* in: db the databse where the element has to be added
|
1022 |
* list the list of the alto elements structure
|
1023 |
* num number of eements to add
|
1024 |
* ret: 1/-1 for success failuire
|
1025 |
*/
|
1026 |
int alto_parse_from_list(struct alto_db_t *db, struct alto_guidance_t *list, int num_of_elements){ |
1027 |
alto_debugf("%s: Convert given list into internal DB structure\n", __FUNCTION__);
|
1028 |
|
1029 |
// Sanity check
|
1030 |
returnIf((db == NULL || list == NULL), "No lists to parse from / parse in, ABORT!", -1); |
1031 |
|
1032 |
// and now will the elements in the DB
|
1033 |
int i;
|
1034 |
for(i=0; i < num_of_elements; i++){ |
1035 |
|
1036 |
// Create a new element
|
1037 |
struct alto_db_element_t *element;
|
1038 |
element = malloc(sizeof(ALTO_DB_ELEMENT_T));
|
1039 |
element->alto_db = db; |
1040 |
element->next = NULL;
|
1041 |
element->prev = NULL;
|
1042 |
element->host = list[i].alto_host; // here the values come in
|
1043 |
element->host_mask = list[i].prefix; // here the values come in
|
1044 |
element->rating = 0; // here the values come in |
1045 |
|
1046 |
// and now append it to the DB
|
1047 |
alto_add_element(db, element); |
1048 |
} |
1049 |
|
1050 |
// That's should be it
|
1051 |
return 1; |
1052 |
} |
1053 |
|
1054 |
|
1055 |
|
1056 |
|
1057 |
|
1058 |
int alto_write_to_file(altoDbPtr db, char *file_name){ |
1059 |
alto_debugf("%s: Write hosts to file (%s.out) \n", __FUNCTION__, file_name);
|
1060 |
|
1061 |
// Sanity checks
|
1062 |
returnIf(file_name == NULL, "Can't open the file! ABORT",-1); |
1063 |
returnIf(db == NULL, "No DB select! ABORT", -1); |
1064 |
|
1065 |
// Create the new file
|
1066 |
char * str_out;
|
1067 |
str_out = (char*)malloc(256 * sizeof(char)); |
1068 |
strcpy (str_out,file_name); |
1069 |
strcat (str_out,".out");
|
1070 |
|
1071 |
// create the output filename
|
1072 |
FILE *file; |
1073 |
file = fopen(str_out, "a+");
|
1074 |
returnIf(file == NULL, "Can't create the file! ABORT", 0); |
1075 |
|
1076 |
// Write everything to the file
|
1077 |
int count = 0; |
1078 |
ALTO_DB_ELEMENT_T * cur = db->first; |
1079 |
while(cur != NULL){ |
1080 |
fprintf(file, "%s/%d \t", inet_ntoa(cur->host), cur->host_mask);
|
1081 |
fprintf(file, "%d \t", cur->rating);
|
1082 |
fprintf(file, "\n");
|
1083 |
count++; |
1084 |
cur = cur->next; |
1085 |
} |
1086 |
|
1087 |
// Return the number of sucessful written lines
|
1088 |
return count;
|
1089 |
} |
1090 |
|
1091 |
|
1092 |
|
1093 |
|
1094 |
/*
|
1095 |
* Start & Innitialize the ALTO client
|
1096 |
*/
|
1097 |
void start_ALTO_client(){
|
1098 |
alto_debugf("START ALTO client! \n");
|
1099 |
|
1100 |
// initialize the DBs
|
1101 |
ALTO_DB_req = alto_db_init(); |
1102 |
ALTO_DB_res = alto_db_init(); |
1103 |
|
1104 |
// prepare the XML environment
|
1105 |
LIBXML_TEST_VERSION; |
1106 |
|
1107 |
// and Initialize the XMLs
|
1108 |
ALTO_XML_req = NULL;
|
1109 |
ALTO_XML_res = NULL;
|
1110 |
|
1111 |
|
1112 |
} |
1113 |
|
1114 |
|
1115 |
/*
|
1116 |
* Stop & CleanUp the ALTO client
|
1117 |
*/
|
1118 |
void stop_ALTO_client(){
|
1119 |
alto_debugf("STOP ALTO client! \n");
|
1120 |
|
1121 |
// Kill the DBs
|
1122 |
alto_free_db(ALTO_DB_req); |
1123 |
alto_free_db(ALTO_DB_res); |
1124 |
|
1125 |
// Kill the XML
|
1126 |
if (ALTO_XML_req) { xmlFreeDoc(ALTO_XML_req); ALTO_XML_req = NULL; } |
1127 |
if (ALTO_XML_res) { xmlFreeDoc(ALTO_XML_res); ALTO_XML_res = NULL; } |
1128 |
|
1129 |
xmlCleanupParser(); |
1130 |
} |
1131 |
|
1132 |
|
1133 |
|
1134 |
|
1135 |
|
1136 |
|
1137 |
/*
|
1138 |
* Function: gets for a list in a txt file the correct rating
|
1139 |
*
|
1140 |
* in: *txt pointer to the list
|
1141 |
* rc_host The Resource Consumer locator
|
1142 |
* pri_rat Primary Rating criteria
|
1143 |
* sec_rat Secondary Rating criteria
|
1144 |
* return: 1/0 Success/Erros
|
1145 |
*/
|
1146 |
int get_ALTO_guidance_for_txt(char * txt, struct in_addr rc_host, int pri_rat, int sec_rat){ |
1147 |
alto_debugf("get_ALTO_guidance_txt(%s) was called \n", txt);
|
1148 |
|
1149 |
// Sanity checks
|
1150 |
returnIf(txt == NULL, "Can't access the file! ABORT!", 0); |
1151 |
returnIf(rc_host.s_addr == NULL, "Can't read the rc_host! ABORT!", 0); |
1152 |
returnIf((pri_rat < 1 || pri_rat > 3), "Primary Rating Criteria wrong! ABORT!", 0); |
1153 |
returnIf((sec_rat < 1 || sec_rat > 8), "Secondary Rating Criteria(s) wrong! ABORT", 0); |
1154 |
|
1155 |
// first purge existing DB entries
|
1156 |
alto_purge_db(ALTO_DB_req); |
1157 |
|
1158 |
// Step 1: fill the txt into the DB
|
1159 |
alto_parse_from_file(ALTO_DB_req, txt); |
1160 |
|
1161 |
// do the ALTO trick / update db
|
1162 |
do_ALTO_update(rc_host, pri_rat, sec_rat); |
1163 |
|
1164 |
// Step 3 (write values back)
|
1165 |
alto_write_to_file(ALTO_DB_req, txt); |
1166 |
|
1167 |
// done
|
1168 |
return 1; |
1169 |
} |
1170 |
|
1171 |
/*
|
1172 |
* Function: gets for a list of elements the correct rating
|
1173 |
*
|
1174 |
* in: *list pointer to the list
|
1175 |
* *num Number of elements to process
|
1176 |
* return: count Number of sucessfully processed hosts
|
1177 |
*/
|
1178 |
int get_ALTO_guidance_for_list(ALTO_GUIDANCE_T * list, int num, struct in_addr rc_host, int pri_rat, int sec_rat){ |
1179 |
alto_debugf("get_ALTO_guidance(list, num_of_elements) was called \n");
|
1180 |
|
1181 |
int count = 0; |
1182 |
|
1183 |
// Sanity checks (list)
|
1184 |
returnIf(list == NULL, "Can't access the list!", 0); |
1185 |
|
1186 |
// Sanity checks (num of elements)
|
1187 |
returnIf(num < 0, "<0 elements?", 0); |
1188 |
|
1189 |
// first purge existing DB entries
|
1190 |
alto_purge_db(ALTO_DB_req); |
1191 |
|
1192 |
// Step 1 (read struct into DB)
|
1193 |
alto_parse_from_list(ALTO_DB_req, list, num); |
1194 |
|
1195 |
// do the ALTO trick / update db
|
1196 |
do_ALTO_update(rc_host, pri_rat, sec_rat); |
1197 |
|
1198 |
// Step 2 (write values back)
|
1199 |
for(count = 0; count < num; count++){ |
1200 |
list[count].rating = get_ALTO_rating_for_host(list[count].alto_host, ALTO_DB_req); |
1201 |
} |
1202 |
|
1203 |
// This should be it
|
1204 |
return 1; |
1205 |
} |
1206 |
|
1207 |
/*==================================
|
1208 |
Multi-Threaded Query
|
1209 |
==================================*/
|
1210 |
|
1211 |
static int queryState = ALTO_QUERY_READY; |
1212 |
|
1213 |
static pthread_t threadId;
|
1214 |
static pthread_attr_t attr;
|
1215 |
|
1216 |
typedef struct { |
1217 |
ALTO_GUIDANCE_T* list; |
1218 |
int num; // number of elements in list |
1219 |
struct in_addr rc_host;
|
1220 |
int pri_rat;
|
1221 |
int sec_rat;
|
1222 |
} ALTO_ThreadArgs_t; |
1223 |
|
1224 |
ALTO_ThreadArgs_t threadArgs; |
1225 |
|
1226 |
void* alto_query_thread_func(void* thread_args) |
1227 |
{ |
1228 |
int count = 0; |
1229 |
ALTO_ThreadArgs_t* args = (ALTO_ThreadArgs_t*) thread_args; |
1230 |
|
1231 |
alto_debugf("alto_query_thread_func\n");
|
1232 |
|
1233 |
// this will block at some point
|
1234 |
do_ALTO_update(args->rc_host, args->pri_rat, args->sec_rat); |
1235 |
|
1236 |
// write values back
|
1237 |
for(count = 0; count < args->num; count++){ |
1238 |
args->list[count].rating = get_ALTO_rating_for_host(args->list[count].alto_host, ALTO_DB_req); |
1239 |
} |
1240 |
|
1241 |
// signal that query is ready
|
1242 |
queryState = ALTO_QUERY_READY; |
1243 |
|
1244 |
return thread_args;
|
1245 |
} |
1246 |
|
1247 |
int ALTO_query_state() {
|
1248 |
return queryState;
|
1249 |
} |
1250 |
|
1251 |
int ALTO_query_exec(ALTO_GUIDANCE_T * list, int num, struct in_addr rc_host, int pri_rat, int sec_rat){ |
1252 |
alto_debugf("ALTO_query_exec\n");
|
1253 |
|
1254 |
// Sanity checks (list)
|
1255 |
returnIf(list == NULL, "Can't access the list!", 0); |
1256 |
|
1257 |
// Sanity checks (num of elements)
|
1258 |
returnIf(num < 0, "<0 elements?", 0); |
1259 |
|
1260 |
// set new state
|
1261 |
if (queryState == ALTO_QUERY_INPROGRESS) {
|
1262 |
alto_debugf("*** WARNING: Calling ALTO_query_exec while query is still in progress! Race condition?!\n");
|
1263 |
return 0; |
1264 |
} |
1265 |
queryState = ALTO_QUERY_INPROGRESS; |
1266 |
|
1267 |
// first purge existing DB entries
|
1268 |
alto_purge_db(ALTO_DB_req); |
1269 |
|
1270 |
// Step 1 (read struct into DB)
|
1271 |
alto_parse_from_list(ALTO_DB_req, list, num); |
1272 |
|
1273 |
//ALTO_XML_req = alto_create_request_XML(ALTO_DB_req, rc_host, pri_rat, sec_rat);
|
1274 |
|
1275 |
threadArgs.list = list; |
1276 |
threadArgs.num = num; |
1277 |
pthread_attr_init(&attr); |
1278 |
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
1279 |
if (pthread_create(&threadId, &attr, alto_query_thread_func, &threadArgs) != 0) { |
1280 |
fprintf(stderr,"[ALTOclient] pthread_create failed!\n");
|
1281 |
queryState = ALTO_QUERY_READY; |
1282 |
return 0; |
1283 |
} |
1284 |
|
1285 |
// This should be it
|
1286 |
return 1; |
1287 |
} |
1288 |
|
1289 |
|
1290 |
|
1291 |
/*
|
1292 |
* Function: With this call the internal request to update the DB is triggered.
|
1293 |
* This should be done on a regual basis to keep the local ALTO-DB
|
1294 |
* up2date
|
1295 |
*/
|
1296 |
|
1297 |
|
1298 |
void do_ALTO_update(struct in_addr rc_host, int pri_rat, int sec_rat){ |
1299 |
assertCheck(ALTO_DB_req, "ALTO_DB_req is NULL!");
|
1300 |
|
1301 |
// Step 2: create an XML from the DB entries
|
1302 |
ALTO_XML_req = alto_create_request_XML(ALTO_DB_req, rc_host, pri_rat, sec_rat); |
1303 |
|
1304 |
#ifndef USE_LOCAL_REPLY_XML
|
1305 |
// Step2a: send POST request to ALTO server
|
1306 |
#ifdef USE_CURL
|
1307 |
ALTO_XML_res = query_ALTO_server_curl(ALTO_XML_req, alto_server_url); |
1308 |
#else
|
1309 |
ALTO_XML_res = ALTO_request_to_server(ALTO_XML_req, alto_server_url); |
1310 |
#endif
|
1311 |
#else
|
1312 |
// Step2b: use for testing the local stored TXT-file
|
1313 |
ALTO_XML_res = xmlReadFile("reply.xml",NULL,XML_PARSE_RECOVER); |
1314 |
#endif
|
1315 |
|
1316 |
if (ALTO_XML_res) {
|
1317 |
// Step 3: Parse the XML to the DB
|
1318 |
alto_parse_from_XML(ALTO_DB_res, ALTO_XML_res); |
1319 |
|
1320 |
// ###### Big Magic ######
|
1321 |
// And now check for the corresponding rating
|
1322 |
alto_do_the_magic(ALTO_DB_req, ALTO_DB_res); |
1323 |
|
1324 |
xmlFreeDoc(ALTO_XML_res); |
1325 |
ALTO_XML_res = NULL;
|
1326 |
} |
1327 |
|
1328 |
// free xml data
|
1329 |
xmlFreeDoc(ALTO_XML_req); |
1330 |
ALTO_XML_req = NULL;
|
1331 |
|
1332 |
// purge the intermediate DB
|
1333 |
alto_purge_db(ALTO_DB_res); |
1334 |
} |
1335 |
|
1336 |
|