www.pudn.com > exosip.rar > jcalls.cpp


/* This source has been formatted by an unregistered SourceFormatX */ 
/* If you want to remove this info, please register this shareware */ 
/* Please visit http://www.textrush.com to get more information    */ 
 
/* 
The antisipc program is a modular SIP softphone (SIP -rfc3261-) 
Copyright (C) 2005  Aymeric MOIZARD -  
*/ 
 
#include "stdafx.h" 
#include "jcalls.h" 
#include "sdptools.h" 
#include  
 
 
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; 
}