Revision 1d54077e plugins/janus_sip.c

View differences:

plugins/janus_sip.c
30 30
 * as events with the same transaction.
31 31
 *
32 32
 * The supported requests are \c register , \c unregister , \c call ,
33
 * \c accept, \c hold , \c unhold and \c hangup . \c register can be used,
33
 * \c accept, \c info , \c message , \c dtmf_info , \c recording ,
34
 * \c hold , \c unhold and \c hangup . \c register can be used,
34 35
 * as the name suggests, to register a username at a SIP registrar to
35 36
 * call and be called, while \c unregister unregisters it; \c call is used
36 37
 * to send an INVITE to a different SIP URI through the plugin, while
37 38
 * \c accept is used to accept the call in case one is invited instead
38 39
 * of inviting; \c hold and \c unhold can be used respectively to put a
39
 * call on-hold and to resume it; finally, \c hangup can be used to terminate the
40
 * call on-hold and to resume it; \c info allows you to send a generic
41
 * SIP INFO request, while \c dtmf_info is focused on using INFO for DTMF
42
 * instead; \c message is the method you use to send a SIP message
43
 * to the other peer; \c recording is used, instead, to record the
44
 * conversation to one or more .mjr files (depending on the direction you
45
 * want to record); finally, \c hangup can be used to terminate the
40 46
 * communication at any time, either to hangup (BYE) an ongoing call or
41 47
 * to cancel/decline (CANCEL/BYE) a call that hasn't started yet.
42 48
 *
