belle_sip_refresher_tester.c 49.1 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 67 68 69 70
typedef struct endpoint {
	belle_sip_stack_t* stack;
	belle_sip_listener_callbacks_t* listener_callbacks;
	belle_sip_provider_t* provider;
	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 78
	const char* received;
	int rport;
79
	unsigned char unreconizable_contact;
80
	int connection_family;
81
	int register_count;
82 83
	int transiant_network_failure;
	belle_sip_refresher_t* refresher;
84
	int early_refresher;
85
	int number_of_body_found;
86 87
	const char* realm;
	unsigned int max_nc_count;
jehan's avatar
jehan committed
88
	bool_t bad_next_nonce;
89
    const char* algo;
90
    const char* ha1;
jehan's avatar
jehan committed
91 92
} endpoint_t;

Ghislain MARY's avatar
Ghislain MARY committed
93

jehan's avatar
jehan committed
94 95
static unsigned int  wait_for(belle_sip_stack_t*s1, belle_sip_stack_t*s2,int* counter,int value,int timeout) {
	int retry=0;
96
#define ITER 20
jehan's avatar
jehan committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110
	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));*/
111
//	/*BC_ASSERT(CU_FALSE);*/
jehan's avatar
jehan committed
112
//}
Ghislain MARY's avatar
Ghislain MARY committed
113

jehan's avatar
jehan committed
114 115 116 117 118 119
static void compute_response(const char* username
									,const char* realm
									,const char* passwd
									,const char* nonce
									,const char* method
									,const char* uri
120 121 122 123 124 125 126
									,char* response
                                    ,size_t size
                                    ,const char* algo) {
	char ha1[size],ha2[size];
	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
127
}
Ghislain MARY's avatar
Ghislain MARY committed
128

jehan's avatar
jehan committed
129 130 131 132 133 134 135 136 137
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
138 139 140 141 142 143 144
                                        ,char* response
                                        ,size_t size
                                        ,const char* algo) {
    char ha1[size],ha2[size];
	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
145
}
Ghislain MARY's avatar
Ghislain MARY committed
146

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

jehan's avatar
jehan committed
149 150 151 152 153
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;
jehan's avatar
jehan committed
154 155 156
	belle_sip_header_contact_t* contact;
	belle_sip_header_expires_t* expires;
	belle_sip_header_authorization_t* authorization;
157
	belle_sip_header_via_t* via;
158 159
    const char* raw_authenticate_digest;
    const char* raw_proxy_authenticate_digest;
160
    if((endpoint->algo==NULL)||(!strcmp(endpoint->algo,"MD5"))||(!strcmp(endpoint->algo,"MD_SHA"))){
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        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
177
	belle_sip_header_www_authenticate_t* www_authenticate=NULL;
178
    belle_sip_header_www_authenticate_t* two_www_authenticate=NULL;
jehan's avatar
jehan committed
179 180 181
	const char* auth_uri;
	const char* qop;
	unsigned char auth_ok=0;
182 183 184
    size_t size;
    const char* algo;
    const char* algo_ref="SHA-256";
jehan's avatar
jehan committed
185

jehan's avatar
jehan committed
186 187 188 189
	belle_sip_message("caller_process_request_event received [%s] message",belle_sip_request_get_method(belle_sip_request_event_get_request(event)));

	switch (endpoint->auth) {
	case none: {
jehan's avatar
jehan committed
190
		auth_ok=1;
jehan's avatar
jehan committed
191 192
		break;
	}
jehan's avatar
jehan committed
193
	case digest_auth:
jehan's avatar
jehan committed
194 195
	case digest_with_next_nonce:
	case digest_auth_with_next_nonce:
jehan's avatar
jehan committed
196
	case digest: {
197 198
		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  ){
jehan's avatar
jehan committed
199
			qop=belle_sip_header_authorization_get_qop(authorization);
200 201 202 203 204
			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));
			}
205 206 207 208 209 210 211
            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[size];
jehan's avatar
jehan committed
212 213 214 215 216 217 218 219 220 221
			if (qop && strcmp(qop,"auth")==0) {
				compute_response_auth_qop(	belle_sip_header_authorization_get_username(authorization)
											,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))
