Revision 5f3adef4 ALTOclient/ALTOclient.c

View differences:

ALTOclient/ALTOclient.c
1 1
/*
2 2
 ============================================================================
3 3
 Name        : ALTOclient.c
4
 Authors     : Thilo Ewald
5
			   Armin Jahanpanah <jahanpanah@neclab.eu>
6
 
4
 Author      : T. Ewald <ewald@nw.neclab.eu>
5
 Version     : 243
7 6
 Proprietary : NEC Europe Ltd. PROPRIETARY INFORMATION
8 7
			   This software is supplied under the terms of a license
9 8
			   agreement or nondisclosure agreement with NEC Europe Ltd. and
......
29 28
			   OUT OF THE USE OF OR INABILITY TO USE THIS PROGRAM, EVEN IF NEC
30 29
			   Europe Ltd. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 30
 Modification: THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
31
 Description : First try of the ALTO client
32 32
 ============================================================================
33 33
 */
34 34

  
35 35
#include "ALTOclient.h"
36 36
#include "ALTOclient_impl.h"
37 37

  
38
#include <stddef.h>
39 38
#include <stdarg.h>
40 39
#include <pthread.h>
41
#include <sys/time.h>
42
#include <time.h>
43

  
44
typedef struct {
45
	int query_failure_count;
46
	int query_failure_count_total;
47
} alto_stats;
48

  
49
static alto_stats stats;
50 40

  
51 41
/*
52 42
 * 		Here the reference to the accessible DBs is set
......
57 47
static xmlDocPtr ALTO_XML_req = NULL;		// Pointer to the XML for the Request
58 48
static xmlDocPtr ALTO_XML_res = NULL;		// Pointer to the XML for the Request
59 49

  
50

  
60 51
// This is the varaiable where the ALTO server can be found
61 52
static char alto_server_url[256];
62 53

  
......
92 83

  
93 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; }
94 85

  
95
#define errorMsg(msg) alto_errorf("%s (%s, line: %d) -- %s\n", __FUNCTION__, __FILE__, __LINE__, msg);
96

  
97
typedef struct {
98
	uint64_t timer_start;	/* time of init */
99
	uint64_t timer_last;	/* time of last update */
100
	uint64_t timer_delta;	/* timespan between last two updates */
101
	uint64_t ticks;			/* microsecs since timer_start */
102
	float t;				/* seconds since timer start */
103
	float dt;				/* timer_delta in seconds */
104
} alto_timer;
105

  
106
static void alto_timer_init(alto_timer* timer)
107
{
108
	struct timeval tnow;
109
	gettimeofday(&tnow, NULL);
110
	timer->timer_start = (tnow.tv_usec + tnow.tv_sec * 1000000ull);
111
	timer->timer_last = timer->timer_start;
112
	timer->timer_delta = 0;
113
	timer->ticks = 0;
114
	timer->t = 0.0f;
115
	timer->dt = 0.0f;
116
}
117

  
118
static void alto_timer_update(alto_timer* timer)
119
{
120
	struct timeval tnow;
121
	gettimeofday(&tnow, NULL);
122
	uint64_t timer_now = (tnow.tv_usec + tnow.tv_sec * 1000000ull);
123
	timer->timer_delta = timer_now - timer->timer_last;
124
	timer->timer_last = timer_now;
125
	timer->ticks = timer_now - timer->timer_start;
126
	timer->t = timer->ticks / 1000000.0f; /* in seconds */
127
	timer->dt = timer->timer_delta / 1000000.0f; /* in seconds */
128
}
129

  
130

  
131 86
/*
132 87
 * 	Function to set the actual ALTO server for configuration
133 88
 */
......
147 102
	return (char *) alto_server_url;
148 103
}
149 104

  
105

  
106

  
107

  
108

  
109

  
110

  
111

  
150 112
/*
151 113
 * 	Func:					Convert the "Baschtl" notation into a readable
152 114
 * 							format (get IP address)
......
178 140
	return IP;
179 141
}
180 142

  
143

  
144

  
145

  
181 146
/*
182 147
 * 	Func:			Convert the "Baschtl" notation into a readable format
183 148
 * 					(get prefix)
......
201 166
    return 32;
202 167
}
203 168

  
169

  
204 170
/*
205 171
 *  Func:	Create an ALTO XML request from a given DB
206 172
 *
......
209 175
 *  ret:	XML_doc		the XML where the request is stored in
210 176
 */
