sal_op_events.c 12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
linphone
Copyright (C) 2012  Belledonne Communications, Grenoble, France

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 the Free Software Foundation; either version 2
of the License, or (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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "sal_impl.h"

SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){
	belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t);
	SalSubscribeStatus sss=SalSubscribeNone;
	if (subscription_state_header){
		if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0)
			sss=SalSubscribeTerminated;
		else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0)
			sss=SalSubscribePending;
		else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0)
			sss=SalSubscribeActive;
	}
	return sss;
}

35 36 37 38 39 40 41 42
static void subscribe_refresher_listener (belle_sip_refresher_t* refresher
		,void* user_pointer
		,unsigned int status_code
		,const char* reason_phrase) {
	SalOp* op = (SalOp*)user_pointer;
	belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher));
	/*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/
	SalSubscribeStatus sss=SalSubscribeTerminated;
43
	
44 45 46 47 48
	ms_message("Subscribe refresher  [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none");
	if (status_code>=200 && status_code<300){
		if (status_code==200) sss=SalSubscribeActive;
		else if (status_code==202) sss=SalSubscribePending;
		set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr));
49
	}
50
	if (status_code>=200){
51 52
		sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
		op->base.root->callbacks.subscribe_response(op,sss);
53 54
	}else if (status_code==0){
		op->base.root->callbacks.on_expire(op);
55
	}
56 57 58 59 60 61 62 63 64 65 66 67
	
}

static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
	ms_error("subscribe_process_io_error not implemented yet");
}

static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
	SalOp* op= (SalOp*)ctx;
	if (op->dialog) {
		op->dialog=NULL;
		sal_op_unref(op);
68 69 70
	}
}

71 72 73
static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){
}

74 75 76 77 78 79
static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
}

static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
}

80
static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){
81 82 83 84 85 86 87 88 89 90
	SalSubscribeStatus sub_state;
	belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
	belle_sip_response_t* resp;
	belle_sip_server_transaction_t* server_transaction = op->pending_server_trans;
	
	if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
		sub_state=SalSubscribeTerminated;
		ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
	} else
		sub_state=SalSubscribeActive;
91
	sal_op_ref(op);
92
	op->base.root->callbacks.notify(op,sub_state,eventname,body_handler);
93 94
	resp=sal_op_create_response_from_request(op,req,200);
	belle_sip_server_transaction_send_response(server_transaction,resp);
95
	sal_op_unref(op);
96 97
}

98 99 100 101 102 103 104
static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
	SalOp* op = (SalOp*)op_base;
	belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_state_t dialog_state;
	belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
	belle_sip_header_t *event_header;
105
	belle_sip_body_handler_t *body_handler;
106 107
	belle_sip_response_t* resp;
	const char *eventname=NULL;
108
	const char *method=belle_sip_request_get_method(req);
109 110 111 112 113 114
	
	belle_sip_object_ref(server_transaction);
	if (op->pending_server_trans)  belle_sip_object_unref(op->pending_server_trans);
	op->pending_server_trans=server_transaction;

	event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event");
115
	body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req)));
116
	
117
	if (event_header==NULL){
118 119 120 121 122
		ms_warning("No event header in incoming SUBSCRIBE.");
		resp=sal_op_create_response_from_request(op,req,400);
		belle_sip_server_transaction_send_response(server_transaction,resp);
		return;
	}
123 124 125 126 127
	if (op->event==NULL) {
		op->event=event_header;
		belle_sip_object_ref(op->event);
	}
	eventname=belle_sip_header_get_unparsed_value(event_header);
128 129
	
	if (!op->dialog) {
130 131
		if (strcmp(method,"SUBSCRIBE")==0){
			op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
132
			belle_sip_dialog_set_application_data(op->dialog, sal_op_ref(op));
133 134
			ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
		}else{ /*this is a NOTIFY*/
135
			handle_notify(op, req, eventname, (SalBodyHandler *)body_handler);
136 137
			return;
		}
138 139 140 141 142
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);
	switch(dialog_state) {

	case BELLE_SIP_DIALOG_NULL: {
143 144 145 146
		const char *type = NULL;
		belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t);
		if (content_type) type = belle_sip_header_content_type_get_type(content_type);
		op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL);