222 223 224
											,local_resp
                                            ,size
                                            ,algo);
jehan's avatar
jehan committed
225 226 227 228 229 230 231 232
			} else {
				/*digest*/
				compute_response(belle_sip_header_authorization_get_username(authorization)
						,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))
233 234 235
						,local_resp
                        ,size
                        ,algo);
jehan's avatar
jehan committed
236 237 238 239 240

			}
			belle_sip_free((void*)auth_uri);
			auth_ok=strcmp(belle_sip_header_authorization_get_response(authorization),local_resp)==0;
		}
241
		if (auth_ok && endpoint->nonce_count < endpoint->max_nc_count ) {/*revoke nonce after MAX_NC_COUNT uses*/
jehan's avatar
jehan committed
242
			if (endpoint->auth == digest || endpoint->auth == digest_with_next_nonce || endpoint->auth == digest_auth_with_next_nonce) {
243
				sprintf(endpoint->nonce,"%p",authorization); //*change the nonce for next auth*/
jehan's avatar
jehan committed
244 245 246 247
			} else {
				endpoint->nonce_count++;
			}
		} else {
248
			auth_ok=0;
249 250 251 252 253 254
			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*/
jehan's avatar
jehan committed
255
			belle_sip_header_www_authenticate_set_nonce(www_authenticate,endpoint->nonce);
jehan's avatar
jehan committed
256
			if (endpoint->auth == digest_auth || endpoint->auth == digest_auth_with_next_nonce) {
jehan's avatar
jehan committed
257
				belle_sip_header_www_authenticate_add_qop(www_authenticate,"auth");
258 259 260
				if (endpoint->nonce_count>=MAX_NC_COUNT) {
					belle_sip_header_www_authenticate_set_stale(www_authenticate,1);
				}
261
				endpoint->nonce_count=1;
jehan's avatar
jehan committed
262 263 264 265
			}
		}
	}
	break;
jehan's avatar
jehan committed
266 267 268
	default:
		break;
	}
jehan's avatar
jehan committed
269 270 271 272 273
	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)));
		}
274 275 276 277 278
		if (strcmp(belle_sip_request_get_method(req),"REGISTER")==0) {
			contact=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
		} else {
			contact=belle_sip_header_contact_new();
		}
279
		if(endpoint->unreconizable_contact) {
280
			/*put an unexpected address*/
281 282
			belle_sip_uri_set_host(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact)),"nimportequoi.com");
		}
jehan's avatar
jehan committed
283 284 285 286 287 288 289 290 291 292 293
		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=")); 
			}
				
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), BELLE_SIP_HEADER(authentication_info));
		}
294
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(contact));
295
		if (strcmp(belle_sip_request_get_method(req),"PUBLISH")==0) {
296 297 298

			belle_sip_header_t* sip_if_match=belle_sip_message_get_header(BELLE_SIP_MESSAGE(resp),"SIP-If-Match");
			if (sip_if_match) {
299
				BC_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(sip_if_match)),"blablietag");
300
			}
301
			/*check for body*/
302
			BC_ASSERT_PTR_NOT_NULL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)));
303
			if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
304
				BC_ASSERT_STRING_EQUAL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),publish_body);
305
			}
306 307
			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));
308 309
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),belle_sip_header_create("SIP-ETag","blablietag"));
		}
310 311 312 313 314 315
		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));
			}
		}
jehan's avatar
jehan committed
316
	} else {
317 318 319 320 321 322 323
		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);
324
        if (www_authenticate){
325
            if ((endpoint->algo!=NULL)&&(!strcmp(endpoint->algo,"MD_SHA"))){
326 327 328 329 330 331
                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
332
	}
333 334 335 336
	if (endpoint->received) {
		via=belle_sip_message_get_header_by_type(req,belle_sip_header_via_t);
		belle_sip_header_via_set_received(via,endpoint->received);
	}
337 338 339
	if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
		endpoint->number_of_body_found++;
	}
