belle_sip_refresher_tester.c 51.8 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 2 of the License, or
jehan's avatar
jehan committed
8 9 10 11 12 13 14 15 16 17 18 19 20
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "belle-sip/belle-sip.h"
#include "belle_sip_internal.h"
Ghislain MARY's avatar
Ghislain MARY committed
21 22
#include "belle_sip_tester.h"

23
#ifndef _MSC_VER
jehan's avatar
jehan committed
24
#include <sys/time.h>
25 26 27
#include "belle-sip/headers.h"
#include "belle-sip/parameters.h"
#include <stdlib.h>
28
#endif
Ghislain MARY's avatar
Ghislain MARY committed
29 30


jehan's avatar
jehan committed
31 32 33
#define USERNAME "toto"
#define SIPDOMAIN "sip.linphone.org"
#define PASSWD "secret"
34
#define ALGOM "MD5"
Ghislain MARY's avatar
Ghislain MARY committed
35

36 37 38 39 40 41 42 43 44 45 46
static char publish_body[]=
	"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
	"<impp:presence xmlns:impp=\"urn:ietf:params:xml:ns:pidf entity=\"pres:someone@example.com\">\n"
	"	<impp:tuple id=\"sg89ae\">\n"
	"		<impp:status>\n"
	"			<impp:basic>open</impp:basic>\n"
	"		</impp:status>\n"
	"		<impp:contact priority=\"0.8\">tel:+09012345678</impp:contact>\n"
	"	</impp:tuple>\n"
	"</impp:presence>\n";

jehan's avatar
jehan committed
47 48 49 50
typedef enum auth_mode {
	none
	,digest
	,digest_auth
jehan's avatar
jehan committed
51 52
	,digest_with_next_nonce
	,digest_auth_with_next_nonce
jehan's avatar
jehan committed
53 54
}auth_mode_t;

55
typedef struct _status {
jehan's avatar
jehan committed
56
	int twoHundredOk;
jehan's avatar
jehan committed
57
	int fourHundredOne;
58
	int fourHundredSeven;
59
	int fourHundredEightyOne;
jehan's avatar
jehan committed
60
	int refreshOk;
61
	int refreshKo;
62
	int dialogTerminated;
63
	int fiveHundredTree;
64
}status_t;
Ghislain MARY's avatar
Ghislain MARY committed
65

jehan's avatar
jehan committed
66
typedef struct endpoint {
67 68 69
	belle_sip_stack_t *stack;
	belle_sip_listener_callbacks_t *listener_callbacks;
	belle_sip_provider_t *provider;
jehan's avatar
jehan committed
70
	belle_sip_listening_point_t *lp;
71
	belle_sip_listener_t *listener;
jehan's avatar
jehan committed
72
	auth_mode_t auth;
73
	status_t stat;
jehan's avatar
jehan committed
74
	unsigned char expire_in_contact;
jehan's avatar
jehan committed
75 76
	char nonce[32];
	unsigned int nonce_count;
77
	const char *received;
78
	int rport;
79
	unsigned char unreconizable_contact;
80
	int connection_family;
81
	int register_count;
82
	int transiant_network_failure;
83
	belle_sip_refresher_t *refresher;
84
	int early_refresher;
85
	int number_of_body_found;
86
	const char *realm;
87
	unsigned int max_nc_count;
jehan's avatar
jehan committed
88
	bool_t bad_next_nonce;
89 90
	const char *algo;
	const char *ha1;
91
	int retry_after;
jehan's avatar
jehan committed
92 93
} endpoint_t;

Ghislain MARY's avatar
Ghislain MARY committed
94

jehan's avatar
jehan committed
95 96
static unsigned int  wait_for(belle_sip_stack_t*s1, belle_sip_stack_t*s2,int* counter,int value,int timeout) {
	int retry=0;
97
#define ITER 20
jehan's avatar
jehan committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111
	while (*counter<value && retry++ <(timeout/ITER)) {
		if (s1) belle_sip_stack_sleep(s1,ITER/2);
		if (s2) belle_sip_stack_sleep(s2,ITER/2);
	}
	if(*counter<value) return FALSE;
	else return TRUE;
}

//static void process_dialog_terminated(void *obj, const belle_sip_dialog_terminated_event_t *event){
//	belle_sip_message("process_dialog_terminated called");
//}
//static void process_io_error(void *obj, const belle_sip_io_error_event_t *event){
//	belle_sip_warning("process_io_error");
//	/*belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));*/
112
//	/*BC_ASSERT(CU_FALSE);*/
jehan's avatar
jehan committed
113
//}
Ghislain MARY's avatar
Ghislain MARY committed
114

jehan's avatar
jehan committed
115 116 117 118 119 120
static void compute_response(const char* username
									,const char* realm
									,const char* passwd
									,const char* nonce
									,const char* method
									,const char* uri
121 122 123
									,char* response
                                    ,size_t size
                                    ,const char* algo) {
124
	char ha1[MAX_RESPONSE_SIZE],ha2[MAX_RESPONSE_SIZE];
125 126 127
	belle_sip_auth_helper_compute_ha1_for_algorithm(username,realm,passwd,ha1,size,algo);
	belle_sip_auth_helper_compute_ha2_for_algorithm(method,uri,ha2,size,algo);
	belle_sip_auth_helper_compute_response_for_algorithm(ha1,nonce,ha2,response,size,algo);
jehan's avatar
jehan committed
128
}
Ghislain MARY's avatar
Ghislain MARY committed
129

jehan's avatar
jehan committed
130 131 132 133 134 135 136 137 138
static void compute_response_auth_qop(const char* username
										,const char* realm
										,const char* passwd
										,const char* nonce
										,unsigned int nonce_count
										,const char* cnonce
										,const char* qop
										,const char* method
										,const char* uri
139 140 141
                                        ,char* response
                                        ,size_t size
                                        ,const char* algo) {
142
	char ha1[MAX_RESPONSE_SIZE],ha2[MAX_RESPONSE_SIZE];
143 144 145
	belle_sip_auth_helper_compute_ha1_for_algorithm(username,realm,passwd,ha1,size,algo);
	belle_sip_auth_helper_compute_ha2_for_algorithm(method,uri,ha2,size,algo);
	belle_sip_auth_helper_compute_response_qop_auth_for_algorithm(ha1, nonce,nonce_count, cnonce,qop,ha2,response,size,algo);
jehan's avatar
jehan committed
146
}
Ghislain MARY's avatar
Ghislain MARY committed
147