147 148 149 150 151 152 153
		break;
	}
	case BELLE_SIP_DIALOG_EARLY:
		ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog);
		break;

	case BELLE_SIP_DIALOG_CONFIRMED:
154
		if (strcmp("NOTIFY",method)==0) {
155
			handle_notify(op, req, eventname, (SalBodyHandler *)body_handler);
156
		} else if (strcmp("SUBSCRIBE",method)==0) {
157 158
			/*either a refresh of an unsubscribe*/
			if (expires && belle_sip_header_expires_get_expires(expires)>0) {
159 160
				resp=sal_op_create_response_from_request(op,req,200);
				belle_sip_server_transaction_send_response(server_transaction,resp);
161 162 163 164 165 166 167 168 169 170 171 172 173 174
			} else if(expires) {
				ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
				resp=sal_op_create_response_from_request(op,req,200);
				belle_sip_server_transaction_send_response(server_transaction,resp);
				op->base.root->callbacks.subscribe_closed(op);
			}
		}
		break;
		default: {
			ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
		}
	}
}

175 176
static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 };

177
void sal_op_subscribe_fill_cbs(SalOp*op) {
178 179 180 181 182 183 184 185 186
	if (op_subscribe_callbacks.process_io_error==NULL){
		op_subscribe_callbacks.process_io_error=subscribe_process_io_error;
		op_subscribe_callbacks.process_response_event=subscribe_response_event;
		op_subscribe_callbacks.process_timeout=subscribe_process_timeout;
		op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated;
		op_subscribe_callbacks.process_request_event=subscribe_process_request_event;
		op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated;
	}
	op->callbacks=&op_subscribe_callbacks;
187 188 189 190
	op->type=SalOpSubscribe;
}


191
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){
192 193 194 195 196 197 198 199 200 201 202
	belle_sip_request_t *req=NULL;
	
	if (from)
		sal_op_set_from(op,from);
	if (to)
		sal_op_set_to(op,to);
	
	if (!op->dialog){
		sal_op_subscribe_fill_cbs(op);
		/*???sal_exosip_fix_route(op); make sure to ha ;lr*/
		req=sal_op_build_request(op,"SUBSCRIBE");
203 204 205
		if( req == NULL ) {
			return -1;
		}
206 207 208 209 210 211
		if (eventname){
			if (op->event) belle_sip_object_unref(op->event);
			op->event=belle_sip_header_create("Event",eventname);
			belle_sip_object_ref(op->event);
		}
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
212
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
213
		belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler));
214 215 216 217 218
		return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener);
	}else if (op->refresher){
		const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
		/* modify last request to update body*/
219
		belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler));
220
		return belle_sip_refresher_refresh(op->refresher,expires);
221
	}
222 223
	ms_warning("sal_subscribe(): no dialog and no refresher ?");
	return -1;
224 225
}

226 227 228 229 230 231 232 233 234
int sal_subscribe_refresh(SalOp *op) {
	if (op->refresher) {
		belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher));
		return 0;
	}
	ms_warning("sal_refresh_subscribe(): no refresher");
	return -1;
}

235
int sal_unsubscribe(SalOp *op){
236 237 238
	if (op->refresher){
		const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
239
		belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0);
240 241
		belle_sip_refresher_refresh(op->refresher,0);
		return 0;
242
	}
243
	return -1;
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
}

int sal_subscribe_accept(SalOp *op){
	belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
	belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
	belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires));
	belle_sip_server_transaction_send_response(op->pending_server_trans,resp);
	return 0;
}

int sal_subscribe_decline(SalOp *op, SalReason reason){
	belle_sip_response_t*  resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),
									   sal_reason_to_sip_code(reason));
	belle_sip_server_transaction_send_response(op->pending_server_trans,resp);
	return 0;
}

262
int sal_notify(SalOp *op, const SalBodyHandler *body_handler){
263 264 265 266
	belle_sip_request_t* notify;
	
	if (!op->dialog) return -1;
	
267
	if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
268

269
	if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
270 271 272

	belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
			,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
273
	belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler));
274 275 276 277 278 279
	return sal_op_send_request(op,notify);
}

int sal_notify_close(SalOp *op){
	belle_sip_request_t* notify;
	if (!op->dialog) return -1;
280
	if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
281
	if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
282 283 284 285 286
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
		,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1)));
	return sal_op_send_request(op,notify);
}