jehan's avatar
jehan committed
340 341
	belle_sip_server_transaction_send_response(server_transaction,resp);
}
Ghislain MARY's avatar
Ghislain MARY committed
342

343 344 345 346 347 348 349 350 351 352
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
353 354 355 356 357 358
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) {
359 360 361 362 363 364 365
	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);
366 367 368 369 370 371
			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");
			}
372 373
		}
		break;
jehan's avatar
jehan committed
374
	case 401:endpoint->stat.fourHundredOne++; break;
375
	case 407:endpoint->stat.fourHundredSeven++; break;
jehan's avatar
jehan committed
376 377 378 379 380
	default: break;
	}


}
Ghislain MARY's avatar
Ghislain MARY committed
381

jehan's avatar
jehan committed
382 383 384 385 386 387
//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
388

jehan's avatar
jehan committed
389
static void client_process_auth_requested(void *obj, belle_sip_auth_event_t *event){
390
    endpoint_t* endpoint = (endpoint_t*)obj;
391 392
    if(endpoint->algo==NULL)
        endpoint->algo = "MD5";
jehan's avatar
jehan committed
393 394 395
	belle_sip_message("process_auth_requested requested for [%s@%s]"
			,belle_sip_auth_event_get_username(event)
			,belle_sip_auth_event_get_realm(event));
396
    if (((event->algorithm)&&(!strcmp(endpoint->algo,event->algorithm)))){
397 398 399 400 401
        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
402
}
jehan's avatar
jehan committed
403

404
static void belle_sip_refresher_listener (belle_sip_refresher_t* refresher
jehan's avatar
jehan committed
405 406
		,void* user_pointer
		,unsigned int status_code
407
		,const char* reason_phrase, int will_retry) {
jehan's avatar
jehan committed
408
	endpoint_t* endpoint = (endpoint_t*)user_pointer;
409
	BELLESIP_UNUSED(refresher);
jehan's avatar
jehan committed
410
	belle_sip_message("belle_sip_refresher_listener [%i] reason [%s]",status_code,reason_phrase);
411 412
	if (status_code >=300)
		endpoint->stat.refreshKo++;
jehan's avatar
jehan committed
413 414
	switch (status_code) {
		case 200:endpoint->stat.refreshOk++; break;
415 416
		case 481:endpoint->stat.fourHundredEightyOne++;break;
		case 503:endpoint->stat.fiveHundredTree++;break;
417
		default:
418
			/*nop*/
419 420 421 422
			break;
	}
	if (endpoint->stat.refreshKo==1 && endpoint->transiant_network_failure) {
		belle_sip_stack_set_send_error(endpoint->stack,0);
423 424 425
	} else 	if (endpoint->stat.refreshOk==1
				&& endpoint->stat.refreshKo==0
				&& endpoint->transiant_network_failure) {
426 427 428
		/*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
429 430 431
	}
}

432
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
433 434 435
	endpoint_t* endpoint = belle_sip_new0(endpoint_t);
	endpoint->stack=belle_sip_stack_new(NULL);
	endpoint->listener_callbacks=listener_callbacks;
436 437
	endpoint->lp=belle_sip_stack_create_listening_point(endpoint->stack,ip,port,transport);
	endpoint->connection_family=AF_INET;
438
	endpoint->max_nc_count=MAX_NC_COUNT;
439

440
	if (endpoint->lp) belle_sip_object_ref(endpoint->lp);
441

jehan's avatar
jehan committed
442
	endpoint->provider=belle_sip_stack_create_provider(endpoint->stack,endpoint->lp);
443
	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
444 445
	sprintf(endpoint->nonce,"%p",endpoint); /*initial nonce*/
	endpoint->nonce_count=1;
446
	endpoint->register_count=3;
jehan's avatar
jehan committed
447 448
	return endpoint;
}
Simon Morlat's avatar
Simon Morlat committed
449

jehan's avatar
jehan committed
450 451 452 453
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);
454
	belle_sip_object_unref(endpoint->listener);
jehan's avatar
jehan committed
455 456
	belle_sip_free(endpoint);
}
Simon Morlat's avatar
Simon Morlat committed
457