211 177
xmlDocPtr alto_create_request_XML(struct alto_db_t * db, struct in_addr rc_host, int pri_rat, int sec_rat){
212
	returnIf(db == NULL, "internal db ptr is NULL!", NULL);
178
	assertCheck(db, "internal db ptr is NULL!");
213 179

  
214 180
	// Creates a new document
215 181
	// <?xml version="1.0" encoding="UTF-8"?>
216 182
	xmlDocPtr doc = NULL;       /* document pointer */
217 183
	doc = xmlNewDoc(BAD_CAST "1.0");
218 184

  
219
	returnIf(doc == NULL, "xmlNewDoc failed! Out of memory?", NULL);
185
	assertCheck(doc, "xmlNewDoc failed! Out of memory?");
220 186

  
221 187
	// Create the root node and name it with the correct name space
222 188
	// <alto xmlns='urn:ietf:params:xml:ns:p2p:alto'>
......
252 218
    	xmlNewProp(node_PRI, BAD_CAST "crit", BAD_CAST "lat");
253 219
    }
254 220

  
221

  
255 222
    // Add the additional rating criteria
256 223
	if((sec_rat & REL_PREF) == REL_PREF){
257 224
		xmlNodePtr node_SEC1 = NULL;
......
269 236
		xmlNewProp(node_SEC4, BAD_CAST "crit", BAD_CAST "lat");
270 237
	}
271 238

  
239

  
272 240
    // Now create the source of the request
273 241
    // <rc_hla><ipprefix version='4' prefix='195.37.70.39/32'/></rc_hla>
274 242
    xmlNodePtr node_RC_HLA = NULL;
......
325 293
       libCURL-based POST code
326 294
  ==================================*/
