1253 |
1253 |
video ? "video" : "audio",
|
1254 |
1254 |
video ? session->media.video_ssrc : session->media.audio_ssrc);
|
1255 |
1255 |
}
|
1256 |
|
if((video && session->media.has_video && session->media.video_rtp_fd) ||
|
1257 |
|
(!video && session->media.has_audio && session->media.audio_rtp_fd)) {
|
|
1256 |
if((video && session->media.has_video && session->media.video_rtp_fd != -1) ||
|
|
1257 |
(!video && session->media.has_audio && session->media.audio_rtp_fd != -1)) {
|
1258 |
1258 |
/* Save the frame if we're recording */
|
1259 |
1259 |
janus_recorder_save_frame(video ? session->vrc : session->arc, buf, len);
|
1260 |
1260 |
/* Is SRTP involved? */
|
... | ... | |
1294 |
1294 |
return;
|
1295 |
1295 |
}
|
1296 |
1296 |
/* Forward to our SIPre peer */
|
1297 |
|
if((video && session->media.has_video && session->media.video_rtcp_fd) ||
|
1298 |
|
(!video && session->media.has_audio && session->media.audio_rtcp_fd)) {
|
|
1297 |
if((video && session->media.has_video && session->media.video_rtcp_fd != -1) ||
|
|
1298 |
(!video && session->media.has_audio && session->media.audio_rtcp_fd != -1)) {
|
1299 |
1299 |
/* Fix SSRCs as the gateway does */
|
1300 |
1300 |
JANUS_LOG(LOG_HUGE, "[SIPre-%s] Fixing %s SSRCs (local %u, peer %u)\n",
|
1301 |
1301 |
session->account.username ? session->account.username : "unknown",
|
... | ... | |
1965 |
1965 |
}
|
1966 |
1966 |
/* Accept a call from another peer */
|
1967 |
1967 |
JANUS_LOG(LOG_VERB, "We're accepting the call from %s\n", session->callee);
|
|
1968 |
gboolean answer = !strcasecmp(msg_sdp_type, "answer");
|
|
1969 |
if(!answer) {
|
|
1970 |
JANUS_LOG(LOG_VERB, "This is a response to an offerless INVITE\n");
|
|
1971 |
}
|
1968 |
1972 |
JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg_sdp_type, msg_sdp);
|
1969 |
1973 |
session->media.has_srtp_local = answer_srtp;
|
1970 |
1974 |
if(answer_srtp) {
|
... | ... | |
2018 |
2022 |
/* Also notify event handlers */
|
2019 |
2023 |
if(notify_events && gateway->events_is_enabled()) {
|
2020 |
2024 |
json_t *info = json_object();
|
2021 |
|
json_object_set_new(info, "event", json_string("accepted"));
|
|
2025 |
json_object_set_new(info, "event", json_string(answer ? "accepted" : "accepting"));
|
2022 |
2026 |
if(session->callid)
|
2023 |
2027 |
json_object_set_new(info, "call-id", json_string(session->callid));
|
2024 |
2028 |
gateway->notify_event(&janus_sipre_plugin, session->handle, info);
|
2025 |
2029 |
}
|
2026 |
2030 |
/* Enqueue the 200 OK */
|
|
2031 |
if(!answer) {
|
|
2032 |
if(session->transaction)
|
|
2033 |
g_free(session->transaction);
|
|
2034 |
session->transaction = msg->transaction ? g_strdup(msg->transaction) : NULL;
|
|
2035 |
}
|
2027 |
2036 |
g_atomic_int_set(&session->hangingup, 0);
|
2028 |
2037 |
session->status = janus_sipre_call_status_incall;
|
2029 |
2038 |
session->temp_sdp = sdp;
|
2030 |
2039 |
mqueue_push(mq, janus_sipre_mqueue_event_do_accept, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
|
2031 |
2040 |
/* Send an ack back */
|
2032 |
2041 |
result = json_object();
|
2033 |
|
json_object_set_new(result, "event", json_string("accepted"));
|
2034 |
|
/* Start the media */
|
2035 |
|
session->media.ready = TRUE; /* FIXME Maybe we need a better way to signal this */
|
2036 |
|
GError *error = NULL;
|
2037 |
|
char tname[16];
|
2038 |
|
g_snprintf(tname, sizeof(tname), "siprertp %s", session->account.username);
|
2039 |
|
g_thread_try_new(tname, janus_sipre_relay_thread, session, &error);
|
2040 |
|
if(error != NULL) {
|
2041 |
|
JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
|
|
2042 |
json_object_set_new(result, "event", json_string(answer ? "accepted" : "accepting"));
|
|
2043 |
if(answer) {
|
|
2044 |
/* Start the media */
|
|
2045 |
session->media.ready = TRUE; /* FIXME Maybe we need a better way to signal this */
|
|
2046 |
GError *error = NULL;
|
|
2047 |
char tname[16];
|
|
2048 |
g_snprintf(tname, sizeof(tname), "siprertp %s", session->account.username);
|
|
2049 |
g_thread_try_new(tname, janus_sipre_relay_thread, session, &error);
|
|
2050 |
if(error != NULL) {
|
|
2051 |
JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
|
|
2052 |
}
|
2042 |
2053 |
}
|
2043 |
2054 |
} else if(!strcasecmp(request_text, "decline")) {
|
2044 |
2055 |
/* Reject an incoming call */
|
... | ... | |
2927 |
2938 |
int i = 0;
|
2928 |
2939 |
for(i=0; i<num; i++) {
|
2929 |
2940 |
if(fds[i].revents & (POLLERR | POLLHUP)) {
|
2930 |
|
/* Socket error? */
|
2931 |
|
JANUS_LOG(LOG_ERR, "[SIPre-%s] Error polling: %s...\n", session->account.username,
|
2932 |
|
fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
|
2933 |
|
JANUS_LOG(LOG_ERR, "[SIPre-%s] -- %d (%s)\n", session->account.username, errno, strerror(errno));
|
|
2941 |
/* If we just updated the session, let's wait until things have calmed down */
|
2934 |
2942 |
if(session->media.updated)
|
2935 |
2943 |
break;
|
2936 |
|
goon = FALSE; /* Can we assume it's pretty much over, after a POLLERR? */
|
|
2944 |
/* Check the socket error */
|
|
2945 |
int error = 0;
|
|
2946 |
socklen_t errlen = sizeof(error);
|
|
2947 |
getsockopt(fds[i].fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
|
|
2948 |
if(error == 0) {
|
|
2949 |
/* Maybe not a breaking error after all? */
|
|
2950 |
continue;
|
|
2951 |
} else if(error == 111) {
|
|
2952 |
/* ICMP error? If it's related to RTCP, let's just close the RTCP socket and move on */
|
|
2953 |
if(fds[i].fd == session->media.audio_rtcp_fd) {
|
|
2954 |
JANUS_LOG(LOG_WARN, "[SIPre-%s] Got a '%s' on the audio RTCP socket, closing it\n",
|
|
2955 |
session->account.username, strerror(error));
|
|
2956 |
close(session->media.audio_rtcp_fd);
|
|
2957 |
session->media.audio_rtcp_fd = -1;
|
|
2958 |
} else if(fds[i].fd == session->media.video_rtcp_fd) {
|
|
2959 |
JANUS_LOG(LOG_WARN, "[SIPre-%s] Got a '%s' on the video RTCP socket, closing it\n",
|
|
2960 |
session->account.username, strerror(error));
|
|
2961 |
close(session->media.video_rtcp_fd);
|
|
2962 |
session->media.video_rtcp_fd = -1;
|
|
2963 |
}
|
|
2964 |
/* FIXME Should we do the same with the RTP sockets as well? We may risk overreacting, there... */
|
|
2965 |
continue;
|
|
2966 |
}
|
|
2967 |
JANUS_LOG(LOG_ERR, "[SIPre-%s] Error polling %d (socket #%d): %s...\n", session->account.username,
|
|
2968 |
fds[i].fd, i, fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
|
|
2969 |
JANUS_LOG(LOG_ERR, "[SIPre-%s] -- %d (%s)\n", session->account.username, error, strerror(error));
|
|
2970 |
/* Can we assume it's pretty much over, after a POLLERR? */
|
|
2971 |
goon = FALSE;
|
2937 |
2972 |
/* FIXME Simulate a "hangup" coming from the browser */
|
2938 |
2973 |
janus_sipre_message *msg = g_malloc0(sizeof(janus_sipre_message));
|
2939 |
2974 |
msg->handle = session->handle;
|
... | ... | |
3263 |
3298 |
}
|
3264 |
3299 |
return;
|
3265 |
3300 |
}
|
3266 |
|
/* New incoming call */
|
3267 |
|
const char *offer = (const char *)mbuf_buf(msg->mb);
|
3268 |
|
if(offer == NULL) {
|
3269 |
|
/* No SDP? */
|
3270 |
|
JANUS_LOG(LOG_WARN, "[SIPre-%s] No SDP in the INVITE?\n", session->account.username);
|
3271 |
|
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
3272 |
|
return;
|
3273 |
|
}
|
|
3301 |
/* New incoming call, check if there's an SDP to process */
|
3274 |
3302 |
char sdp_offer[1024];
|
3275 |
|
g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
|
3276 |
|
JANUS_LOG(LOG_HUGE, "[SIPre-%s] -- Offer: %s\n", session->account.username, sdp_offer);
|
3277 |
|
/* Parse the remote SDP */
|
3278 |
|
char sdperror[100];
|
3279 |
|
janus_sdp *sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
|
3280 |
|
if(!sdp) {
|
3281 |
|
JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
|
3282 |
|
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
3283 |
|
return;
|
|
3303 |
janus_sdp *sdp = NULL;
|
|
3304 |
const char *offer = (const char *)mbuf_buf(msg->mb);
|
|
3305 |
if(offer == NULL || mbuf_get_left(msg->mb) == 0) {
|
|
3306 |
JANUS_LOG(LOG_WARN, "[SIPre-%s] Received offerless INVITE\n", session->account.username);
|
|
3307 |
} else {
|
|
3308 |
g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
|
|
3309 |
JANUS_LOG(LOG_WARN, "[SIPre-%s] -- Offer: %s\n", session->account.username, sdp_offer);
|
|
3310 |
/* Parse the remote SDP */
|
|
3311 |
char sdperror[100];
|
|
3312 |
sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
|
|
3313 |
if(!sdp) {
|
|
3314 |
JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
|
|
3315 |
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
|
3316 |
return;
|
|
3317 |
}
|
3284 |
3318 |
}
|
3285 |
3319 |
session->callee = g_strdup(from);
|
3286 |
3320 |
session->callid = g_strdup(callid);
|
... | ... | |
3290 |
3324 |
janus_sipre_srtp_cleanup(session);
|
3291 |
3325 |
/* Parse SDP */
|
3292 |
3326 |
JANUS_LOG(LOG_VERB, "Someone is inviting us a call\n");
|
3293 |
|
gboolean changed = FALSE;
|
3294 |
|
janus_sipre_sdp_process(session, sdp, FALSE, FALSE, &changed);
|
3295 |
|
/* Check if offer has neither audio nor video, fail with 488 */
|
3296 |
|
if (!session->media.has_audio && !session->media.has_video) {
|
3297 |
|
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
3298 |
|
janus_sdp_free(sdp);
|
3299 |
|
return;
|
3300 |
|
}
|
3301 |
|
/* Also fail with 488 if there's no remote IP address that can be used for RTP */
|
3302 |
|
if (!session->media.remote_ip) {
|
3303 |
|
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
3304 |
|
janus_sdp_free(sdp);
|
3305 |
|
return;
|
|
3327 |
if(sdp) {
|
|
3328 |
gboolean changed = FALSE;
|
|
3329 |
janus_sipre_sdp_process(session, sdp, FALSE, FALSE, &changed);
|
|
3330 |
/* Check if offer has neither audio nor video, fail with 488 */
|
|
3331 |
if(!session->media.has_audio && !session->media.has_video) {
|
|
3332 |
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
|
3333 |
janus_sdp_free(sdp);
|
|
3334 |
return;
|
|
3335 |
}
|
|
3336 |
/* Also fail with 488 if there's no remote IP address that can be used for RTP */
|
|
3337 |
if(!session->media.remote_ip) {
|
|
3338 |
mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
|
|
3339 |
janus_sdp_free(sdp);
|
|
3340 |
return;
|
|
3341 |
}
|
3306 |
3342 |
}
|
3307 |
3343 |
session->stack.invite = msg;
|
3308 |
|
/* Send SDP to the browser */
|
3309 |
|
json_t *jsep = json_pack("{ssss}", "type", "offer", "sdp", sdp_offer);
|
|
3344 |
/* Notify the browser about the call */
|
|
3345 |
json_t *jsep = NULL;
|
|
3346 |
if(sdp)
|
|
3347 |
jsep = json_pack("{ssss}", "type", "offer", "sdp", sdp_offer);
|
3310 |
3348 |
json_t *call = json_object();
|
3311 |
3349 |
json_object_set_new(call, "sip", json_string("event"));
|
3312 |
3350 |
json_t *calling = json_object();
|
... | ... | |
3315 |
3353 |
if(strlen(dname)) {
|
3316 |
3354 |
json_object_set_new(calling, "displayname", json_string(dname));
|
3317 |
3355 |
}
|
3318 |
|
if(session->media.has_srtp_remote) {
|
|
3356 |
if(sdp && session->media.has_srtp_remote) {
|
3319 |
3357 |
/* FIXME Maybe a true/false instead? */
|
3320 |
3358 |
json_object_set_new(calling, "srtp", json_string(session->media.require_srtp ? "sdes_mandatory" : "sdes_optional"));
|
3321 |
3359 |
}
|
... | ... | |
3325 |
3363 |
JANUS_LOG(LOG_VERB, " >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
|
3326 |
3364 |
}
|
3327 |
3365 |
json_decref(call);
|
3328 |
|
json_decref(jsep);
|
|
3366 |
if(jsep)
|
|
3367 |
json_decref(jsep);
|
3329 |
3368 |
janus_sdp_free(sdp);
|
3330 |
3369 |
/* Also notify event handlers */
|
3331 |
3370 |
if(notify_events && gateway->events_is_enabled()) {
|