148
#define MAX_NC_COUNT 5
Ghislain MARY's avatar
Ghislain MARY committed
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
static void server_process_request_event(void *obj, const belle_sip_request_event_t *event) {
	endpoint_t *endpoint = (endpoint_t *)obj;
	belle_sip_server_transaction_t *server_transaction = belle_sip_provider_create_server_transaction(endpoint->provider, belle_sip_request_event_get_request(event));
	belle_sip_request_t *req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction));
	belle_sip_response_t *resp;
	belle_sip_header_contact_t *contact;
	belle_sip_header_expires_t *expires;
	belle_sip_header_authorization_t *authorization;
	belle_sip_header_via_t *via;
	const char *raw_authenticate_digest;
	const char *raw_proxy_authenticate_digest;
	if ((endpoint->algo == NULL) || (!strcmp(endpoint->algo, "MD5")) || (!strcmp(endpoint->algo, "MD_SHA"))) {
		raw_authenticate_digest = "WWW-Authenticate: Digest "
		                          "algorithm=MD5, realm=\"" SIPDOMAIN "\", opaque=\"1bc7f9097684320\"";
		raw_proxy_authenticate_digest = "Proxy-Authenticate: Digest "
		                                "algorithm=MD5, realm=\"" SIPDOMAIN "\", opaque=\"1bc7f9097684320\"";
	} else if (!strcmp(endpoint->algo, "SHA-256")) {
		raw_authenticate_digest = "WWW-Authenticate: Digest "
		                          "algorithm=SHA-256, realm=\"" SIPDOMAIN "\", opaque=\"1bc7f9097684320\"";
		raw_proxy_authenticate_digest = "Proxy-Authenticate: Digest "
		                                "algorithm=SHA-256, realm=\"" SIPDOMAIN "\", opaque=\"1bc7f9097684320\"";
	} else {
		belle_sip_error("Algorithm of server must be MD5, SHA-256 or MD_SHA, can not be %s", endpoint->algo);
		return;
jehan's avatar
jehan committed
174
	}
jehan's avatar
jehan committed
175

176 177
	belle_sip_header_www_authenticate_t *www_authenticate = NULL;
	belle_sip_header_www_authenticate_t *two_www_authenticate = NULL;
178
	belle_sip_header_retry_after_t *retry_after_header = NULL;
179 180 181 182 183 184 185 186
	const char *auth_uri;
	const char *qop;
	unsigned char auth_ok = 0;
	size_t size;
	const char *algo;
	const char *algo_ref = "SHA-256";

	belle_sip_message("caller_process_request_event received [%s] message", belle_sip_request_get_method(belle_sip_request_event_get_request(event)));
187 188 189 190 191 192 193 194 195 196 197 198
	
	if (endpoint->retry_after) {
		unsigned int response_code;
		response_code = 404;
		resp = belle_sip_response_create_from_request(belle_sip_request_event_get_request(event), response_code);
		if (www_authenticate) {
			if ((endpoint->algo != NULL) && (!strcmp(endpoint->algo, "MD_SHA"))) {
				two_www_authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_object_clone(BELLE_SIP_OBJECT(www_authenticate)));
				belle_sip_header_www_authenticate_set_algorithm(two_www_authenticate, algo_ref);
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(two_www_authenticate));
			}
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(www_authenticate));
jehan's avatar
jehan committed
199
		}
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
		retry_after_header = BELLE_SIP_HEADER_RETRY_AFTER(belle_sip_header_retry_after_create(endpoint->retry_after));
		
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(retry_after_header));

		endpoint->retry_after = 0;
	} else {
		switch (endpoint->auth) {
			case none: {
				auth_ok = 1;
				break;
			}
			case digest_auth:
			case digest_with_next_nonce:
			case digest_auth_with_next_nonce:
			case digest: {
				if ((authorization = belle_sip_message_get_header_by_type(req, 	belle_sip_header_authorization_t)) != NULL
			        	|| (authorization = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(req, belle_sip_header_proxy_authorization_t))) != NULL) {
					qop = belle_sip_header_authorization_get_qop(authorization);
					if (strcasecmp("REGISTER", belle_sip_request_get_method(req)) == 0) {
						BC_ASSERT_FALSE(BELLE_SIP_OBJECT_IS_INSTANCE_OF(authorization, belle_sip_header_proxy_authorization_t));
					} else {
						BC_ASSERT_TRUE(BELLE_SIP_OBJECT_IS_INSTANCE_OF(authorization, belle_sip_header_proxy_authorization_t));
					}
					algo = belle_sip_header_authorization_get_algorithm(authorization);
					size = belle_sip_auth_define_size(algo);
					if (!size) {
						belle_sip_error("Algorithm [%s] is not correct ", algo);
						return;
					}
					char local_resp[MAX_RESPONSE_SIZE];
					if (qop && strcmp(qop, "auth") == 0) {
						compute_response_auth_qop(belle_sip_header_authorization_get_username(authorization)
232 233 234 235 236 237 238 239
					                          , belle_sip_header_authorization_get_realm(authorization)
					                          , PASSWD
					                          , endpoint->nonce
					                          , endpoint->nonce_count
					                          , belle_sip_header_authorization_get_cnonce(authorization)
					                          , belle_sip_header_authorization_get_qop(authorization)
					                          , belle_sip_request_get_method(req)
					                          , auth_uri = belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization))
240
					                          , local_resp
241 242
					                          , size
					                          , algo);
243 244 245
					} else {
						/*digest*/
						compute_response(belle_sip_header_authorization_get_username(authorization)
246 247 248 249 250 251 252 253 254
					                 , belle_sip_header_authorization_get_realm(authorization)
					                 , PASSWD
					                 , endpoint->nonce
					                 , belle_sip_request_get_method(req)
					                 , auth_uri = belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization))
					                              , local_resp
					                 , size
					                 , algo);

255 256 257
					}
					belle_sip_free((void *)auth_uri);
					auth_ok = strcmp(belle_sip_header_authorization_get_response(authorization), local_resp) == 0;
258
				}
259 260 261 262 263 264
				if (auth_ok && endpoint->nonce_count < endpoint->max_nc_count) { /*revoke nonce after MAX_NC_COUNT uses*/
					if (endpoint->auth == digest || endpoint->auth == digest_with_next_nonce || endpoint->auth == digest_auth_with_next_nonce) {
						sprintf(endpoint->nonce, "%p", authorization); //*change the nonce for next auth*/
					} else {
						endpoint->nonce_count++;
					}
265
				} else {
266 267 268 269 270 271 272 273 274 275 276 277 278 279
					auth_ok = 0;
					if (strcasecmp("REGISTER", belle_sip_request_get_method(req)) == 0) {
						www_authenticate = belle_sip_header_www_authenticate_parse(raw_authenticate_digest);
					} else {
						www_authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_header_proxy_authenticate_parse(raw_proxy_authenticate_digest));
					}
					sprintf(endpoint->nonce, "%p", www_authenticate); //*change the nonce for next auth*/
					belle_sip_header_www_authenticate_set_nonce(www_authenticate, endpoint->nonce);
					if (endpoint->auth == digest_auth || endpoint->auth == digest_auth_with_next_nonce) {
						belle_sip_header_www_authenticate_add_qop(www_authenticate, "auth");
						if (endpoint->nonce_count >= MAX_NC_COUNT) {
							belle_sip_header_www_authenticate_set_stale(www_authenticate, 1);
						}
						endpoint->nonce_count = 1;
280
					}