jehan's avatar
jehan committed
458
static endpoint_t* create_udp_endpoint(int port,belle_sip_listener_callbacks_t* listener_callbacks) {
459
	endpoint_t *endpoint=create_endpoint("0.0.0.0",port,"udp",listener_callbacks);
460
	BC_ASSERT_PTR_NOT_NULL(endpoint->lp);
461
	return endpoint;
jehan's avatar
jehan committed
462
}
Ghislain MARY's avatar
Ghislain MARY committed
463

464

465 466 467 468 469 470
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
471 472 473
	belle_sip_request_t* req;
	belle_sip_client_transaction_t* trans;
	belle_sip_header_route_t* destination_route;
474
	belle_sip_refresher_t* refresher;
jehan's avatar
jehan committed
475 476 477
	const char* identity = "sip:" USERNAME "@" SIPDOMAIN ;
	const char* domain="sip:" SIPDOMAIN ;
	belle_sip_header_contact_t* contact=belle_sip_header_contact_new();
478
	belle_sip_uri_t *dest_uri;
479 480
	uint64_t begin;
	uint64_t end;
481
	if (client->expire_in_contact) belle_sip_header_contact_set_expires(contact,1);
482 483
    
    
484
	dest_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_listening_point_get_uri(server->lp));
485 486 487 488
	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");
489
	destination_route=belle_sip_header_route_create(belle_sip_header_address_create(NULL,dest_uri));
jehan's avatar
jehan committed
490 491 492 493


	req=belle_sip_request_create(
		                    belle_sip_uri_parse(domain),
494
		                    method,
jehan's avatar
jehan committed
495
		                    belle_sip_provider_create_call_id(client->provider),
496
		                    belle_sip_header_cseq_create(20,method),
jehan's avatar
jehan committed
497 498 499 500
		                    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
501
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact));
502
	if (!client->expire_in_contact)
jehan's avatar
jehan committed
503 504
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(1)));

jehan's avatar
jehan committed
505
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(destination_route));
506 507 508 509 510 511
	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);
	}
512 513
	if (client->realm
		&&
514
		belle_sip_provider_add_authorization(client->provider, req, NULL, NULL,NULL, client->realm)) {
515 516
		
	}
jehan's avatar
jehan committed
517
	trans=belle_sip_provider_create_client_transaction(client->provider,req);
518
	
jehan's avatar
jehan committed
519
	belle_sip_object_ref(trans);/*to avoid trans from being deleted before refresher can use it*/
jehan's avatar
jehan committed
520
	belle_sip_client_transaction_send_request(trans);
521
	if (client->early_refresher) {
522 523 524
		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
525
	} else {
526
		if (server->auth == none) {
527
			BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
528
		} else {
529 530 531 532 533
			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));
			}
534
			/*update cseq*/
535
			req=belle_sip_client_transaction_create_authenticated_request(trans,NULL,NULL);
536 537 538 539
			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);
540
			BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
541
		}
542
		client->refresher= refresher = belle_sip_client_transaction_create_refresher(trans);       
jehan's avatar
jehan committed
543
	}
544 545 546
	if (BC_ASSERT_PTR_NOT_NULL(refresher)) {
		belle_sip_object_unref(trans);
		belle_sip_refresher_set_listener(refresher,belle_sip_refresher_listener,client);
547
        
548 549 550
		begin = belle_sip_time_ms();
		BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count+(client->early_refresher?1:0),client->register_count*1000 + 1000));
		end = belle_sip_time_ms();
551
		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*/
Simon Morlat's avatar
Simon Morlat committed
552
		BC_ASSERT_LOWER_STRICT(end-begin,(client->register_count*1000 + 2000),unsigned long long,"%llu");
553
	}
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
	return refresher;
}

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);
	/*unregister twice to make sure refresh operation can be safely cascaded*/
	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");
	belle_sip_refresher_stop(refresher);
569
    belle_sip_object_unref(refresher);
570 571
	