327 295

  
296
// libcurl is now obsolete!
328 297
#ifdef USE_CURL
329 298

  
330 299
// this function will be registered with curl as a handler, which
331 300
// copies the http reply to a the buffer
332
static size_t curl_copy_reply_to_buf(void *ptr,size_t size,size_t nmemb,void *stream){
301
size_t curl_copy_reply_to_buf(void *ptr,size_t size,size_t nmemb,void *stream){
333 302
    size_t realsize = size * nmemb;
334 303
    struct curl_reply_buffer_t *crb = (struct curl_reply_buffer_t *)stream;
335 304
    // error: new chunk plus trailing zero would not fit into remaining buffer
......
341 310
}
342 311
uint16_t prefixes = 0;
343 312

  
313

  
314

  
344 315
xmlDocPtr query_ALTO_server_curl(xmlDocPtr doc, char* ALTO_server_URL){
345 316
	xmlDocPtr ALTO_XML_response;
346 317

  
......
351 322
	struct curl_httppost *lastptr=NULL;
352 323

  
353 324
	curl = curl_easy_init();
354
	returnIf(curl == NULL, "Couldn't get a handle from curl_easy_init(). abort.", NULL);
325
	assertCheck(curl, "Couldn't get a handle from curl_easy_init(). abort.");
355 326

  
356
	//printf("Will send HTTP POST to %s\nwith form data:\n\n%s\n", alto_server_url, ALTO_XML_query);
327
//	printf("Will send HTTP POST to %s\nwith form data:\n\n%s\n", alto_server_url, ALTO_XML_query);
357 328

  
358 329
	// prepare the buffer to be send
359 330
	xmlChar*  doctxt;
360 331
	int       doclen;
361 332
	xmlDocDumpFormatMemoryEnc(doc,&doctxt,&doclen,"utf-8",1);
362 333

  
363
	#ifdef USE_DEBUG_OUTPUT
364
	printf(stderr, "[ALTOclientCURL] Will send HTTP POST to %s\nwith XML data:\n\n%s\n", alto_server_url, doctxt);
365
	#endif
366

  
367 334
	// URL that receives this POST
368 335
	curl_easy_setopt(curl, CURLOPT_URL, ALTO_server_URL);
369
//	curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
370
//	curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
371
	curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
372 336

  
373 337
	// add form data
374 338
	curl_formadd(&formpost,
375 339
				 &lastptr,
376 340
				 CURLFORM_COPYNAME, "alto_xml_request",
377 341
//				 CURLFORM_COPYCONTENTS, ALTO_XML_query,
378
				 CURLFORM_COPYCONTENTS, doctxt,		// PTRCONTENTS?
342
				 CURLFORM_COPYCONTENTS, doctxt,
379 343
				 CURLFORM_END);
380 344

  
381 345
	curl_formadd(&formpost,
......
400 364
	// then cleanup the form post chain
401 365
	curl_formfree(formpost);
402 366

  
403
	#ifdef USE_DEBUG_OUTPUT
404
	//printf("result of curl_easy_perform() is: %i\n", res);
405
	fprintf(stderr, "[ALTOclientCURL] received %i octets. the buffer is:\n\n%s\nthat's all. bye.\n", alto_rep_buf.fill, alto_rep_buf.buffer);
406
	#endif
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);
407 369

  
408 370

  
409 371
	// and last but nor least, transform it into an XML doc
410
	ALTO_XML_response = xmlRecoverMemory(alto_rep_buf.buffer, sizeof(alto_rep_buf.buffer));		// <- for getting XML from memory
372
	ALTO_XML_response = xmlRecoverMemory(alto_rep_buf.buffer,sizeof(alto_rep_buf.buffer));		// <- for getting XML from memory
411 373

  
412 374
	return ALTO_XML_response;
413 375
}
......
420 382

  
421 383
#define POST_BOUNDARY "---------------------------12408751047121013601852724877"
422 384

  
423
static void POST_add(char* buf, const char* name, const char* value) {
385
void POST_add(char* buf, const char* name, const char* value) {
424 386
	sprintf(buf+strlen(buf), "--"POST_BOUNDARY"\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", name, value);
425 387
}
426 388

  
427
static void POST_end(char* buf) {
389
void POST_end(char* buf) {
428 390
	sprintf(buf+strlen(buf), "--"POST_BOUNDARY"--\r\n\r\n");
429 391
}
430 392

  
431
static void* POST_send(const char* url, const char* data) {
393
void* POST_send(const char* url, const char* data) {
432 394
	int i;
433 395
	void* ctx = NULL;
434 396
	char header[] = "Connection: close\r\n";
435 397
	char contentType[] = "multipart/form-data; boundary="POST_BOUNDARY;
436 398
	char* ct = contentType;
437 399

  
438
	returnIf(url == NULL, "ALTO server URL is NULL!", NULL);
439
	returnIf(data == NULL, "POST data is NULL!", NULL);
400
	assertCheck(url, "ALTO server URL is NULL!");
401
	assertCheck(data, "POST data is NULL!");
440 402

  
441 403
	//ctx = xmlNanoHTTPMethod(url, "POST", data, &ct, NULL, strlen(data));
442 404
	for (i=0; i < 3; i++) {
......
449 411
		fprintf(stderr, "URL was '%s'.", url);
450 412
		return NULL;
451 413
	}
414
	assertCheck(ctx, "xmlNanoHTTPMethod failed! Make sure ALTO server is reachable (NAT issue?)..");
452 415

  
453 416
	free(ct);
454 417
	return ctx;
......
469 432
//	int		errorcode = 0;
470 433
//	FILE*	f = NULL;
471 434

  
472
	returnIf(doc == NULL, "xml doc ptr is NULL!", NULL);
473
	returnIf(endPoint == NULL, "ALTO server URL is NULL!", NULL);
435
	assertCheck(doc, "xml doc ptr is NULL!");
436
	assertCheck(endPoint, "ALTO server URL is NULL!");
474 437

  
475 438
	xmlNanoHTTPInit();
476 439
	xmlDocDumpFormatMemoryEnc(doc,&doctxt,&doclen,"utf-8",1);
477 440

  
478 441
	dataLen = doclen + 2048;
479 442
	data = malloc(dataLen);
480
	returnIf(data == NULL, "Couldn't allocate data buffer! Out of memory?", NULL);
443
	assertCheck(data, "Couldn't allocate data buffer! Out of memory?");
481 444
	memset(data, 0, dataLen);
482 445

  
483 446
	// build the mime multipart contents
......
571 534
	return result;
572 535
}
573 536

  
537

  
538

  
539

  
574 540
/*
575 541
 *
576 542
 * 		HERE is the magic for the internal DB management
......
585 551
	struct alto_db_t * db;
586 552
	db = malloc(sizeof(struct alto_db_t));
587 553
//	db = (alto_db_t *)malloc(sizeof(struct alto_db_element_t));
588
	returnIf(db == NULL, "Couldn't allocate internal db! Out of memory?", NULL);
554
	assertCheck(db, "Couldn't allocate internal db! Out of memory?");
589 555

  
590 556
	db->first = NULL;
591 557
	db->last = NULL;
......
626 592
	return 1;
627 593
}
628 594

  
595

  
596

  
629 597
/*
630 598
 * 	Helper function to print values of one ALTO DB element
631 599
 */
632 600
void alto_dump_element(struct alto_db_element_t * cur){
633 601
	// Sanity check
634
	if (cur == NULL) return;
602
	assertCheck(cur == NULL, "No element to print values from! ABORT");
635 603

  
636 604
	// normal case, print everything
637 605
//	fprintf(stdout, "---> Internal Data\t");
......
657 625
	alto_debugf("Dump what's in the DB \n");
658 626

  
659 627
	// Security Check
660
	if (!db) return;
628
	assertCheck(db, "Failure in DB structure! ABORT");
661 629

  
662 630
	// General Data
663 631
	alto_debugf("Number of elements in DB: %d \n", db->num_of_elements);
......
676 644
	return;
677 645
}
678 646

  
647

  
648

  
649

  
679 650
/*
680 651
 *  Adds one ALTO entry to the DB
681 652
 */
......
768 739
		return 1;
769 740
	}
770 741

  
742

  
771 743
	// normal handling, somwhere in the DB
772 744
	else {
773 745
		// update predecessor
......
787 759
	return -1;
788 760
}
789 761

  
762

  
790 763
struct in_addr compute_subnet(struct in_addr host, int prefix){
791 764
	struct in_addr subn;
792 765
	uint32_t match_host = host.s_addr;
......
802 775
	return subn;
803 776
}
804 777

  
778

  
779

  
805 780
/*
806 781
 * 	Search in an ALTO DB for the match of an host
807 782
 *
......
829 804
	return 0;
830 805
}
831 806

  
807

  
808

  
809

  
810

  
811

  
812

  
813

  
814

  
832 815
int ask_helper_func(struct in_addr subnet, ALTO_DB_T * db){
833 816
	ALTO_DB_ELEMENT_T * cur = db->first;
834 817
	while(cur != NULL){
......
842 825
	return 0;
843 826
}
844 827

  
828

  
829

  
845 830
int get_alto_rating(ALTO_DB_ELEMENT_T * element, ALTO_DB_T * db){
846 831

  
847 832
	int mask = element->host_mask;
......
861 846
	return 0;
862 847
}
863 848

  
849

  
850

  
864 851
int get_alto_subnet_mask(ALTO_DB_ELEMENT_T * element, ALTO_DB_T * db){
865 852
	int mask = element->host_mask;
866 853
	struct in_addr subnet = compute_subnet(element->host, mask);
......
876 863
	return 0;
877 864
}
878 865

  
866

  
867

  
868

  
869

  
870

  
871

  
872

  
879 873
/*
880 874
 * 	Here the matching between the requested IPs and the delivered
881 875
 * 	list will be done
......
906 900
	return 1;
907 901
}
908 902

  
903

  
904

  
905

  
906

  
907

  
909 908
int alto_parse_from_file(altoDbPtr db, char *file_name){
910 909
	alto_debugf("%s: Read hosts from file (%s) and store it in the Request-DB\n", __FUNCTION__, file_name);
911 910

  
......
1014 1013
	return 1;
1015 1014
}
1016 1015

  
1016

  
1017

  
1017 1018
/*
1018 1019
 * 	Converts a given alto_list_t structure into the internal DB structure
1019 1020
 *
......
1050 1051
	return 1;
1051 1052
}
1052 1053

  
1054

  
1055

  
1056

  
1057

  
1053 1058
int alto_write_to_file(altoDbPtr db, char *file_name){
1054 1059
	alto_debugf("%s: Write hosts to file (%s.out) \n", __FUNCTION__, file_name);
1055 1060

  
......
1083 1088
	return count;
1084 1089
}
1085 1090

  
1091

  
1092

  
1093

  
1086 1094
/*
1087 1095
 * 	Start & Innitialize the ALTO client
1088 1096
 */
......
1096 1104
	// prepare the XML environment
1097 1105
	LIBXML_TEST_VERSION;
1098 1106

  
1099
#ifdef USE_CURL
1100
	// prepare CURL
1101
	// ---------------------------------------------------------------------------------
1102
	// XXX: NOTE:
1103
	// "This function is NOT THREAD SAFE. You must not call it when any other thread 
1104
	// in the program (i.e. a thread sharing the same memory) is running. This doesn't 
1105
	// just mean no other thread that is using libcurl. Because curl_global_init() calls 
1106
	// functions of other libraries that are similarly thread unsafe, it could conflict 
1107
	// with any other thread that uses these other libraries."
1108
	// ---------------------------------------------------------------------------------
1109

  
1110
	curl_global_init(CURL_GLOBAL_ALL);
1111
#endif
1112

  
1113 1107
	// and Initialize the XMLs
1114 1108
    ALTO_XML_req = NULL;
1115 1109
    ALTO_XML_res = NULL;
1116 1110

  
1117
	// init query failure counters
1118
	stats.query_failure_count = 0;
1119
    stats.query_failure_count_total = 0;
1111

  
1120 1112
}
1121 1113

  
1122 1114

  
......
1135 1127
    if (ALTO_XML_res) { xmlFreeDoc(ALTO_XML_res); ALTO_XML_res = NULL; }
1136 1128

  
1137 1129
	xmlCleanupParser();
1138

  
1139
#ifdef USE_CURL
1140
	// shutdown  libCurl
1141
	// XXX: NOTE: same thread un-safety warning applies!
1142
	curl_global_cleanup();
1143
#endif
1144 1130
}
1145 1131

  
1132

  
1133

  
1134

  
1135

  
1136

  
1146 1137
/*
1147 1138
 * 	Function:	gets for a list in a txt file the correct rating
1148 1139
 *
......
1218 1209
  ==================================*/
1219 1210

  
1220 1211
static int queryState = ALTO_QUERY_READY;
1221
static alto_timer queryTimer;
1222 1212

  
1223 1213
static pthread_t threadId;
1224 1214
static pthread_attr_t attr;
......
1231 1221
	int sec_rat;
1232 1222
} ALTO_ThreadArgs_t;
1233 1223

  
1234
static ALTO_ThreadArgs_t threadArgs;
1224
ALTO_ThreadArgs_t threadArgs;
1235 1225

  
1236 1226
void* alto_query_thread_func(void* thread_args)
1237 1227
{
......
1240 1230

  
1241 1231
	alto_debugf("alto_query_thread_func\n");
1242 1232

  
1243
	// *** this will block at some point ***
1244
	do_ALTO_update(args->rc_host, args->pri_rat, args->sec_rat);	// BLOCK
1245

  
1246
	// *** at this point we got the results from the ALTO server ***
1247

  
1248
    // reset counter of consecutive connection failures
1249
    stats.query_failure_count = 0;
1233
	// this will block at some point
1234
	do_ALTO_update(args->rc_host, args->pri_rat, args->sec_rat);
1250 1235

  
1251 1236
	// write values back
1252 1237
	for(count = 0; count < args->num; count++){
......
1256 1241
	// signal that query is ready
1257 1242
	queryState = ALTO_QUERY_READY;
1258 1243

  
1259
//	alto_timer_update(&queryTimer);
1260
//	alto_debugf("Query took %.2f seconds.\n", queryTimer.t);
1261

  
1262 1244
	return thread_args;
1263 1245
}
1264 1246

  
......
1266 1248
	return queryState;
1267 1249
}
1268 1250

  
1269
int ALTO_stats(int stat_id) {
1270
	if (stat_id == ALTO_STAT_FAILURE_COUNT) return stats.query_failure_count;
1271
	else if (stat_id == ALTO_STAT_FAILURE_COUNT_TOTAL) return  stats.query_failure_count_total;
1272
	return 0;
1273
}
1274

  
1275 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)
1276 1255
	returnIf(list == NULL, "Can't access the list!", 0);