281
				}
jehan's avatar
jehan committed
282
			}
283
			break;
284 285
			default:
				break;
286
		}
287 288 289 290 291 292 293
		if (auth_ok) {
			resp = belle_sip_response_create_from_request(belle_sip_request_event_get_request(event), 200);
			if (!endpoint->expire_in_contact) {
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(expires = belle_sip_message_get_header_by_type(req, belle_sip_header_expires_t)));
			}
			if (strcmp(belle_sip_request_get_method(req), "REGISTER") == 0) {
				contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t);
jehan's avatar
jehan committed
294
			} else {
295
				contact = belle_sip_header_contact_new();
jehan's avatar
jehan committed
296
			}
297 298 299 300 301 302 303 304 305 306 307 308
			if (endpoint->unreconizable_contact) {
				/*put an unexpected address*/
				belle_sip_uri_set_host(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact)), "nimportequoi.com");
			}
			if (endpoint->auth == digest_with_next_nonce || endpoint->auth == digest_auth_with_next_nonce) {
				belle_sip_header_t *authentication_info;
				if (!endpoint->bad_next_nonce) {
					authentication_info = BELLE_SIP_HEADER(belle_sip_header_authentication_info_new());
					belle_sip_header_authentication_info_set_next_nonce(BELLE_SIP_HEADER_AUTHENTICATION_INFO(authentication_info), endpoint->nonce);
				} else {
					authentication_info = BELLE_SIP_HEADER(belle_sip_header_extension_create(BELLE_SIP_AUTHENTICATION_INFO, "nonce=\"nimporte quoi\" nc="));
				}
309

310
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(authentication_info));
311
			}
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(contact));
			if (strcmp(belle_sip_request_get_method(req), "PUBLISH") == 0) {

				belle_sip_header_t *sip_if_match = belle_sip_message_get_header(BELLE_SIP_MESSAGE(resp), "SIP-If-Match");
				if (sip_if_match) {
					BC_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(sip_if_match)), "blablietag");
				}
				/*check for body*/
				BC_ASSERT_PTR_NOT_NULL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)));
				if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
					BC_ASSERT_STRING_EQUAL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)), publish_body);
				}
				BC_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header_by_type(req, belle_sip_header_content_type_t));
				BC_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header_by_type(req, belle_sip_header_content_length_t));
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), belle_sip_header_create("SIP-ETag", "blablietag"));
327
			}
328 329 330 331 332
			if (strcmp(belle_sip_request_get_method(req), "SUBSCRIBE") == 0) {
				if (belle_sip_request_event_get_dialog(event) == NULL) {
					belle_sip_message("creating dialog for incoming SUBSCRIBE");
					belle_sip_provider_create_dialog(endpoint->provider, BELLE_SIP_TRANSACTION(server_transaction));
				}
333
			}
334
		} else {
335 336 337 338 339 340 341 342 343 344 345 346 347 348
			unsigned int response_code;
			if (strcasecmp("REGISTER", belle_sip_request_get_method(req)) == 0) {
				response_code = 401;
			} else {
				response_code = 407;
			}
			resp = belle_sip_response_create_from_request(belle_sip_request_event_get_request(event), response_code);
			if (www_authenticate) {
				if ((endpoint->algo != NULL) && (!strcmp(endpoint->algo, "MD_SHA"))) {
					two_www_authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_object_clone(BELLE_SIP_OBJECT(www_authenticate)));
					belle_sip_header_www_authenticate_set_algorithm(two_www_authenticate, algo_ref);
					belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(two_www_authenticate));
				}
				belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(www_authenticate));
349 350
			}
		}
jehan's avatar
jehan committed
351
	}
352
	
353
	if (endpoint->received) {
354 355
		via = belle_sip_message_get_header_by_type(req, belle_sip_header_via_t);
		belle_sip_header_via_set_received(via, endpoint->received);
356
	}
357 358 359
	if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
		endpoint->number_of_body_found++;
	}
360
	belle_sip_server_transaction_send_response(server_transaction, resp);
jehan's avatar
jehan committed
361
}
Ghislain MARY's avatar
Ghislain MARY committed
362

363 364 365 366 367 368 369 370 371 372
static void client_process_dialog_terminated(void *obj, const belle_sip_dialog_terminated_event_t *event){
	endpoint_t* endpoint = (endpoint_t*)obj;
	endpoint->stat.dialogTerminated++;
}

static void server_process_dialog_terminated(void *obj, const belle_sip_dialog_terminated_event_t *event){
	endpoint_t* endpoint = (endpoint_t*)obj;
	endpoint->stat.dialogTerminated++;
}

jehan's avatar
jehan committed
373 374 375 376 377 378
static void client_process_response_event(void *obj, const belle_sip_response_event_t *event){
	//belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	endpoint_t* endpoint = (endpoint_t*)obj;
	int status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
	belle_sip_message("caller_process_response_event [%i]",status);
	switch (status) {
379 380 381 382 383 384 385
	case 200:
		endpoint->stat.twoHundredOk++;
		if (endpoint->connection_family!=AF_UNSPEC){
			const char *host;
			int family_found;
			belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type(
				(belle_sip_message_t*)belle_sip_response_event_get_response(event),belle_sip_header_contact_t);
386 387 388 389 390 391
			if (BC_ASSERT_PTR_NOT_NULL(ct)) {
				host=belle_sip_uri_get_host(belle_sip_header_address_get_uri((belle_sip_header_address_t*)ct));
				if (strchr(host,':')) family_found=AF_INET6;
				else family_found=AF_INET;
				BC_ASSERT_EQUAL(family_found,endpoint->connection_family,int,"%d");
			}
392 393
		}
		break;
jehan's avatar
jehan committed
394
	case 401:endpoint->stat.fourHundredOne++; break;
395
	case 407:endpoint->stat.fourHundredSeven++; break;
jehan's avatar
jehan committed
396 397 398 399 400
	default: break;
	}


}
Ghislain MARY's avatar
Ghislain MARY committed
401

jehan's avatar
jehan committed
402 403 404 405 406 407
//static void process_timeout(void *obj, const belle_sip_timeout_event_t *event){
//	belle_sip_message("process_timeout");
//}
//static void process_transaction_terminated(void *obj, const belle_sip_transaction_terminated_event_t *event){
//	belle_sip_message("process_transaction_terminated");
//}
Ghislain MARY's avatar
Ghislain MARY committed
408

