Revision 1d54077e plugins/janus_sip.c
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