1277
	returnIf(num < 0, "<0 elements?", 0);
1278 1256

  
1279
	int res = ALTO_QUERY_EXEC_OK;
1257
	// Sanity checks (num of elements)
1258
	returnIf(num < 0, "<0 elements?", 0);
1280 1259

  
1281 1260
	// set new state
1282 1261
	if (queryState == ALTO_QUERY_INPROGRESS) {
1283
		alto_timer_update(&queryTimer);
1284
		if (queryTimer.t < ALTO_TIMEOUT) {
1285
			alto_debugf("*** WARNING: Calling ALTO_query_exec while query is still in progress! Aborting..\n");
1286
			return ALTO_QUERY_EXEC_INPROGRESS;
1287
		}
1288
		alto_debugf("*** NOTE: Previous ALTO_query_exec timed out (> %d sec.), starting new query..\n", ALTO_TIMEOUT);
1289

  
1290
		res = ALTO_QUERY_EXEC_TIMEOUT;
1291

  
1292
		// count connection failures
1293
		stats.query_failure_count++;
1294
		stats.query_failure_count_total++;
1295
		alto_debugf("total count of ALTO server query connection failures so far: %d\n", stats.query_failure_count_total);
1262
		alto_debugf("*** WARNING: Calling ALTO_query_exec while query is still in progress! Race condition?!\n");
1263
		return 0;
1296 1264
	}