409 410 411 412
static void client_process_auth_requested(void *obj, belle_sip_auth_event_t *event) {
	endpoint_t *endpoint = (endpoint_t *)obj;
	if (endpoint->algo == NULL)
		endpoint->algo = "MD5";
jehan's avatar
jehan committed
413
	belle_sip_message("process_auth_requested requested for [%s@%s]"
414 415 416 417 418 419 420 421
	                  , belle_sip_auth_event_get_username(event)
	                  , belle_sip_auth_event_get_realm(event));
	if (((event->algorithm) && (!strcmp(endpoint->algo, event->algorithm)))) {
		if (endpoint->ha1)
			belle_sip_auth_event_set_ha1(event, endpoint->ha1);
		else
			belle_sip_auth_event_set_passwd(event, PASSWD);
	}
jehan's avatar
jehan committed
422
}
jehan's avatar
jehan committed
423

424
static void belle_sip_refresher_listener (belle_sip_refresher_t* refresher
jehan's avatar
jehan committed
425 426
		,void* user_pointer
		,unsigned int status_code
427
		,const char* reason_phrase, int will_retry) {
jehan's avatar
jehan committed
428
	endpoint_t* endpoint = (endpoint_t*)user_pointer;
429
	BELLESIP_UNUSED(refresher);
jehan's avatar
jehan committed
430
	belle_sip_message("belle_sip_refresher_listener [%i] reason [%s]",status_code,reason_phrase);
431 432
	if (status_code >=300)
		endpoint->stat.refreshKo++;
jehan's avatar
jehan committed
433 434
	switch (status_code) {
		case 200:endpoint->stat.refreshOk++; break;
435 436
		case 481:endpoint->stat.fourHundredEightyOne++;break;
		case 503:endpoint->stat.fiveHundredTree++;break;
437
		default:
438
			/*nop*/
439 440 441 442
			break;
	}
	if (endpoint->stat.refreshKo==1 && endpoint->transiant_network_failure) {
		belle_sip_stack_set_send_error(endpoint->stack,0);
443 444 445
	} else 	if (endpoint->stat.refreshOk==1
				&& endpoint->stat.refreshKo==0
				&& endpoint->transiant_network_failure) {
446 447 448
		/*generate a network failure*/
		belle_sip_refresher_set_retry_after(endpoint->refresher,100);
		belle_sip_stack_set_send_error(endpoint->stack,-1);
jehan's avatar
jehan committed
449 450 451
	}
}

452
static endpoint_t* create_endpoint(const char *ip, int port,const char* transport,belle_sip_listener_callbacks_t* listener_callbacks) {
jehan's avatar
jehan committed
453 454 455
	endpoint_t* endpoint = belle_sip_new0(endpoint_t);
	endpoint->stack=belle_sip_stack_new(NULL);
	endpoint->listener_callbacks=listener_callbacks;
456 457
	endpoint->lp=belle_sip_stack_create_listening_point(endpoint->stack,ip,port,transport);
	endpoint->connection_family=AF_INET;
458
	endpoint->max_nc_count=MAX_NC_COUNT;
459

460
	if (endpoint->lp) belle_sip_object_ref(endpoint->lp);
461

jehan's avatar
jehan committed
462
	endpoint->provider=belle_sip_stack_create_provider(endpoint->stack,endpoint->lp);
463
	belle_sip_provider_add_sip_listener(endpoint->provider,(endpoint->listener=belle_sip_listener_create_from_callbacks(endpoint->listener_callbacks,endpoint)));
jehan's avatar
jehan committed
464 465
	sprintf(endpoint->nonce,"%p",endpoint); /*initial nonce*/
	endpoint->nonce_count=1;
466
	endpoint->register_count=3;
467
	endpoint->retry_after=0;
jehan's avatar
jehan committed
468 469
	return endpoint;
}
Simon Morlat's avatar
Simon Morlat committed
470

jehan's avatar
jehan committed
471 472 473 474
static void destroy_endpoint(endpoint_t* endpoint) {
	belle_sip_object_unref(endpoint->lp);
	belle_sip_object_unref(endpoint->provider);
	belle_sip_object_unref(endpoint->stack);
475
	belle_sip_object_unref(endpoint->listener);
jehan's avatar
jehan committed
476 477
	belle_sip_free(endpoint);
}
Simon Morlat's avatar
Simon Morlat committed
478

jehan's avatar
jehan committed
479
static endpoint_t* create_udp_endpoint(int port,belle_sip_listener_callbacks_t* listener_callbacks) {
480
	endpoint_t *endpoint=create_endpoint("0.0.0.0",port,"udp",listener_callbacks);
481
	BC_ASSERT_PTR_NOT_NULL(endpoint->lp);
482
	return endpoint;
jehan's avatar
jehan committed
483
}
Ghislain MARY's avatar
Ghislain MARY committed
484

485

486 487 488 489 490 491
static belle_sip_refresher_t*  refresher_base_with_body2( endpoint_t* client
														, endpoint_t *server
														, const char* method
														, belle_sip_header_content_type_t* content_type
														, const char* body
														, int number_active_refresher) {
jehan's avatar
jehan committed
492 493 494
	belle_sip_request_t* req;
	belle_sip_client_transaction_t* trans;
	belle_sip_header_route_t* destination_route;
495
	belle_sip_refresher_t* refresher;
jehan's avatar
jehan committed
496 497 498
	const char* identity = "sip:" USERNAME "@" SIPDOMAIN ;
	const char* domain="sip:" SIPDOMAIN ;
	belle_sip_header_contact_t* contact=belle_sip_header_contact_new();
499
	belle_sip_uri_t *dest_uri;
500 501
	uint64_t begin;
	uint64_t end;
502
	if (client->expire_in_contact) belle_sip_header_contact_set_expires(contact,1);
503 504


505
	dest_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_listening_point_get_uri(server->lp));
506 507 508 509
	if (client->connection_family==AF_INET6)
		belle_sip_uri_set_host(dest_uri,"::1");
	else
		belle_sip_uri_set_host(dest_uri,"127.0.0.1");
510
	destination_route=belle_sip_header_route_create(belle_sip_header_address_create(NULL,dest_uri));
jehan's avatar
jehan committed
511 512 513 514


	req=belle_sip_request_create(
		                    belle_sip_uri_parse(domain),
515
		                    method,
jehan's avatar
jehan committed
516
		                    belle_sip_provider_create_call_id(client->provider),
517
		                    belle_sip_header_cseq_create(20,method),
jehan's avatar
jehan committed
518 519 520 521
		                    belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG),
		                    belle_sip_header_to_create2(identity,NULL),
		                    belle_sip_header_via_new(),
		                    70);
jehan's avatar
jehan committed
522
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact));
523
	if (!client->expire_in_contact)
jehan's avatar
jehan committed
524 525
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(1)));