572
}
573 574 575
static void refresher_base(endpoint_t* client,endpoint_t *server, const char* method) {
	refresher_base_with_body(client,server,method,NULL,NULL);
}
576 577 578
static void register_base(endpoint_t* client,endpoint_t *server) {
	refresher_base(client,server,"REGISTER");
}
579
static void refresher_base_with_param_and_body_for_ha1(const char* method
580 581 582 583
												, unsigned char expire_in_contact
												, auth_mode_t auth_mode
												, int early_refresher
												, belle_sip_header_content_type_t* content_type
584 585
												,const char* body
                                                ,const char* client_algo
586 587
                                                ,const char* server_algo
                                                ,const char* ha1){
588 589 590 591 592 593 594 595 596 597 598 599
	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;
600 601
    server->algo=server_algo;
    client->algo=client_algo;
602
	client->early_refresher=early_refresher;
603 604 605
    if(ha1){
        client->ha1=ha1;
    }
606
	refresher_base_with_body(client,server,method,content_type,body);
jehan's avatar
jehan committed
607 608
	destroy_endpoint(client);
	destroy_endpoint(server);
jehan's avatar
jehan committed
609
}
610 611 612 613 614 615 616 617 618 619 620 621 622 623

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){
    refresher_base_with_param_and_body_for_ha1(method,expire_in_contact,auth_mode,early_refresher,content_type,body,client_algo,server_algo,NULL);
}

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);
624 625

}
626 627

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) {
628 629 630 631 632
    refresher_base_with_param("REGISTER",expire_in_contact,auth_mode,client_algo,server_algo,NULL);
}

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){
    refresher_base_with_param("REGISTER",expire_in_contact,auth_mode,client_algo,server_algo,ha1);
633 634
}

635
static void register_test_with_param(unsigned char expire_in_contact,auth_mode_t auth_mode) {
636
    register_test_with_param_for_algorithm(expire_in_contact,auth_mode,NULL,NULL);
637
}
638

639 640 641 642 643 644 645 646
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";
647

648 649

static void subscribe_base(int with_resource_lists) {
650 651 652 653 654 655 656
	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 ;
657 658
	endpoint_t* client,*server;
	belle_sip_uri_t *dest_uri;
659
	belle_sip_refresher_t* refresher;
660
	belle_sip_header_contact_t* contact=belle_sip_header_contact_new();
661
	belle_sip_dialog_t * client_dialog;
662
	char *call_id = NULL;
663
	int dummy = 0;
664 665
	uint64_t begin;
	uint64_t end;
666 667 668
	memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
	memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));

669
	client_callbacks.process_dialog_terminated=client_process_dialog_terminated;
670 671 672
	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;
673
	server_callbacks.process_dialog_terminated=server_process_dialog_terminated;
674

675 676
	client = create_udp_endpoint(3452,&client_callbacks);
	server = create_udp_endpoint(6788,&server_callbacks);
677 678
	server->expire_in_contact=0;
	server->auth=digest_auth;
679

680 681 682
	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));
683 684 685 686 687 688 689 690 691 692 693 694 695


	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
696
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_create("Event","Presence")));
697 698

	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(destination_route));
699 700 701 702
	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));
	}
703

704 705 706 707
	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);

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

710
	req=belle_sip_client_transaction_create_authenticated_request(trans,NULL,NULL);
711 712 713 714
	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);
715
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));
716
	 /*maybe dialog should be automatically created*/
717
	BC_ASSERT_PTR_NOT_NULL(client_dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(trans)));
718 719
	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);
720

721
	refresher = belle_sip_client_transaction_create_refresher(trans);
722 723 724
	belle_sip_object_unref(trans);
	belle_sip_refresher_set_listener(refresher,belle_sip_refresher_listener,client);

725
	begin = belle_sip_time_ms();
726
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,3,4000));
727
	end = belle_sip_time_ms();
728
	BC_ASSERT_GREATER((long double)(end-begin),3000*.9,long double,"%Lf");
Simon Morlat's avatar
Simon Morlat committed
729
	BC_ASSERT_LOWER_STRICT(end-begin,5000,unsigned long long,"%llu");
730

jehan's avatar
jehan committed
731
	belle_sip_message("simulating dialog error and recovery");