1297 1265
	queryState = ALTO_QUERY_INPROGRESS;
1298
	alto_timer_init(&queryTimer);
1299 1266

  
1300 1267
	// first purge existing DB entries
1301 1268
	alto_purge_db(ALTO_DB_req);
......
1305 1272

  
1306 1273
	//ALTO_XML_req = alto_create_request_XML(ALTO_DB_req, rc_host, pri_rat, sec_rat);
1307 1274

  
1308
	// *** start async query thread ***
1309 1275
	threadArgs.list = list;
1310 1276
	threadArgs.num = num;
1311 1277
	pthread_attr_init(&attr);
......
1313 1279
	if (pthread_create(&threadId, &attr, alto_query_thread_func, &threadArgs) != 0) {
1314 1280
		fprintf(stderr,"[ALTOclient] pthread_create failed!\n");
1315 1281
		queryState = ALTO_QUERY_READY;
1316
		return ALTO_QUERY_EXEC_THREAD_FAIL;
1282
		return 0;
1317 1283
	}
1318 1284

  
1319 1285
	// This should be it
1320
	return res;
1286
	return 1;
1321 1287
}
1322 1288

  
1289

  
1290

  
1323 1291
/*
1324 1292
 * Function:	With this call the internal request to update the DB is triggered.
1325 1293
 * 				This should be done on a regual basis to keep the local ALTO-DB
1326 1294
 * 				up2date
1327 1295
 */
1296

  
1297

  
1328 1298
void do_ALTO_update(struct in_addr rc_host, int pri_rat, int sec_rat){
1329
	if (!ALTO_DB_req) {
1330
		errorMsg("ALTO_DB_req is NULL!");
1331
		return;
1332
	}
1299
	assertCheck(ALTO_DB_req, "ALTO_DB_req is NULL!");
1333 1300

  
1334 1301
	// Step 2: create an XML from the DB entries
1335 1302
	ALTO_XML_req = alto_create_request_XML(ALTO_DB_req, rc_host, pri_rat, sec_rat);
1336
	if (!ALTO_XML_req) {
1337
		errorMsg("alto_create_request_XML failed!");
1338
		return;
1339
	}
1340 1303

  
1341 1304
#ifndef USE_LOCAL_REPLY_XML
1342 1305
	// Step2a: send POST request to ALTO server
......
1360 1323

  
1361 1324
		xmlFreeDoc(ALTO_XML_res);
1362 1325
		ALTO_XML_res = NULL;
1363
	} else {
1364
		alto_debugf("** WARNING: Invalid response from ALTO server! (%s)\n", __FUNCTION__);
1365 1326
	}
1366 1327

  
1367 1328
	// free xml data

Also available in: Unified diff