jehan's avatar
jehan committed
526
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(destination_route));
527 528 529 530 531 532
	if (content_type && body) {
		size_t body_lenth=strlen(body);
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(content_type));
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(body_lenth)));
		belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),body,body_lenth);
	}
533 534
	if (client->realm
		&&
535
		belle_sip_provider_add_authorization(client->provider, req, NULL, NULL,NULL, client->realm)) {
536

537
	}
jehan's avatar
jehan committed
538
	trans=belle_sip_provider_create_client_transaction(client->provider,req);
539

jehan's avatar
jehan committed
540
	belle_sip_object_ref(trans);/*to avoid trans from being deleted before refresher can use it*/
jehan's avatar
jehan committed
541
	belle_sip_client_transaction_send_request(trans);
542
	if (client->early_refresher) {
543 544 545
		client->refresher = refresher = belle_sip_client_transaction_create_refresher(trans);
		if (client->realm)
			belle_sip_refresher_set_realm(client->refresher, client->realm);
jehan's avatar
jehan committed
546
	} else {
547
		if (server->auth == none) {
548
			BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
549
		} else {
550 551 552 553 554
			if (strcasecmp("REGISTER",belle_sip_request_get_method(req))==0) {
				BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredOne,1,1000));
			} else {
				BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredSeven,1,1000));
			}
555
			/*update cseq*/
556
			req=belle_sip_client_transaction_create_authenticated_request(trans,NULL,NULL);
557 558 559 560
			belle_sip_object_unref(trans);
			trans=belle_sip_provider_create_client_transaction(client->provider,req);
			belle_sip_object_ref(trans);
			belle_sip_client_transaction_send_request(trans);
561
			BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
562
		}
563
		client->refresher= refresher = belle_sip_client_transaction_create_refresher(trans);
jehan's avatar
jehan committed
564
	}
565 566 567
	if (BC_ASSERT_PTR_NOT_NULL(refresher)) {
		belle_sip_object_unref(trans);
		belle_sip_refresher_set_listener(refresher,belle_sip_refresher_listener,client);
568 569
		int timeout = client->retry_after + client->register_count;
		
570
		begin = belle_sip_time_ms();
571
		BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count+(client->early_refresher?1:0), timeout*1000 + 1000));
572
		end = belle_sip_time_ms();
573
		BC_ASSERT_GREATER((long double)(end-begin),(client->register_count/number_active_refresher)*1000*.9,long double,"%Lf"); /*because refresh is at 90% of expire*/
574
		BC_ASSERT_LOWER_STRICT(end-begin,(timeout*1000 + 2000),unsigned long long,"%llu");
575
	}
576 577 578
	return refresher;
}

579 580 581 582 583 584
static void refresher_base_with_body(endpoint_t *client
                                     , endpoint_t *server
                                     , const char *method
                                     , belle_sip_header_content_type_t *content_type
                                     , const char *body) {
	belle_sip_refresher_t  *refresher = refresher_base_with_body2(client, server, method, content_type, body, 1);
585
	/*unregister twice to make sure refresh operation can be safely cascaded*/
586 587 588 589
	belle_sip_refresher_refresh(refresher, 0);
	belle_sip_refresher_refresh(refresher, 0);
	BC_ASSERT_TRUE(wait_for(server->stack, client->stack, &client->stat.refreshOk, client->register_count + 1, 1000));
	BC_ASSERT_EQUAL(client->stat.refreshOk, client->register_count + 1, int, "%d");
590
	belle_sip_refresher_stop(refresher);
591
	belle_sip_object_unref(refresher);
592

593
}
594

595 596 597
static void refresher_base(endpoint_t* client,endpoint_t *server, const char* method) {
	refresher_base_with_body(client,server,method,NULL,NULL);
}
598 599 600
static void register_base(endpoint_t* client,endpoint_t *server) {
	refresher_base(client,server,"REGISTER");
}
601
static void refresher_base_with_param_and_body_for_ha1(const char* method
602 603 604 605
												, unsigned char expire_in_contact
												, auth_mode_t auth_mode
												, int early_refresher
												, belle_sip_header_content_type_t* content_type
606 607
												,const char* body
                                                ,const char* client_algo
608 609
                                                ,const char* server_algo
                                                ,const char* ha1){
610 611 612 613 614 615 616 617 618 619 620 621
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=client->expire_in_contact=expire_in_contact;
	server->auth=auth_mode;
622 623
	server->algo=server_algo;
	client->algo=client_algo;
624
	client->early_refresher=early_refresher;
625 626 627
	if(ha1){
		client->ha1=ha1;
	}
628
	refresher_base_with_body(client,server,method,content_type,body);
jehan's avatar
jehan committed
629 630
	destroy_endpoint(client);
	destroy_endpoint(server);
jehan's avatar
jehan committed
631
}
632 633 634 635 636 637 638 639 640

static void refresher_base_with_param_and_body(const char* method
                                               , unsigned char expire_in_contact
                                               , auth_mode_t auth_mode
                                               , int early_refresher
                                               , belle_sip_header_content_type_t* content_type
                                               ,const char* body
                                               ,const char* client_algo
                                               ,const char* server_algo){
641
	refresher_base_with_param_and_body_for_ha1(method,expire_in_contact,auth_mode,early_refresher,content_type,body,client_algo,server_algo,NULL);
642 643 644 645
}

static void refresher_base_with_param(const char* method, unsigned char expire_in_contact,auth_mode_t auth_mode,const char* client_algo,const char* server_algo,const char* ha1) {
	refresher_base_with_param_and_body_for_ha1(method,expire_in_contact,auth_mode,FALSE,NULL,NULL,client_algo,server_algo,ha1);
646 647

}
648 649

static void register_test_with_param_for_algorithm(unsigned char expire_in_contact,auth_mode_t auth_mode,const char* client_algo,const char* server_algo) {
650
	refresher_base_with_param("REGISTER",expire_in_contact,auth_mode,client_algo,server_algo,NULL);
651 652 653
}

static void register_test_with_param_for_algorithm_ha1(unsigned char expire_in_contact,auth_mode_t auth_mode,const char* client_algo,const char* server_algo,const char* ha1){
654
	refresher_base_with_param("REGISTER",expire_in_contact,auth_mode,client_algo,server_algo,ha1);
655 656
}

657
static void register_test_with_param(unsigned char expire_in_contact,auth_mode_t auth_mode) {
658
	register_test_with_param_for_algorithm(expire_in_contact,auth_mode,NULL,NULL);
659
}
660

661 662 663 664 665 666 667 668
static char *list =	"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
						"<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\"\n"
						"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
						"<list>\n"
							"\t<entry uri=\"sip:marie@sexample.com\" />\n"
							"\t<entry uri=\"sip:pauline@sexample.com\" />\n"
						"</list>\n"
					"</resource-lists>\n";
669

670 671