Simon Morlat's avatar
Simon Morlat committed
732
	belle_sip_stack_set_send_error(client->stack, 1);
jehan's avatar
jehan committed
733
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredEightyOne,1,4000));
Simon Morlat's avatar
Simon Morlat committed
734 735
	/*let the transaction timeout*/
	wait_for(server->stack,client->stack, &dummy, 1, 32000);
736
	belle_sip_stack_set_send_error(client->stack, 0);
Simon Morlat's avatar
Simon Morlat committed
737
	
738

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

742 743
	/*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))));
744 745 746
	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);
747 748 749 750
	
	belle_sip_message("simulating dialog terminated server side and recovery");
	
	client_dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
751 752
	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);
753 754 755 756 757 758 759 760 761 762 763 764 765
	
	belle_sip_provider_enable_unconditional_answer(server->provider,TRUE);
	belle_sip_provider_set_unconditional_answer(server->provider,481);
	belle_sip_refresher_refresh(refresher, 10);
	
	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");
	
	/*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_refresher_refresh(refresher, 0);
	belle_sip_refresher_refresh(refresher, 0);
771

772
	belle_sip_refresher_stop(refresher);
Simon Morlat's avatar
Simon Morlat committed
773 774
	BC_ASSERT_TRUE(wait_for(server->stack,client->stack,&server->stat.dialogTerminated,3,4000));
	
775
	belle_sip_object_unref(refresher);
776

777 778 779
	if (with_resource_lists) {
		BC_ASSERT_EQUAL(server->number_of_body_found, (server->auth == none ?1:2), int, "%i");
	}
780

781
	
782 783 784 785
	destroy_endpoint(client);
	destroy_endpoint(server);
}

786 787 788 789 790 791
static void subscribe_test(void) {
	subscribe_base(FALSE);
}
static void subscribe_list_test(void) {
	subscribe_base(TRUE);
}
792

793
static void register_expires_header(void) {
jehan's avatar
jehan committed
794 795
	register_test_with_param(0,none);
}
Ghislain MARY's avatar
Ghislain MARY committed
796

797
static void register_expires_in_contact(void) {
jehan's avatar
jehan committed
798 799
	register_test_with_param(1,none);
}
Ghislain MARY's avatar
Ghislain MARY committed
800

801
static void register_expires_header_digest(void) {
jehan's avatar
jehan committed
802 803
	register_test_with_param(0,digest);
}
jehan's avatar
jehan committed
804

805
static void register_expires_in_contact_header_digest_auth(void) {
jehan's avatar
jehan committed
806 807
	register_test_with_param(1,digest_auth);
}
808

809 810 811 812 813 814 815 816
static void register_expires_in_contact_header_digest_auth_sha256(void) {
    register_test_with_param_for_algorithm(1,digest_auth,"SHA-256","SHA-256");
}

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

817 818 819 820
static void register_expires_in_contact_header_digest_md_sha_ha1(void) {
    register_test_with_param_for_algorithm_ha1(1,digest_auth,"MD5","MD_SHA","323897f425eb3f4c22efa4119c85b434");
}

821 822 823 824
static void register_expires_in_contact_header_digest_md_sha256(void) {
    register_test_with_param_for_algorithm(1,digest_auth,"SHA-256","MD_SHA");
}

825 826 827 828
static void register_expires_in_contact_header_digest_md_sha256_ha1(void) {
    register_test_with_param_for_algorithm_ha1(1,digest_auth,"SHA-256","MD_SHA","ebf7a06f8211417d6735cd8bfcbecc30ef2045a80d1d6148a6b9d5d3c4f76911");
}

829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
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);
844
	BC_ASSERT_EQUAL(client->stat.refreshKo,1,int,"%d");
845 846 847
	destroy_endpoint(client);
	destroy_endpoint(server);
}
Ghislain MARY's avatar
Ghislain MARY committed
848
static void register_with_unrecognizable_contact(void) {
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
	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);
}
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
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);
}
884

885 886 887 888 889 890 891 892 893 894 895 896
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;
897
	client->register_count=1;
898

899 900 901 902 903 904 905 906 907 908 909 910 911
	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;
}

912 913 914 915 916 917 918 919 920 921 922 923 924
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;
925

926 927 928 929 930 931 932 933 934 935 936 937 938
	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;
}

939
static void register_test_ipv6_to_ipv4(void){
940 941 942 943
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
944 945 946 947
	register_test_with_interfaces("udp","::0","0.0.0.0",AF_INET);
}

static void register_test_ipv4_to_ipv6(void){
948 949 950 951
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
952 953 954 955
	register_test_with_interfaces("udp","0.0.0.0","::0",AF_INET);
}

static void register_test_ipv6_to_ipv6_with_ipv4(void){
956 957 958 959
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
960 961 962 963
	register_test_with_interfaces("udp","::0","::0",AF_INET);
}

static void register_test_ipv6_to_ipv6_with_ipv6(void){
964 965 966 967
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
968 969 970
	register_test_with_interfaces("udp","::0","::0",AF_INET6);
}

971
static void register_tcp_test_ipv6_to_ipv4(void){
972 973 974 975
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
976 977 978 979
	register_test_with_interfaces("tcp","::0","0.0.0.0",AF_INET);
}

static void register_tcp_test_ipv4_to_ipv6(void){
980 981 982 983
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
984 985 986 987
	register_test_with_interfaces("tcp","0.0.0.0","::0",AF_INET);
}

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

static void register_tcp_test_ipv6_to_ipv6_with_ipv6(void){
996 997 998 999
	if (!belle_sip_tester_ipv6_available()){
		belle_sip_warning("Test skipped, IPv6 connectivity not available.");
		return;
	}
1000 1001 1002
	register_test_with_interfaces("tcp","::0","::0",AF_INET6);
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
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);
}

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
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);
}

1027
static void simple_publish(void) {
1028
	belle_sip_header_content_type_t* content_type=belle_sip_header_content_type_create("application","pidf+xml");
1029
	refresher_base_with_param_and_body("PUBLISH",FALSE,TRUE,FALSE, content_type,publish_body,"MD5","MD5");
1030 1031

}
1032
static void simple_publish_with_early_refresher(void) {
1033
	belle_sip_header_content_type_t* content_type=belle_sip_header_content_type_create("application","pidf+xml");
1034
	refresher_base_with_param_and_body("PUBLISH",FALSE,TRUE,TRUE, content_type,publish_body,"MD5","MD5");
1035

1036
}
1037

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
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");
	
	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);
	
	client->register_count = 2 * client->register_count;
	client->stat.refreshOk = 0;
	/*to make sure we can still use same nonce*/
	client->nonce_count -=2;
	
	publish_refresher = refresher_base_with_body2(client,server,"PUBLISH",content_type,publish_body,2);
	
	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);
	
	
	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);
	
	destroy_endpoint(client);
	destroy_endpoint(server);
}

jehan's avatar
jehan committed
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
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
1111
test_t refresher_tests[] = {
1112 1113 1114 1115
	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),
1116 1117
    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),
1118
    TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA ha1", register_expires_in_contact_header_digest_md_sha_ha1),
1119
    TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA-256", register_expires_in_contact_header_digest_md_sha256),
1120
    TEST_NO_TAG("REGISTER Expires in Contact digest auth MD_SHA-256 ha1", register_expires_in_contact_header_digest_md_sha256_ha1),
1121 1122
	TEST_NO_TAG("REGISTER with failure", register_with_failure),
	TEST_NO_TAG("REGISTER with early refresher",register_early_refresher),
Simon Morlat's avatar
Simon Morlat committed
1123
	TEST_NO_TAG("SUBSCRIBE", subscribe_test),
Simon Morlat's avatar
Simon Morlat committed
1124
	TEST_NO_TAG("SUBSCRIBE of list" , subscribe_list_test),
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
	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),
1140
	TEST_NO_TAG("REGISTER AND PUBLISH", register_and_publish),
jehan's avatar
jehan committed
1141 1142 1143
	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)
1144
	
Ghislain MARY's avatar
Ghislain MARY committed
1145 1146
};

1147 1148
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};