......
171 177
	{"digit", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
172 178
	{"duration", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}
173 179
};
180
static struct janus_json_parameter info_parameters[] = {
181
	{"type", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
182
	{"content", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
183
};
184
static struct janus_json_parameter sipmessage_parameters[] = {
185
	{"content", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
186
};
174 187

  
175 188
/* Useful stuff */
176 189
static volatile gint initialized = 0, stopping = 0;
......
2402 2415
			/* Notify the result */
2403 2416
			result = json_object();
2404 2417
			json_object_set_new(result, "event", json_string("recordingupdated"));
2418
		} else if(!strcasecmp(request_text, "info")) {
2419
			/* Send a SIP INFO request: we'll need the payload type and content */
2420
			if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2421
				JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2422
				g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2423
				goto error;
2424
			}
2425
			if(session->callee == NULL) {
2426
				JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2427
				error_code = JANUS_SIP_ERROR_WRONG_STATE;
2428
				g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2429
				goto error;
2430
			}
2431
			JANUS_VALIDATE_JSON_OBJECT(root, info_parameters,
2432
				error_code, error_cause, TRUE,
2433
				JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2434
			if(error_code != 0)
2435
				goto error;
2436
			const char *info_type = json_string_value(json_object_get(root, "type"));
2437
			const char *info_content = json_string_value(json_object_get(root, "content"));
2438
			nua_info(session->stack->s_nh_i,
2439
				SIPTAG_CONTENT_TYPE_STR(info_type),
2440
				SIPTAG_PAYLOAD_STR(info_content),
2441
				TAG_END());
2442
			/* Notify the operation */
2443
			result = json_object();
2444
			json_object_set_new(result, "event", json_string("infosent"));
2445
		} else if(!strcasecmp(request_text, "message")) {
2446
			/* Send a SIP MESSAGE request: we'll only need the content */
2447
			if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2448
				JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2449
				g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2450
				goto error;
2451
			}
2452
			if(session->callee == NULL) {
2453
				JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2454
				error_code = JANUS_SIP_ERROR_WRONG_STATE;
2455
				g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2456
				goto error;
2457
			}
2458
			JANUS_VALIDATE_JSON_OBJECT(root, sipmessage_parameters,
2459
				error_code, error_cause, TRUE,
2460
				JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2461
			if(error_code != 0)
2462
				goto error;
2463
			const char *msg_content = json_string_value(json_object_get(root, "content"));
2464
			nua_message(session->stack->s_nh_i,
2465
				NUTAG_URL(session->callee),
2466
				SIPTAG_PAYLOAD_STR(msg_content),
2467
				TAG_END());
2468
			/* Notify the operation */
2469
			result = json_object();
2470
			json_object_set_new(result, "event", json_string("messagesent"));
2405 2471
		} else if(!strcasecmp(request_text, "dtmf_info")) {
2406 2472
			/* Send DMTF tones using SIP INFO
2407 2473
			 * (https://tools.ietf.org/html/draft-kaplan-dispatch-info-dtmf-package-00)
......
2738 2804
			session->stack->s_nh_i = nh;
2739 2805
			break;
2740 2806
		}
2807
		case nua_i_info: {
2808
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2809
			/* We expect a payload */
2810
			if(!sip->sip_content_type || !sip->sip_content_type->c_type || !sip->sip_payload || !sip->sip_payload->pl_data) {
2811
				nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2812
				return;
2813
			}
2814
			const char *type = sip->sip_content_type->c_type;
2815
			char *payload = sip->sip_payload->pl_data;
2816
			/* Notify the application */
2817
			json_t *info = json_object();
2818
			json_object_set_new(info, "sip", json_string("event"));
2819
			json_t *result = json_object();
2820
			json_object_set_new(result, "event", json_string("info"));
2821
			char *caller_text = url_as_string(session->stack->s_home, sip->sip_from->a_url);
2822
			json_object_set_new(result, "sender", json_string(caller_text));
2823
			su_free(session->stack->s_home, caller_text);
2824
			if(sip->sip_from && sip->sip_from->a_display && strlen(sip->sip_from->a_display) > 0) {
2825
				json_object_set_new(result, "displayname", json_string(sip->sip_from->a_display));
2826
			}
2827
			json_object_set_new(result, "type", json_string(type));
2828
			json_object_set_new(result, "content", json_string(payload));
2829
			json_object_set_new(info, "result", result);
2830
			int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, info, NULL);
2831
			JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2832
			json_decref(info);
2833
			/* Send a 200 back */
2834
			nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2835
			break;
2836
		}
2837
		case nua_i_message: {
2838
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2839
			/* We expect a payload */
2840
			if(!sip->sip_payload || !sip->sip_payload->pl_data) {
2841
				nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2842
				return;
2843
			}
2844
			char *payload = sip->sip_payload->pl_data;
2845
			/* Notify the application */
2846
			json_t *message = json_object();
2847
			json_object_set_new(message, "sip", json_string("event"));
2848
			json_t *result = json_object();
2849
			json_object_set_new(result, "event", json_string("message"));
2850
			char *caller_text = url_as_string(session->stack->s_home, sip->sip_from->a_url);
2851
			json_object_set_new(result, "sender", json_string(caller_text));
2852
			su_free(session->stack->s_home, caller_text);
2853
			if(sip->sip_from && sip->sip_from->a_display && strlen(sip->sip_from->a_display) > 0) {
2854
				json_object_set_new(result, "displayname", json_string(sip->sip_from->a_display));
2855
			}
2856
			json_object_set_new(result, "content", json_string(payload));
2857
			json_object_set_new(message, "result", result);
2858
			int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, message, NULL);
2859
			JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2860
			json_decref(message);
2861
			/* Send a 200 back */
2862
			nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2863
			break;
2864
		}
2741 2865
		case nua_i_options:
2742 2866
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2743 2867
			/* FIXME Should we handle this message? for now we reply with a 405 Method Not Implemented */
......
2776 2900
			break;
2777 2901
		case nua_r_info:
2778 2902
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2903
			/* FIXME Should we notify the user, in case the SIP INFO returned an error? */
2904
			break;
2905
		case nua_r_message:
2906
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2907
			/* FIXME Should we notify the user, in case the SIP MESSAGE returned an error? */
2779 2908
			break;
2780 2909
		case nua_r_invite: {
2781 2910
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
......
3695 3824
	session->stack->s_nua = nua_create(session->stack->s_root,
3696 3825
				janus_sip_sofia_callback,
3697 3826
				session,
3698
				SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE"),
3827
				SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE, MESSAGE, INFO"),
3699 3828
				NUTAG_M_USERNAME(session->account.username),
3700 3829
				NUTAG_URL(sip_url),
3701 3830
				TAG_IF(session->account.sips, NUTAG_SIPS_URL(sips_url)),

Also available in: Unified diff