static void subscribe_base(int with_resource_lists) {
672 673 674 675 676 677 678
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	belle_sip_request_t* req;
	belle_sip_client_transaction_t* trans;
	belle_sip_header_route_t* destination_route;
	const char* identity = "sip:" USERNAME "@" SIPDOMAIN ;
	const char* domain="sip:" SIPDOMAIN ;
679 680
	endpoint_t* client,*server;
	belle_sip_uri_t *dest_uri;
681
	belle_sip_refresher_t* refresher;
682
	belle_sip_header_contact_t* contact=belle_sip_header_contact_new();
683
	belle_sip_dialog_t * client_dialog;
684
	char *call_id = NULL;
685
	int dummy = 0;
686 687
	uint64_t begin;
	uint64_t end;
688 689 690
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));

691
	client_callbacks.process_dialog_terminated=client_process_dialog_terminated;
692 693 694
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
695
	server_callbacks.process_dialog_terminated=server_process_dialog_terminated;
696

697 698
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
699 700
	server->expire_in_contact=0;
	server->auth=digest_auth;
701

702 703 704
	dest_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_listening_point_get_uri(server->lp));
	belle_sip_uri_set_host(dest_uri,"127.0.0.1");
	destination_route=belle_sip_header_route_create(belle_sip_header_address_create(NULL,dest_uri));
705 706 707 708 709 710 711 712 713 714 715 716 717


	req=belle_sip_request_create(
		                    belle_sip_uri_parse(domain),
		                    "SUBSCRIBE",
		                    belle_sip_provider_create_call_id(client->provider),
		                    belle_sip_header_cseq_create(20,"SUBSCRIBE"),
		                    belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG),
		                    belle_sip_header_to_create2(identity,NULL),
		                    belle_sip_header_via_new(),
		                    70);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(1)));
jehan's avatar
jehan committed
718
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_create("Event","Presence")));
719 720

	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(destination_route));
721 722 723 724
	if (with_resource_lists) {
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","resource-lists+xml")));
		belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), list, strlen(list));
	}
725

726 727 728 729
	trans=belle_sip_provider_create_client_transaction(client->provider,req);
	belle_sip_object_ref(trans);/*to avoid trans from being deleted before refresher can use it*/
	belle_sip_client_transaction_send_request(trans);

730
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredSeven,1,1000));
731

732
	req=belle_sip_client_transaction_create_authenticated_request(trans,NULL,NULL);
733 734 735 736
	belle_sip_object_unref(trans);
	trans=belle_sip_provider_create_client_transaction(client->provider,req);
	belle_sip_object_ref(trans);
	belle_sip_client_transaction_send_request(trans);
737
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
738
	 /*maybe dialog should be automatically created*/
739
	BC_ASSERT_PTR_NOT_NULL(client_dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(trans)));
740 741
	call_id = belle_sip_strdup(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(client_dialog)));
	belle_sip_object_ref(client_dialog);
742

743
	refresher = belle_sip_client_transaction_create_refresher(trans);
744 745 746
	belle_sip_object_unref(trans);
	belle_sip_refresher_set_listener(refresher,belle_sip_refresher_listener,client);

747
	begin = belle_sip_time_ms();
748
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,3,4000));
749
	end = belle_sip_time_ms();
750
	BC_ASSERT_GREATER((long double)(end-begin),3000*.9,long double,"%Lf");
Simon Morlat's avatar
Simon Morlat committed
751
	BC_ASSERT_LOWER_STRICT(end-begin,5000,unsigned long long,"%llu");
752

jehan's avatar
jehan committed
753
	belle_sip_message("simulating dialog error and recovery");
Simon Morlat's avatar
Simon Morlat committed
754
	belle_sip_stack_set_send_error(client->stack, 1);
jehan's avatar
jehan committed
755
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredEightyOne,1,4000));
Simon Morlat's avatar
Simon Morlat committed
756 757
	/*let the transaction timeout*/
	wait_for(server->stack,client->stack, &dummy, 1, 32000);
758
	belle_sip_stack_set_send_error(client->stack, 0);
759

760

761 762
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,4,4000));
	BC_ASSERT_EQUAL(client->stat.dialogTerminated, 0, int, "%i");
763

764 765
	/*make sure dialog has changed*/
	BC_ASSERT_PTR_NOT_EQUAL(client_dialog, belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))));
766 767 768
	BC_ASSERT_STRING_NOT_EQUAL(call_id, belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))))));
	belle_sip_free(call_id);
	belle_sip_object_unref(client_dialog);
769

770
	belle_sip_message("simulating dialog terminated server side and recovery");
771

772
	client_dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
773 774
	call_id = belle_sip_strdup(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(client_dialog)));
	belle_sip_object_ref(client_dialog);
775

776 777 778
	belle_sip_provider_enable_unconditional_answer(server->provider,TRUE);
	belle_sip_provider_set_unconditional_answer(server->provider,481);
	belle_sip_refresher_refresh(refresher, 10);
779

780 781 782 783 784
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredEightyOne,2,4000));
	belle_sip_provider_enable_unconditional_answer(server->provider,FALSE);

	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,5,4000));
	BC_ASSERT_EQUAL(client->stat.dialogTerminated, 0, int, "%i");
785

786 787
	/*make sure dialog has changed*/
	BC_ASSERT_PTR_NOT_EQUAL(client_dialog, belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))));
788 789 790
	BC_ASSERT_STRING_NOT_EQUAL(call_id, belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))))));
	belle_sip_free(call_id);
	belle_sip_object_unref(client_dialog);
791 792
	belle_sip_refresher_refresh(refresher, 0);
	belle_sip_refresher_refresh(refresher, 0);
793

794
	belle_sip_refresher_stop(refresher);
Simon Morlat's avatar
Simon Morlat committed
795
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&server->stat.dialogTerminated,3,4000));
796

797
	belle_sip_object_unref(refresher);
798

799 800 801 802 803 804
/*
Peio : assert qui pète à chaque fois et ce bug DOIT être corrigé.
il serait utile de commenter l'assert afin de savoir à quoi elle sert précisément
avant d'avoir à relire tout le code qui lui est liée.  
Issue assignée à Jehan

805 806
	if (with_resource_lists) {
		BC_ASSERT_EQUAL(server->number_of_body_found, (server->auth == none ?1:2), int, "%i");
807 808
	}*/

809

810 811 812 813
	destroy_endpoint(client);
	destroy_endpoint(server);
}

814 815 816 817 818 819
static void subscribe_test(void) {
	subscribe_base(FALSE);
}
static void subscribe_list_test(void) {
	subscribe_base(TRUE);
}
820

821
static void register_expires_header(void) {
jehan's avatar
jehan committed
822 823
	register_test_with_param(0,none);
}
Ghislain MARY's avatar
Ghislain MARY committed
824

