Statistics
| Branch: | Revision:

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