Revision d4f87512

View differences:

html/siptest.html
12 12
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.1.0/bootbox.min.js"></script>
13 13
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js"></script>
14 14
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.6.0/js/md5.min.js"></script>
15
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>
15 16
<script type="text/javascript" src="janus.js" ></script>
16 17
<script type="text/javascript" src="siptest.js"></script>
17 18
<script>
......
26 27
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/cerulean/bootstrap.min.css" type="text/css"/>
27 28
<link rel="stylesheet" href="css/demo.css" type="text/css"/>
28 29
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.2/css/font-awesome.min.css" type="text/css"/>
30
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.css"/>
29 31
</head>
30 32
<body>
31 33

  
html/siptest.js
288 288
													}
289 289
												}
290 290
											});											
291
										} else if(event === 'accepting') {
292
											// Response to an offerless INVITE, let's wait for an 'accepted'
293
										} else if(event === 'progress') {
294
											Janus.log("There's early media from " + result["username"] + ", wairing for the call!");
295
											Janus.log(jsep);
296
											// Call can start already: handle the remote answer
297
											if(jsep !== null && jsep !== undefined) {
298
												sipcall.handleRemoteJsep({jsep: jsep, error: doHangup });
299
											}
300
											toastr.info("Early media...");
291 301
										} else if(event === 'accepted') {
292 302
											Janus.log(result["username"] + " accepted the call!");
293 303
											Janus.log(jsep);
......
295 305
											if(jsep !== null && jsep !== undefined) {
296 306
												sipcall.handleRemoteJsep({jsep: jsep, error: doHangup });
297 307
											}
308
											toastr.success("Call accepted!");
298 309
										} else if(event === 'hangup') {
299 310
											if(incoming != null) {
300 311
												incoming.modal('hide');
plugins/janus_sip.c
311 311

  
312 312
typedef struct janus_sip_media {
313 313
	char *remote_ip;
314
	gboolean earlymedia;
314 315
	gboolean ready;
315 316
	gboolean autoack;
316 317
	gboolean require_srtp, has_srtp_local, has_srtp_remote;
......
973 974
	session->callid = NULL;
974 975
	session->sdp = NULL;
975 976
	session->media.remote_ip = NULL;
977
	session->media.earlymedia = FALSE;
976 978
	session->media.ready = FALSE;
977 979
	session->media.autoack = TRUE;
978 980
	session->media.require_srtp = FALSE;
......
2026 2028
			/* Also notify event handlers */
2027 2029
			if(notify_events && gateway->events_is_enabled()) {
2028 2030
				json_t *info = json_object();
2029
				json_object_set_new(info, "event", json_string("accepted"));
2031
				json_object_set_new(info, "event", json_string(answer ? "accepted" : "accepting"));
2030 2032
				if(session->callid)
2031 2033
					json_object_set_new(info, "call-id", json_string(session->callid));
2032 2034
				gateway->notify_event(&janus_sip_plugin, session->handle, info);
......
2050 2052
			g_free(sdp);
2051 2053
			/* Send an ack back */
2052 2054
			result = json_object();
2053
			json_object_set_new(result, "event", json_string("accepted"));
2055
			json_object_set_new(result, "event", json_string(answer ? "accepted" : "accepting"));
2054 2056
			if(answer) {
2055 2057
				/* Start the media */
2056 2058
				session->media.ready = TRUE;	/* FIXME Maybe we need a better way to signal this */
......
2078 2080
				g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2079 2081
				goto error;
2080 2082
			}
2083
			session->media.earlymedia = FALSE;
2081 2084
			session->media.ready = FALSE;
2082 2085
			session->media.on_hold = FALSE;
2083 2086
			session->status = janus_sip_call_status_closing;
......
2200 2203
				g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2201 2204
				goto error;
2202 2205
			}
2206
			session->media.earlymedia = FALSE;
2203 2207
			session->media.ready = FALSE;
2204 2208
			session->media.on_hold = FALSE;
2205 2209
			session->status = janus_sip_call_status_closing;
......
2615 2619
				}
2616 2620
			} else if(callstate == nua_callstate_terminated &&
2617 2621
					(session->stack->s_nh_i == nh || session->stack->s_nh_i == NULL)) {
2622
				session->media.earlymedia = FALSE;
2618 2623
				session->media.ready = FALSE;
2619 2624
				session->media.on_hold = FALSE;
2620 2625
				session->status = janus_sip_call_status_idle;
......
2909 2914
		case nua_r_invite: {
2910 2915
			JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2911 2916

  
2917
			gboolean in_progress = FALSE;
2912 2918
			if(status < 200) {
2913
				/* Not ready yet (FIXME May this be pranswer?? we don't handle it yet...) */
2914
				break;
2919
				/* Not ready yet, either notify the user (e.g., "ringing") or handle early media (if it's a 183) */
2920
				if(status == 180) {
2921
					/* Ringing, notify the application */
2922
					json_t *ringing = json_object();
2923
					json_object_set_new(ringing, "sip", json_string("event"));
2924
					json_t *result = json_object();
2925
					json_object_set_new(result, "event", json_string("ringing"));
2926
					json_object_set_new(ringing, "result", result);
2927
					int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, ringing, NULL);
2928
					JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2929
					json_decref(ringing);
2930
					break;
2931
				} else if(status == 183) {
2932
					/* If's a Session Progress: check if there's an SDP, and if so, treat it like a 200 */
2933
					if(!sip->sip_payload->pl_data)
2934
						break;
2935
					in_progress = TRUE;
2936
				} else {
2937
					/* Nothing to do, let's wait for a 200 OK */
2938
					break;
2939
				}
2915 2940
			} else if(status == 401 || status == 407) {
2916 2941
				char auth[256];
2917 2942
				const char* scheme;
......
2959 2984
				break;
2960 2985
			}
2961 2986
			/* Send an ACK, if needed */
2962
			if(!session->media.autoack) {
2987
			if(!in_progress && !session->media.autoack) {
2963 2988
				char *route = sip->sip_record_route ? url_as_string(session->stack->s_home, sip->sip_record_route->r_url) : NULL;
2964 2989
				JANUS_LOG(LOG_INFO, "Sending ACK (route=%s)\n", route ? route : "none");
2965 2990
				nua_ack(nh,
......
2978 3003
				JANUS_LOG(LOG_ERR, "\tWe asked for mandatory SRTP but didn't get any in the reply!\n");
2979 3004
				janus_sdp_free(sdp);
2980 3005
				/* Hangup immediately */
3006
				session->media.earlymedia = FALSE;
2981 3007
				session->media.ready = FALSE;
2982 3008
				session->media.on_hold = FALSE;
2983 3009
				session->status = janus_sip_call_status_closing;
......
2991 3017
				JANUS_LOG(LOG_ERR, "\tNo remote IP address found for RTP, something's wrong with the SDP!\n");
2992 3018
				janus_sdp_free(sdp);
2993 3019
				/* Hangup immediately */
3020
				session->media.earlymedia = FALSE;
2994 3021
				session->media.ready = FALSE;
2995 3022
				session->media.on_hold = FALSE;
2996 3023
				session->status = janus_sip_call_status_closing;
......
3008 3035
				JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
3009 3036
			}
3010 3037
			session->media.ready = TRUE;	/* FIXME Maybe we need a better way to signal this */
3011
			if(update) {
3038
			if(update && !session->media.earlymedia) {
3012 3039
				/* Don't push to the browser if this is in response to a hold/unhold we sent ourselves */
3013 3040
				JANUS_LOG(LOG_VERB, "This is an update to an existing call (possibly in response to hold/unhold)\n");
3014 3041
				break;
3015 3042
			}
3016
			GError *error = NULL;
3017
			char tname[16];
3018
			g_snprintf(tname, sizeof(tname), "siprtp %s", session->account.username);
3019
			g_thread_try_new(tname, janus_sip_relay_thread, session, &error);
3020
			if(error != NULL) {
3021
				JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
3043
			if(!session->media.earlymedia) {
3044
				GError *error = NULL;
3045
				char tname[16];
3046
				g_snprintf(tname, sizeof(tname), "siprtp %s", session->account.username);
3047
				g_thread_try_new(tname, janus_sip_relay_thread, session, &error);
3048
				if(error != NULL) {
3049
					JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
3050
				}
3051
			}
3052
			/* Send event back to the browser */
3053
			json_t *jsep = NULL;
3054
			if(!session->media.earlymedia) {
3055
				jsep = json_pack("{ssss}", "type", "answer", "sdp", fixed_sdp);
3056
			} else {
3057
				/* We've received the 200 OK after the 183, we can remove the flag now */
3058
				session->media.earlymedia = FALSE;
3059
			}
3060
			if(in_progress) {
3061
				/* If we just received the 183, set the flag instead so that we can handle the 200 OK differently */
3062
				session->media.earlymedia = TRUE;
3022 3063
			}
3023
			/* Send SDP to the browser */
3024
			json_t *jsep = json_pack("{ssss}", "type", "answer", "sdp", fixed_sdp);
3025 3064
			json_t *call = json_object();
3026 3065
			json_object_set_new(call, "sip", json_string("event"));
3027 3066
			json_t *calling = json_object();
3028
			json_object_set_new(calling, "event", json_string("accepted"));
3067
			json_object_set_new(calling, "event", json_string(in_progress ? "progress" : "accepted"));
3029 3068
			json_object_set_new(calling, "username", json_string(session->callee));
3030 3069
			json_object_set_new(call, "result", calling);
3031 3070
			int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call, jsep);
......
3036 3075
			/* Also notify event handlers */
3037 3076
			if(notify_events && gateway->events_is_enabled()) {
3038 3077
				json_t *info = json_object();
3039
				json_object_set_new(info, "event", json_string("accepted"));
3078
				json_object_set_new(info, "event", json_string(in_progress ? "progress" : "accepted"));
3040 3079
				if(session->callid)
3041 3080
					json_object_set_new(info, "call-id", json_string(session->callid));
3042 3081
				json_object_set_new(info, "username", json_string(session->callee));

Also available in: Unified diff