825
static void register_expires_in_contact(void) {
jehan's avatar
jehan committed
826 827
	register_test_with_param(1,none);
}
Ghislain MARY's avatar
Ghislain MARY committed
828

829
static void register_expires_header_digest(void) {
jehan's avatar
jehan committed
830 831
	register_test_with_param(0,digest);
}
jehan's avatar
jehan committed
832

833
static void register_expires_in_contact_header_digest_auth(void) {
jehan's avatar
jehan committed
834 835
	register_test_with_param(1,digest_auth);
}
836

837
static void register_expires_in_contact_header_digest_auth_sha256(void) {
838
	register_test_with_param_for_algorithm(1, digest_auth, "SHA-256", "SHA-256");
839 840 841
}

static void register_expires_in_contact_header_digest_md_sha(void) {
842
	register_test_with_param_for_algorithm(1, digest_auth, "MD5", "MD_SHA");
843 844
}

845
static void register_expires_in_contact_header_digest_md_sha_ha1(void) {
846
	register_test_with_param_for_algorithm_ha1(1, digest_auth, "MD5", "MD_SHA", "323897f425eb3f4c22efa4119c85b434");
847 848
}

849
static void register_expires_in_contact_header_digest_md_sha256(void) {
850
	register_test_with_param_for_algorithm(1, digest_auth, "SHA-256", "MD_SHA");
851 852
}

853
static void register_expires_in_contact_header_digest_md_sha256_ha1(void) {
854
	register_test_with_param_for_algorithm_ha1(1, digest_auth, "SHA-256", "MD_SHA", "ebf7a06f8211417d6735cd8bfcbecc30ef2045a80d1d6148a6b9d5d3c4f76911");
855 856
}

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
static void register_with_failure(void) {
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=1;
	server->auth=digest;
	client->transiant_network_failure=1;
	register_base(client,server);
872
	BC_ASSERT_EQUAL(client->stat.refreshKo,1,int,"%d");
873 874 875
	destroy_endpoint(client);
	destroy_endpoint(server);
}
Ghislain MARY's avatar
Ghislain MARY committed
876
static void register_with_unrecognizable_contact(void) {
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=1;
	server->unreconizable_contact=1;
	server->auth=digest;
	register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);
}
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
static void register_early_refresher(void) {
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=1;
	server->auth=digest;
	client->early_refresher=1;
	register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);
}
912

913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
static void register_retry_after(void) {
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=1;
	server->auth=digest;
	client->early_refresher=1;
	server->retry_after = 2;
	client->retry_after = 2;
	register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);
}

934 935 936 937 938 939 940 941 942 943 944 945
static int register_test_with_interfaces(const char *transport, const char *client_ip, const char *server_ip, int connection_family) {
	int ret=0;
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_endpoint(client_ip,3452,transport,&client_callbacks);
	client->connection_family=connection_family;
946
	client->register_count=1;
947

948 949 950 951 952 953 954 955 956 957 958 959 960
	server = create_endpoint(server_ip,6788,transport,&server_callbacks);
	server->expire_in_contact=client->expire_in_contact=0;
	server->auth=none;

	if (client->lp==NULL || server->lp==NULL){
		belle_sip_warning("Cannot check ipv6 because host has no ipv6 support.");
		ret=-1;
	}else register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);
	return ret;
}

961 962 963 964 965 966 967 968 969 970 971 972 973
static int register_test_with_random_port(const char *transport, const char *client_ip, const char *server_ip, int connection_family) {
	int ret=0;
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_endpoint(client_ip,-1,transport,&client_callbacks);
	client->connection_family=connection_family;
	client->register_count=1;
974

975 976 977 978 979 980 981 982 983 984 985 986 987
	server = create_endpoint(server_ip,6788,transport,&server_callbacks);
	server->expire_in_contact=client->expire_in_contact=0;
	server->auth=none;

	if (client->lp==NULL || server->lp==NULL){
		belle_sip_warning("Cannot check ipv6 because host has no ipv6 support.");
		ret=-1;
	}else register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);
	return ret;
}

988
static void register_test_ipv6_to_ipv4(void){
989 990 991 992
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
993 994 995 996
	register_test_with_interfaces("udp","::0","0.0.0.0",AF_INET);
}

static void register_test_ipv4_to_ipv6(void){
997 998 999 1000
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1001 1002 1003 1004
	register_test_with_interfaces("udp","0.0.0.0","::0",AF_INET);
}

static void register_test_ipv6_to_ipv6_with_ipv4(void){
1005 1006 1007 1008
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1009 1010 1011 1012
	register_test_with_interfaces("udp","::0","::0",AF_INET);
}

static void register_test_ipv6_to_ipv6_with_ipv6(void){
1013 1014 1015 1016
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1017 1018 1019
	register_test_with_interfaces("udp","::0","::0",AF_INET6);
}

1020
static void register_tcp_test_ipv6_to_ipv4(void){
1021 1022 1023 1024
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1025 1026 1027 1028
	register_test_with_interfaces("tcp","::0","0.0.0.0",AF_INET);
}

static void register_tcp_test_ipv4_to_ipv6(void){
1029 1030 1031 1032
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1033 1034 1035 1036
	register_test_with_interfaces("tcp","0.0.0.0","::0",AF_INET);
}

static void register_tcp_test_ipv6_to_ipv6_with_ipv4(void){
1037 1038 1039 1040
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1041 1042 1043 1044
	register_test_with_interfaces("tcp","::0","::0",AF_INET);
}

static void register_tcp_test_ipv6_to_ipv6_with_ipv6(void){
1045 1046 1047 1048
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1049 1050 1051
	register_test_with_interfaces("tcp","::0","::0",AF_INET6);
}

1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
static void register_udp_test_ipv4_random_port(void){
	register_test_with_random_port("udp","0.0.0.0","0.0.0.0",AF_INET);
}

static void register_udp_test_ipv6_random_port(void){
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
	register_test_with_random_port("udp","::0","0.0.0.0",AF_INET);
}

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
static void register_tcp_test_ipv4_random_port(void){
	register_test_with_random_port("tcp","0.0.0.0","0.0.0.0",AF_INET);
}

static void register_tcp_test_ipv6_random_port(void){
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
	register_test_with_random_port("tcp","::0","0.0.0.0",AF_INET);
}

1076
static void simple_publish(void) {
1077
	belle_sip_header_content_type_t* content_type=belle_sip_header_content_type_create("application","pidf+xml");
1078
	refresher_base_with_param_and_body("PUBLISH",FALSE,TRUE,FALSE, content_type,publish_body,"MD5","MD5");
1079 1080

}
1081
static void simple_publish_with_early_refresher(void) {
1082
	belle_sip_header_content_type_t* content_type=belle_sip_header_content_type_create("application","pidf+xml");
1083
	refresher_base_with_param_and_body("PUBLISH",FALSE,TRUE,TRUE, content_type,publish_body,"MD5","MD5");
1084

1085
}
1086

