www.pudn.com > exosip.rar > jcalls.c
/* The antisipc program is a modular SIP softphone (SIP -rfc3261-) Copyright (C) 2005 Aymeric MOIZARD -*/ #include "jcalls.h" #include #include "sdptools.h" call_t calls[MAX_NUMBER_OF_CALLS]; static int ___call_init = 0; static int __call_init () { int k; for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { memset (&(calls[k]), 0, sizeof (call_t)); calls[k].state = NOT_USED; snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) return os_sound_init (); #else return 0; #endif } #if defined(ORTP_SUPPORT) void rcv_telephone_event (RtpSession * rtp_session, call_t * ca) { /* telephone-event received! */ } #endif int call_get_number_of_pending_calls (void) { int pos = 0; int k; for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED) { pos++; } } return pos; } call_t * call_get_call (int pos) { return &calls[pos]; } int call_get_callpos (call_t * ca) { return ca - calls; } call_t * call_locate_call_by_cid (int cid) { int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == cid) return &calls[k]; } return 0; } call_t * call_create_call (int cid) { int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) { memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); calls[k].cid = cid; calls[k].did = -1; calls[k].state = -1; return &calls[k]; } } return 0; } call_t * call_locate_call (eXosip_event_t * je, int createit) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) { if (!createit) return 0; for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) break; } if (k == MAX_NUMBER_OF_CALLS) return NULL; ca = &(calls[k]); memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); ca->cid = je->cid; ca->did = je->did; if (ca->did < 1 && ca->cid < 1) { exit (0); return NULL; /* not enough information for this event?? */ } } ca = &(calls[k]); osip_strncpy (ca->textinfo, je->textinfo, 255); ca->state = je->type; return ca; } call_t * call_find_call (int pos) { int k; for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED) { if (pos == 0) return &(calls[k]); pos--; } } return NULL; } int call_new (eXosip_event_t * je) { sdp_message_t *remote_sdp = NULL; call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); ca->cid = je->cid; ca->did = je->did; ca->tid = je->tid; if (ca->did < 1 && ca->cid < 1) { return -1; /* not enough information for this event?? */ } osip_strncpy (ca->textinfo, je->textinfo, 255); if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } if (je->request != NULL) { char *tmp = NULL; osip_from_to_str (je->request->from, &tmp); if (tmp != NULL) { snprintf (ca->remote_uri, 256, "%s", tmp); osip_free (tmp); } } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_init (); #endif /* negotiate payloads */ if (je->request != NULL) { remote_sdp = eXosip_get_sdp_info (je->request); } if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "missing SDP in INVITE request\n")); } if (remote_sdp != NULL) /* TODO: else build an offer */ { sdp_connection_t *conn; sdp_media_t *remote_med; char *tmp = NULL; if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); eXosip_call_send_answer (ca->tid, 400, NULL); sdp_message_free (remote_sdp); return 0; } conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med == NULL || remote_med->m_port == NULL) { /* no audio media proposed */ eXosip_call_send_answer (ca->tid, 415, NULL); sdp_message_free (remote_sdp); return 0; } ca->remote_sdp_audio_port = atoi (remote_med->m_port); if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { int pos; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); pos = 0; while (!osip_list_eol (&remote_med->m_payloads, pos)) { tmp = (char *) osip_list_get (&remote_med->m_payloads, pos); if (tmp != NULL && (0 == osip_strcasecmp (tmp, "0") || 0 == osip_strcasecmp (tmp, "8"))) { break; } tmp = NULL; pos++; } } if (tmp != NULL) { ca->payload = atoi (tmp); } else { eXosip_call_send_answer (ca->tid, 415, NULL); sdp_message_free (remote_sdp); return 0; } if (tmp != NULL && (ca->payload == 0 || ca->payload == 8) && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) -> %s:%i\n", ca->payload, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); } } #ifndef TEST_PRACK_SUPPORT eXosip_lock (); eXosip_call_send_answer (ca->tid, 180, NULL); eXosip_unlock (); #else if (remote_sdp != NULL) /* TODO: else build an offer */ { osip_message_t *answer; int i; eXosip_lock (); i = eXosip_call_build_answer (ca->tid, 183, &answer); if (i == 0) { osip_message_set_require (answer, "100rel"); osip_message_set_header (answer, "RSeq", "1"); i = sdp_complete_message (ca->did, remote_sdp, answer); if (i != 0) { osip_message_free (answer); eXosip_call_send_answer (ca->tid, 415, NULL); } else { /* start sending audio */ if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } if (ca->enable_audio != 1) /* audio is started */ { sdp_message_t *local_sdp; local_sdp = eXosip_get_sdp_info (answer); if (remote_sdp != NULL && local_sdp != NULL) { sdp_connection_t *conn; sdp_media_t *local_med; sdp_media_t *remote_med; char *tmp = NULL; int audio_port = 0; conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med != NULL && remote_med->m_port != NULL) { ca->remote_sdp_audio_port = atoi (remote_med->m_port); } local_med = eXosip_get_audio_media (local_sdp); if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0' && local_med != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); tmp = (char *) osip_list_get (&local_med->m_payloads, 0); } if (tmp != NULL) { ca->payload = atoi (tmp); } if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); /* search if stream is sendonly or recvonly */ ca->remote_sendrecv = _sdp_analyse_attribute (remote_sdp, remote_med); ca->local_sendrecv = _sdp_analyse_attribute (local_sdp, local_med); if (ca->local_sendrecv == _SENDRECV) { if (ca->remote_sendrecv == _SENDONLY) ca->local_sendrecv = _RECVONLY; else if (ca->remote_sendrecv == _RECVONLY) ca->local_sendrecv = _SENDONLY; } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) if (0 == os_sound_start (ca, audio_port)) { ca->enable_audio = 1; /* audio is started */ } #endif } } sdp_message_free (local_sdp); } i = eXosip_call_send_answer (ca->tid, 183, answer); } if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "cannot send 183 progress?\n")); } } eXosip_unlock (); } #endif sdp_message_free (remote_sdp); ca->state = je->type; return 0; } int call_ack (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (je->ack != NULL) { sdp_message_t *remote_sdp; remote_sdp = eXosip_get_sdp_info (je->ack); if (remote_sdp != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SDP detected in ACK!\n")); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "no SDP detected in ACK!\n")); } } if (ca->enable_audio != 1) /* audio is started */ { sdp_message_t *remote_sdp; sdp_message_t *local_sdp; remote_sdp = eXosip_get_remote_sdp (ca->did); local_sdp = eXosip_get_local_sdp (ca->did); if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); } if (remote_sdp != NULL && local_sdp != NULL) { sdp_connection_t *conn; sdp_media_t *local_med; sdp_media_t *remote_med; char *tmp = NULL; int audio_port = 0; conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med != NULL && remote_med->m_port != NULL) { ca->remote_sdp_audio_port = atoi (remote_med->m_port); } local_med = eXosip_get_audio_media (local_sdp); if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0' && local_med != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); tmp = (char *) osip_list_get (&local_med->m_payloads, 0); } if (tmp != NULL) { ca->payload = atoi (tmp); } if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); /* search if stream is sendonly or recvonly */ ca->remote_sendrecv = _sdp_analyse_attribute (remote_sdp, remote_med); ca->local_sendrecv = _sdp_analyse_attribute (local_sdp, local_med); if (ca->local_sendrecv == _SENDRECV) { if (ca->remote_sendrecv == _SENDONLY) ca->local_sendrecv = _RECVONLY; else if (ca->remote_sendrecv == _RECVONLY) ca->local_sendrecv = _SENDONLY; } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) if (0 == os_sound_start (ca, audio_port)) { ca->enable_audio = 1; /* audio is started */ } #endif } } sdp_message_free (local_sdp); sdp_message_free (remote_sdp); } ca->state = je->type; return 0; } int call_remove (call_t * ca) { if (ca == NULL) return -1; if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } ca->state = NOT_USED; return 0; } int call_proceeding (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) { for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); ca->cid = je->cid; ca->did = je->did; if (ca->did < 1 || ca->cid < 1) { return -1; /* not enough information for this event?? */ } } ca = &(calls[k]); osip_strncpy (ca->textinfo, je->textinfo, 255); if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } if (je->request != NULL) { char *tmp = NULL; osip_from_to_str (je->request->from, &tmp); if (tmp != NULL) { snprintf (ca->remote_uri, 256, "%s", tmp); osip_free (tmp); } } ca->state = je->type; return 0; } int call_ringing (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) { for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); ca->cid = je->cid; ca->did = je->did; if (ca->did < 1 || ca->cid < 1) { return -1; /* not enough information for this event?? */ } } ca = &(calls[k]); ca->cid = je->cid; ca->did = je->did; ca->tid = je->tid; osip_strncpy (ca->textinfo, je->textinfo, 255); if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } if (je->request != NULL) { char *tmp = NULL; osip_from_to_str (je->request->from, &tmp); if (tmp != NULL) { snprintf (ca->remote_uri, 256, "%s", tmp); osip_free (tmp); } } if (ca->enable_audio == 1 && je->response != NULL) { sdp_message_t *sdp = eXosip_get_sdp_info (je->response); if (sdp != NULL) { /* audio is started and session may just have been modified */ sdp_message_free (sdp); } } { osip_header_t *rseq; osip_message_header_get_byname (je->response, "RSeq", 0, &rseq); if (rseq != NULL && rseq->hvalue != NULL) { /* try sending a PRACK */ osip_message_t *prack = NULL; int i; eXosip_lock (); i = eXosip_call_build_prack (ca->tid, &prack); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Failed to build PRACK request\n")); } else { eXosip_call_send_prack (ca->tid, prack); } eXosip_unlock (); } } if (ca->enable_audio != 1) /* audio is started */ { sdp_message_t *remote_sdp; sdp_message_t *local_sdp; local_sdp = eXosip_get_sdp_info (je->request); remote_sdp = eXosip_get_sdp_info (je->response); if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); /* TODO: remote_sdp = retreive from ack above */ } if (local_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "SDP body was probably in the ACK (TODO)\n")); } if (remote_sdp != NULL && local_sdp != NULL) { sdp_connection_t *conn; sdp_media_t *local_med; sdp_media_t *remote_med; char *tmp = NULL; int audio_port = 0; conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med != NULL && remote_med->m_port != NULL) { ca->remote_sdp_audio_port = atoi (remote_med->m_port); } local_med = eXosip_get_audio_media (local_sdp); if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0' && remote_med != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); tmp = (char *) osip_list_get (&remote_med->m_payloads, 0); } if (tmp != NULL) { ca->payload = atoi (tmp); } if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); /* search if stream is sendonly or recvonly */ ca->remote_sendrecv = _sdp_analyse_attribute (remote_sdp, remote_med); ca->local_sendrecv = _sdp_analyse_attribute (local_sdp, local_med); if (ca->local_sendrecv == _SENDRECV) { if (ca->remote_sendrecv == _SENDONLY) ca->local_sendrecv = _RECVONLY; else if (ca->remote_sendrecv == _RECVONLY) ca->local_sendrecv = _SENDONLY; } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) if (0 == os_sound_start (ca, audio_port)) { ca->enable_audio = 1; /* audio is started */ } #endif } } sdp_message_free (local_sdp); sdp_message_free (remote_sdp); } ca->state = je->type;; return 0; } int call_answered (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) { for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state == NOT_USED) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); memset (&(calls[k]), 0, sizeof (call_t)); snprintf (calls[k].wav_file, 256, "%s", "ringback.wav"); ca->cid = je->cid; ca->did = je->did; if (ca->did < 1 && ca->cid < 1) { exit (0); return -1; /* not enough information for this event?? */ } } ca = &(calls[k]); osip_strncpy (ca->textinfo, je->textinfo, 255); if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } if (je->request != NULL) { char *tmp = NULL; osip_from_to_str (je->request->from, &tmp); if (tmp != NULL) { snprintf (ca->remote_uri, 256, "%s", tmp); osip_free (tmp); } } eXosip_lock (); { osip_message_t *ack = NULL; int i; i = eXosip_call_build_ack (ca->did, &ack); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Cannot build ACK for call!\n")); } else { sdp_message_t *local_sdp = NULL; sdp_message_t *remote_sdp = NULL; if (je->request != NULL && je->response != NULL) { local_sdp = eXosip_get_sdp_info (je->request); remote_sdp = eXosip_get_sdp_info (je->response); } if (local_sdp == NULL && remote_sdp != NULL) { /* sdp in ACK */ i = sdp_complete_message (ca->did, remote_sdp, ack); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Cannot complete ACK with sdp body?!\n")); } } sdp_message_free (local_sdp); sdp_message_free (remote_sdp); eXosip_call_send_ack (ca->did, ack); } } eXosip_unlock (); if (ca->enable_audio == 1 && je->response != NULL) { sdp_message_t *sdp = eXosip_get_sdp_info (je->response); if (sdp != NULL) { /* audio is started and session has just been modified */ ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif sdp_message_free (sdp); } } if (ca->enable_audio != 1) /* audio is started */ { sdp_message_t *remote_sdp; sdp_message_t *local_sdp; local_sdp = eXosip_get_sdp_info (je->request); remote_sdp = eXosip_get_sdp_info (je->response); if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); /* TODO: remote_sdp = retreive from ack above */ } if (local_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "SDP body was probably in the ACK (TODO)\n")); } if (remote_sdp != NULL && local_sdp != NULL) { sdp_connection_t *conn; sdp_media_t *local_med; sdp_media_t *remote_med; char *tmp = NULL; int audio_port = 0; conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med != NULL && remote_med->m_port != NULL) { ca->remote_sdp_audio_port = atoi (remote_med->m_port); } local_med = eXosip_get_audio_media (local_sdp); if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0' && remote_med != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); tmp = (char *) osip_list_get (&remote_med->m_payloads, 0); } if (tmp != NULL) { ca->payload = atoi (tmp); } if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); /* search if stream is sendonly or recvonly */ ca->remote_sendrecv = _sdp_analyse_attribute (remote_sdp, remote_med); ca->local_sendrecv = _sdp_analyse_attribute (local_sdp, local_med); if (ca->local_sendrecv == _SENDRECV) { if (ca->remote_sendrecv == _SENDONLY) ca->local_sendrecv = _RECVONLY; else if (ca->remote_sendrecv == _RECVONLY) ca->local_sendrecv = _SENDONLY; } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) if (0 == os_sound_start (ca, audio_port)) { ca->enable_audio = 1; /* audio is started */ } #endif } } sdp_message_free (local_sdp); sdp_message_free (remote_sdp); } ca->state = je->type; return 0; } int call_redirected (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } ca->state = NOT_USED; return 0; } int call_requestfailure (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if ((je->response != NULL && je->response->status_code == 407) || (je->response != NULL && je->response->status_code == 401)) { /* try authentication */ return 0; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } ca->state = NOT_USED; return 0; } int call_serverfailure (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } ca->state = NOT_USED; return 0; } int call_globalfailure (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } ca->state = NOT_USED; return 0; } int call_closed (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } ca->state = NOT_USED; return 0; } int call_modified (eXosip_event_t * je) { call_t *ca; int k; if (___call_init == 0) { ___call_init = -1; __call_init (); } for (k = 0; k < MAX_NUMBER_OF_CALLS; k++) { if (calls[k].state != NOT_USED && calls[k].cid == je->cid && calls[k].did == je->did) break; } if (k == MAX_NUMBER_OF_CALLS) return -1; ca = &(calls[k]); ca->tid = je->tid; osip_strncpy (ca->textinfo, je->textinfo, 255); if (je->response != NULL) { ca->status_code = je->response->status_code; snprintf (ca->reason_phrase, 50, je->response->reason_phrase); } if (je->request != NULL) { char *tmp = NULL; osip_from_to_str (je->request->from, &tmp); if (tmp != NULL) { snprintf (ca->remote_uri, 256, "%s", tmp); osip_free (tmp); } } ca->state = je->type; eXosip_lock (); { osip_message_t *answer = NULL; int i; i = eXosip_call_build_answer (ca->tid, 200, &answer); if (i != 0) { eXosip_call_send_answer (ca->tid, 400, NULL); eXosip_unlock (); return 0; } else { sdp_message_t *remote_sdp = NULL; if (je->request != NULL) remote_sdp = eXosip_get_sdp_info (je->request); if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); /* TODO: sdp in 200 & ACK */ eXosip_call_send_answer (ca->tid, 200, answer); } else { i = sdp_complete_message (ca->did, remote_sdp, answer); if (i != 0) { sdp_message_free (remote_sdp); osip_message_free (answer); eXosip_call_send_answer (ca->tid, 415, NULL); eXosip_unlock (); return 0; } else eXosip_call_send_answer (ca->tid, 200, answer); sdp_message_free (remote_sdp); } } } eXosip_unlock (); if (ca->enable_audio > 0) { ca->enable_audio = -1; #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) os_sound_close (ca); #endif } if (ca->enable_audio != 1) /* audio is started */ { sdp_message_t *remote_sdp; sdp_message_t *local_sdp; remote_sdp = eXosip_get_remote_sdp (ca->did); local_sdp = eXosip_get_local_sdp (ca->did); if (remote_sdp == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "No remote SDP body found for call\n")); } if (remote_sdp != NULL && local_sdp != NULL) { sdp_connection_t *conn; sdp_media_t *local_med; sdp_media_t *remote_med; char *tmp = NULL; int audio_port = 0; conn = eXosip_get_audio_connection (remote_sdp); if (conn != NULL && conn->c_addr != NULL) { snprintf (ca->remote_sdp_audio_ip, 50, conn->c_addr); } remote_med = eXosip_get_audio_media (remote_sdp); if (remote_med != NULL && remote_med->m_port != NULL) { ca->remote_sdp_audio_port = atoi (remote_med->m_port); } local_med = eXosip_get_audio_media (local_sdp); if (local_med != NULL && local_med->m_port != NULL) { audio_port = atoi (local_med->m_port); } if (ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0' && local_med != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection found: %s:%i\n", ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); tmp = (char *) osip_list_get (&local_med->m_payloads, 0); } if (tmp != NULL) { ca->payload = atoi (tmp); } if (tmp != NULL && audio_port > 0 && ca->remote_sdp_audio_port > 0 && ca->remote_sdp_audio_ip[0] != '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "audio connection: (payload=%i) %i -> %s:%i\n", ca->payload, audio_port, ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port)); /* search if stream is sendonly or recvonly */ ca->remote_sendrecv = _sdp_analyse_attribute (remote_sdp, remote_med); ca->local_sendrecv = _sdp_analyse_attribute (local_sdp, local_med); if (ca->local_sendrecv == _SENDRECV) { if (ca->remote_sendrecv == _SENDONLY) ca->local_sendrecv = _RECVONLY; else if (ca->remote_sendrecv == _RECVONLY) ca->local_sendrecv = _SENDONLY; } #if defined(ORTP_SUPPORT) || defined(UCL_SUPPORT) if (0 == os_sound_start (ca, audio_port)) { ca->enable_audio = 1; /* audio is started */ } #endif } } sdp_message_free (local_sdp); sdp_message_free (remote_sdp); } return 0; }