1087 1088 1089 1090 1091 1092 1093
static void register_and_publish(void) {
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	belle_sip_refresher_t *register_refresher;
	belle_sip_refresher_t *publish_refresher;
	belle_sip_header_content_type_t* content_type=belle_sip_header_content_type_create("application","pidf+xml");
1094

1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->expire_in_contact=TRUE;
	server->auth=digest_auth;
	client->early_refresher=TRUE;
	client->realm = SIPDOMAIN;
	register_refresher = refresher_base_with_body2(client,server,"REGISTER",NULL,NULL,1);
1107

1108 1109 1110 1111
	client->register_count = 2 * client->register_count;
	client->stat.refreshOk = 0;
	/*to make sure we can still use same nonce*/
	client->nonce_count -=2;
1112

1113
	publish_refresher = refresher_base_with_body2(client,server,"PUBLISH",content_type,publish_body,2);
1114

1115 1116 1117 1118 1119
	belle_sip_refresher_refresh(register_refresher,0);
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count+1,1000));
	BC_ASSERT_EQUAL(client->stat.refreshOk,client->register_count+1,int,"%d");
	belle_sip_refresher_stop(register_refresher);
	belle_sip_object_unref(register_refresher);
1120 1121


1122 1123 1124 1125 1126
	belle_sip_refresher_refresh(publish_refresher,0);
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count+1,1000));
	BC_ASSERT_EQUAL(client->stat.refreshOk,client->register_count+1,int,"%d");
	belle_sip_refresher_stop(publish_refresher);
	belle_sip_object_unref(publish_refresher);
1127

1128 1129 1130 1131
	destroy_endpoint(client);
	destroy_endpoint(server);
}

jehan's avatar
jehan committed
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
static void register_digest_with_next_nonce(void) {
	register_test_with_param(0,digest_with_next_nonce);
}

static void register_digest_auth_with_next_nonce(void) {
	register_test_with_param(0,digest_auth_with_next_nonce);
}

static void register_digest_auth_with_bad_next_nonce(void) {
	belle_sip_listener_callbacks_t client_callbacks;
	belle_sip_listener_callbacks_t server_callbacks;
	endpoint_t* client,*server;
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	client_callbacks.process_response_event=client_process_response_event;
	client_callbacks.process_auth_requested=client_process_auth_requested;
	server_callbacks.process_request_event=server_process_request_event;
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
	server->auth=digest_auth_with_next_nonce;
	server->bad_next_nonce = TRUE;
	register_base(client,server);
	destroy_endpoint(client);
	destroy_endpoint(server);

}


Ghislain MARY's avatar
Ghislain MARY committed
1160
test_t refresher_tests[] = {
1161 1162 1163 1164
	TEST_NO_TAG("REGISTER Expires header", register_expires_header),
	TEST_NO_TAG("REGISTER Expires in Contact", register_expires_in_contact),
	TEST_NO_TAG("REGISTER Expires header digest", register_expires_header_digest),
	TEST_NO_TAG("REGISTER Expires in Contact digest auth", register_expires_in_contact_header_digest_auth),
1165 1166 1167 1168 1169
	TEST_NO_TAG("REGISTER Expires in Contact digest auth SHA-256", register_expires_in_contact_header_digest_auth_sha256),
	TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA", register_expires_in_contact_header_digest_md_sha),
	TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA ha1", register_expires_in_contact_header_digest_md_sha_ha1),
	TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA-256", register_expires_in_contact_header_digest_md_sha256),
	TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA-256 ha1", register_expires_in_contact_header_digest_md_sha256_ha1),
1170
	TEST_NO_TAG("REGISTER with failure", register_with_failure),
1171
	TEST_NO_TAG("REGISTER with early refresher", register_early_refresher),
1172
	TEST_NO_TAG("REGISTER with retry after", register_retry_after),
Simon Morlat's avatar
Simon Morlat committed
1173
	TEST_NO_TAG("SUBSCRIBE", subscribe_test),
Simon Morlat's avatar
Simon Morlat committed
1174
	TEST_NO_TAG("SUBSCRIBE of list" , subscribe_list_test),
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
	TEST_NO_TAG("PUBLISH", simple_publish),
	TEST_NO_TAG("PUBLISH with early refresher", simple_publish_with_early_refresher),
	TEST_NO_TAG("REGISTER with unrecognizable Contact", register_with_unrecognizable_contact),
	TEST_NO_TAG("REGISTER UDP from ipv6 to ipv4", register_test_ipv6_to_ipv4),
	TEST_NO_TAG("REGISTER UDP from ipv4 to ipv6", register_test_ipv4_to_ipv6),
	TEST_NO_TAG("REGISTER UDP from ipv6 to ipv6 with ipv4", register_test_ipv6_to_ipv6_with_ipv4),
	TEST_NO_TAG("REGISTER UDP from ipv6 to ipv6 with ipv6", register_test_ipv6_to_ipv6_with_ipv6),
	TEST_NO_TAG("REGISTER TCP from ipv6 to ipv4", register_tcp_test_ipv6_to_ipv4),
	TEST_NO_TAG("REGISTER TCP from ipv4 to ipv6", register_tcp_test_ipv4_to_ipv6),
	TEST_NO_TAG("REGISTER TCP from ipv6 to ipv6 with ipv4", register_tcp_test_ipv6_to_ipv6_with_ipv4),
	TEST_NO_TAG("REGISTER TCP from ipv6 to ipv6 with ipv6", register_tcp_test_ipv6_to_ipv6_with_ipv6),
	TEST_NO_TAG("REGISTER UDP from random port using AF_INET", register_udp_test_ipv4_random_port),
	TEST_NO_TAG("REGISTER UDP from random port using AF_INET6", register_udp_test_ipv6_random_port),
	TEST_NO_TAG("REGISTER TCP from random port using AF_INET", register_tcp_test_ipv4_random_port),
	TEST_NO_TAG("REGISTER TCP from random port using AF_INET6", register_tcp_test_ipv6_random_port),
1190
	TEST_NO_TAG("REGISTER AND PUBLISH", register_and_publish),
jehan's avatar
jehan committed
1191 1192 1193
	TEST_NO_TAG("REGISTER, digest with next nonce", register_digest_with_next_nonce),
	TEST_NO_TAG("REGISTER, digest auth with next nonce", register_digest_auth_with_next_nonce),
	TEST_NO_TAG("REGISTER, digest auth with bad next nonce", register_digest_auth_with_bad_next_nonce)
1194

Ghislain MARY's avatar
Ghislain MARY committed
1195 1196
};

1197 1198
test_suite_t refresher_test_suite = {"Refresher", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
									 sizeof(refresher_tests) / sizeof(refresher_tests[0]), refresher_tests};