/**@file tdav_session_mcptt.h * @brief The Media Burst Control Protocol (MCPTT) session. * Used for OMA PoC control plane */ #if !defined(HAVE_TINYMCPTT) || HAVE_TINYMCPTT #include "tinydav/mcptt/tdav_session_mcptt.h" #include "tinymcptt/tmcptt_manager.h" #include "tinyrtp/rtp/trtp_rtp_packet.h" #include "tinyrtp/rtcp/trtp_rtcp_packet.h" #include "tinyrtp/rtcp/trtp_rtcp_header.h" #include "tinyrtp/rtcp/trtp_rtcp_report_app.h" #include "tinymcptt/packet/tmcptt_mcptt_packet.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_taken.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_idle.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_granted.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_request.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_release.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_ack.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_deny.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_revoke.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_specific.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_queue_position_info.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_queue_position_request.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_preestablished.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_ack_preestablished.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_connect.h" #include "tinymcptt/packet/tmcptt_mcptt_packet_disconnect.h" #include "tinymcptt/tmcptt_event.h" #include "tinymcptt/tmcptt_timers.h" #include "tinymcptt/tmcptt_counters.h" #include "tsk_memory.h" /* TSK_FREE */ #include "tsk_timer.h" /** This function is in all services tinyDAV */ int tdav_mcptt_event_proxy_cb(tmcptt_event_t* _event/*!Not the owner of the object*/) { tdav_session_mcptt_t* mcptt; int ret = 0; if(!_event || !_event->callback_data){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } mcptt = tsk_object_ref((void*)_event->callback_data); if(TMEDIA_SESSION_MCPTT(mcptt)->callback.func){ _event->callback_data = TMEDIA_SESSION_MSRP(mcptt)->callback.data; // steal callback data ret = TMEDIA_SESSION_MCPTT(mcptt)->callback.func(_event); // call callback function() } tsk_object_unref(mcptt); return ret; } static int tdav_session_mcptt_alert_user(tdav_session_mcptt_t* self, tmcptt_event_type_t type, tmcptt_message_t* message) { int ret; tdav_session_mcptt_t *session = (tdav_session_mcptt_t*)tsk_object_ref((void*)self); tmcptt_event_t* _event = tmcptt_event_create(session, type, message); ret = tdav_mcptt_event_proxy_cb(_event); TSK_OBJECT_SAFE_FREE(_event); tsk_object_unref(session); return ret; } static int tdav_session_mcptt_timer_t100_expired_handler(const void* arg, tsk_timer_id_t timer_id) { //T100 (Floor release) tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)arg; va_list ap; if (mcptt == tsk_null) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->timer_t100.id != timer_id) { TSK_DEBUG_ERROR("Incorrect timer identity"); return -1; } switch (mcptt->mcptt_status) { case mcptt_status_pending_release: { if (mcptt->counter_c100.curr_value < mcptt->counter_c100.max_value) { va_start(ap, "token"); tdav_session_mcptt_send_release(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->timer_t100.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t100.timeout, tdav_session_mcptt_timer_t100_expired_handler, mcptt); mcptt->counter_c100.curr_value++; } else mcptt->mcptt_status = mcptt_status_no_permission; break; } } return 0; } static int tdav_session_mcptt_timer_t101_expired_handler(const void* arg, tsk_timer_id_t timer_id) { //T101 (Floor request) tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)arg; va_list ap; if (mcptt == tsk_null) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->timer_t101.id != timer_id) { TSK_DEBUG_ERROR("Incorrect timer identity"); return -1; } switch (mcptt->mcptt_status) { case mcptt_status_pending_request: { if (mcptt->counter_c101.curr_value < mcptt->counter_c101.max_value) { va_start(ap, "token"); tdav_session_mcptt_send_request(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->timer_t101.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t101.timeout, tdav_session_mcptt_timer_t101_expired_handler, mcptt); mcptt->counter_c101.curr_value++; } else { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_denied, tsk_null); mcptt->mcptt_status = mcptt_status_no_permission; } break; } } return 0; } static int tdav_session_mcptt_timer_t103_expired_handler(const void* arg, tsk_timer_id_t timer_id) { //T103 (End of RTP media) tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)arg; if (mcptt == tsk_null) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->timer_t103.id != timer_id) { TSK_DEBUG_ERROR("Incorrect timer identity"); return -1; } switch (mcptt->mcptt_status) { case mcptt_status_no_permission: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_idle_channel, tsk_null); break; } } return 0; } static int tdav_session_mcptt_timer_t104_expired_handler(const void* arg, tsk_timer_id_t timer_id) { //T104 (Floor Queue Position Request) tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)arg; va_list ap; if (mcptt == tsk_null) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->timer_t104.id != timer_id) { TSK_DEBUG_ERROR("Incorrect timer identity"); return -1; } switch (mcptt->mcptt_status) { case mcptt_status_queued: { if (mcptt->counter_c104.curr_value < mcptt->counter_c104.max_value) { va_start(ap, "token"); tdav_session_mcptt_send_queue_position_request(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->timer_t104.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t104.timeout, tdav_session_mcptt_timer_t104_expired_handler, mcptt); mcptt->counter_c104.curr_value++; } else { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_queued_timeout, tsk_null); va_start(ap, "token"); tdav_session_mcptt_send_release(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->mcptt_status = mcptt_status_pending_release; } break; } } return 0; } static int tdav_session_mcptt_timer_t132_expired_handler(const void* arg, tsk_timer_id_t timer_id) { //T132 (Queued granted user action) tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)arg; va_list ap; if (mcptt == tsk_null) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->timer_t132.id != timer_id) { TSK_DEBUG_ERROR("Incorrect timer identity"); return -1; } switch (mcptt->mcptt_status) { case mcptt_status_queued: { va_start(ap, "token"); tdav_session_mcptt_send_release(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->mcptt_status = mcptt_status_no_permission; break; } } return 0; } /** In this function is state machine of mcptt */ static int tdav_session_mcptt_cb(const void* callback_data, const trtp_rtcp_packet_t* packet, ...) { /* tdav_session_mcptt_t* mcptt = (tdav_session_mcptt_t*)callback_data; const trtp_rtcp_report_app_t* rtcp_app = tsk_null; TSK_DEBUG_INFO("tdav_session_mcptt_cb"); //#define TMCPTT_ALERT_USER(type) \ //{ \ // tdav_session_mcptt_t *session = (tdav_session_mcptt_t*)tsk_object_ref((void*)mcptt); \ // tmcptt_event_t* _event = tmcptt_event_create(session, tsk_false, type); \ // tdav_mcptt_event_proxy_cb(_event); \ // TSK_OBJECT_SAFE_FREE(_event); \ // tsk_object_unref(session); \ //} if (!packet || !callback_data) { TSK_DEBUG_ERROR("Invalid MCPTT packet"); return -1; } if(packet->header->type != trtp_rtcp_packet_type_app){ TSK_DEBUG_ERROR("Invalid RTCP packet."); return -1; } rtcp_app = (const trtp_rtcp_report_app_t*)packet; if(tsk_strnicmp(rtcp_app->name, MCPTT_PROTO_NAME, 4) != 0){ TSK_DEBUG_ERROR("Incorrect application"); return -1; } TSK_DEBUG_INFO("MCPTT message received from SSRC: %u", rtcp_app->ssrc); switch(rtcp_app->subtype) { case MCPTT_TAKEN_ACK: { va_list ap; va_start(ap, "token"); tdav_session_mcptt_send_ack(TMEDIA_SESSION_MCPTT(mcptt), MCPTT_TAKEN, &ap); va_end(ap); } case MCPTT_TAKEN: { tmcptt_mcptt_packet_taken_t* taken_msg = tmcptt_mcptt_packet_taken_create_null(); TSK_DEBUG_INFO("MCPTT TAKEN received"); taken_msg = tmcptt_mcptt_packet_taken_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(taken_msg) { if (tdav_session_mcptt_process_taken(mcptt, taken_msg) != 0) { TSK_DEBUG_ERROR("Error processing TAKEN message"); return -1; } } break; } case MCPTT_IDLE_ACK: { va_list ap; va_start(ap, "token"); tdav_session_mcptt_send_ack(TMEDIA_SESSION_MCPTT(mcptt), MCPTT_IDLE, &ap); va_end(ap); } case MCPTT_IDLE: { tmcptt_mcptt_packet_idle_t* idle_msg = tmcptt_mcptt_packet_idle_create_null(); TSK_DEBUG_INFO("MCPTT IDLE received"); idle_msg = tmcptt_mcptt_packet_idle_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(idle_msg) { if (tdav_session_mcptt_process_idle(mcptt, idle_msg) != 0) { TSK_DEBUG_ERROR("Error processing IDLE message"); return -1; } } break; } case MCPTT_GRANTED_ACK: { va_list ap; va_start(ap, "token"); tdav_session_mcptt_send_ack(TMEDIA_SESSION_MCPTT(mcptt), MCPTT_GRANTED, &ap); va_end(ap); } case MCPTT_GRANTED: { tmcptt_mcptt_packet_granted_t* granted_msg = tmcptt_mcptt_packet_granted_create_null(); TSK_DEBUG_INFO("MCPTT GRANTED received"); granted_msg = tmcptt_mcptt_packet_granted_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(granted_msg) { if (tdav_session_mcptt_process_granted(mcptt, granted_msg) != 0) { TSK_DEBUG_ERROR("Error processing GRANTED message"); return -1; } } break; } case MCPTT_DENY_ACK: { va_list ap; va_start(ap, "token"); tdav_session_mcptt_send_ack(TMEDIA_SESSION_MCPTT(mcptt), MCPTT_DENY, &ap); va_end(ap); } case MCPTT_DENY: { tmcptt_mcptt_packet_deny_t* deny_msg = tmcptt_mcptt_packet_deny_create_null(); TSK_DEBUG_INFO("MCPTT DENY received"); deny_msg = tmcptt_mcptt_packet_deny_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(deny_msg) { if (tdav_session_mcptt_process_deny(mcptt, deny_msg) != 0) { TSK_DEBUG_ERROR("Error processing DENY message"); return -1; } } } case MCPTT_QUEUE_POS_INFO_ACK: { va_list ap; va_start(ap, "token"); tdav_session_mcptt_send_ack(TMEDIA_SESSION_MCPTT(mcptt), MCPTT_QUEUE_POS_INFO, &ap); va_end(ap); } case MCPTT_QUEUE_POS_INFO: { tmcptt_mcptt_packet_queue_position_info_t* queue_pos_info_msg = tmcptt_mcptt_packet_queue_position_info_create_null(); TSK_DEBUG_INFO("MCPTT QUEUE POSITION INFO received"); queue_pos_info_msg = tmcptt_mcptt_packet_queue_position_info_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(queue_pos_info_msg) { if (tdav_session_mcptt_process_queue_position_info(mcptt, queue_pos_info_msg) != 0) { TSK_DEBUG_ERROR("Error processing QUEUE POSITION INFO message"); return -1; } } } case MCPTT_REVOKE: { tmcptt_mcptt_packet_revoke_t* revoke_msg = tmcptt_mcptt_packet_revoke_create_null(); TSK_DEBUG_INFO("MCPTT REVOKE received"); revoke_msg = tmcptt_mcptt_packet_revoke_deserialize(rtcp_app->payload, rtcp_app->payload_size); if(revoke_msg) { if (tdav_session_mcptt_process_revoke(mcptt, revoke_msg) != 0) { TSK_DEBUG_ERROR("Error processing REVOKE message"); return -1; } } } } */ return 0; } /* ============ Plugin interface ================= */ int tdav_session_mcptt_set(tmedia_session_t* self, const tmedia_param_t* param) { int ret = 0; tdav_session_mcptt_t* mcptt; if(!self){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } TSK_DEBUG_INFO("tdav_session_mcptt_set"); mcptt = (tdav_session_mcptt_t*)self; if(param->value_type == tmedia_pvt_int32) { if(tsk_striequals(param->key, "local_ssrc")){ mcptt->local_ssrc = TSK_TO_UINT32((uint8_t*)param->value); }else if (tsk_striequals(param->key, "priority")){ mcptt->priority_local=TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "implicit")){ mcptt->implicit_local=TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "granted")){ mcptt->granted_local=TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "type_session")){ mcptt->type_session=TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "t100")){ mcptt->timer_t100.timeout = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "t101")){ mcptt->timer_t101.timeout = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "t103")){ mcptt->timer_t103.timeout = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "t104")){ mcptt->timer_t104.timeout = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "t132")){ mcptt->timer_t132.timeout = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "c100")){ mcptt->counter_c100.max_value = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "c101")){ mcptt->counter_c101.max_value = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "c104")){ mcptt->counter_c104.max_value = TSK_TO_UINT32(((uint8_t*)param->value)); }else if (tsk_striequals(param->key, "queueing_enabled")){ if(TSK_TO_UINT32(((uint8_t*)param->value)) > 0) mcptt->queueing_enabled = tsk_true; else mcptt->queueing_enabled = tsk_false; } } else if(param->value_type == tmedia_pvt_pobject) { if (tsk_striequals(param->key, "audio_session")) { TSK_OBJECT_SAFE_FREE(mcptt->audio_session); mcptt->audio_session = (tmedia_session_audio_t*)tsk_object_ref(param->value); } else if(tsk_striequals(param->key, "multicast_audio_session")) { TSK_OBJECT_SAFE_FREE(mcptt->multicast_audio_session); mcptt->multicast_audio_session = (tmedia_session_audio_t*)tsk_object_ref(param->value); }else if(tsk_striequals(param->key, "mcptt_id_local")) { TSK_OBJECT_SAFE_FREE(mcptt->mcptt_id_local); mcptt->mcptt_id_local = (tsip_uri_t*)tsk_object_ref(param->value); }else if(tsk_striequals(param->key, "mcptt_calling_user_id")) { TSK_OBJECT_SAFE_FREE(mcptt->mcptt_calling_user_id); mcptt->mcptt_calling_user_id = (tsip_uri_t*)tsk_object_ref(param->value); }else if(tsk_striequals(param->key, "mcptt_called_party_id")) { TSK_OBJECT_SAFE_FREE(mcptt->mcptt_called_party_id); mcptt->mcptt_called_party_id = (tsip_uri_t*)tsk_object_ref(param->value); }else if(tsk_striequals(param->key, "mcptt_calling_group_id")) { TSK_OBJECT_SAFE_FREE(mcptt->mcptt_calling_group_id); mcptt->mcptt_calling_group_id = (tsip_uri_t*)tsk_object_ref(param->value); } } else if(param->value_type == tmedia_pvt_pchar){ if(tsk_striequals(param->key, "remote-ip")){ // only if no ip associated to the "m=" line if(param->value && !mcptt->remote_ip){ mcptt->remote_ip = tsk_strdup((const char*)param->value); } } else if(tsk_striequals(param->key, "local-ip")){ tsk_strupdate(&mcptt->local_ip, (const char*)param->value); } } return ret; } int tdav_session_mcptt_get(tmedia_session_t* self, tmedia_param_t* param) { return -1; } int tdav_session_mcptt_prepare(tmedia_session_t* self) { tdav_session_mcptt_t* mcptt; int ret = 0; TSK_DEBUG_INFO("tdav_session_mcptt_prepare"); mcptt = (tdav_session_mcptt_t*)self; mcptt->is_multimedia = tsk_true; mcptt->floorid = 0; //TO-DO mcptt->media_label = "AAA"; //TO-DO if(!mcptt->mcptt_manager) { mcptt->mcptt_manager = tmcptt_manager_create(mcptt->local_ip); if(mcptt->mcptt_manager) { if((ret = tmcptt_manager_set_port_range(mcptt->mcptt_manager, tmedia_defaults_get_rtp_port_range_start(), tmedia_defaults_get_rtp_port_range_stop()))){ return ret; } if((ret = tmcptt_manager_set_mcptt_callback(mcptt->mcptt_manager, tdav_session_mcptt_cb, mcptt))){ return ret; } if((ret = tmcptt_manager_prepare(mcptt->mcptt_manager))){ return ret; } } } if(mcptt->local_port == 0) mcptt->local_port = mcptt->mcptt_manager->public_port; if (mcptt->implicit) { mcptt->mcptt_status = mcptt_status_pending_request; /* Start timer T101 */ mcptt->timer_t101.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t101.timeout, tdav_session_mcptt_timer_t101_expired_handler, mcptt); mcptt->counter_c101.curr_value = 1; } return ret; } int tdav_session_mcptt_start(tmedia_session_t* self) { <<<<<<< HEAD tdav_session_mcptt_t* mcptt; tmcptt_message_t* msg; int ret = 0; va_list ap; ======= //tdav_session_mcptt_t* mcptt; int ret = 0; /* >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a TSK_DEBUG_INFO("tdav_session_mcptt_start"); if(!self){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } mcptt = (tdav_session_mcptt_t*)self; if((ret = tmcptt_manager_set_mcptt_remote(mcptt->mcptt_manager, mcptt->remote_ip, mcptt->remote_port))){ TSK_DEBUG_ERROR("Error setting remote MCPTT parameters"); return -1; } if((ret = tmcptt_manager_start(mcptt->mcptt_manager))){ TSK_DEBUG_ERROR("Error starting MCPTT manager"); return -1; } <<<<<<< HEAD if((ret = tsk_timer_manager_start(mcptt->h_timer)) != 0){ TSK_DEBUG_ERROR("Failed to start the timer"); return ret; } if (mcptt->implicit && mcptt->implicit_response) { if (mcptt->granted && mcptt->granted_response) { msg = tmcptt_message_create_null(); tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_granted, msg); mcptt->mcptt_status = mcptt_status_permission; //No need to send REQUEST nor GRANTED } else mcptt->mcptt_status = mcptt_status_pending_request; //Continue waiting for GRANTED request } else { //Need to send REQUEST message va_start(ap, "token"); tdav_session_mcptt_send_request(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t101.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t101.id); mcptt->timer_t101.id = TSK_INVALID_TIMER_ID; } /* Start timer T101 */ mcptt->timer_t101.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t101.timeout, tdav_session_mcptt_timer_t101_expired_handler, mcptt); mcptt->counter_c101.curr_value = 1; mcptt->mcptt_status = mcptt_status_pending_request; //Wait for GRANTED } if(mcptt->audio_session && mcptt->mcptt_status != mcptt_status_permission) TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; else if(mcptt->audio_session && mcptt->mcptt_status == mcptt_status_permission) TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_false; if(mcptt->multicast_audio_session) TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; ======= */ >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a // /* start the transport */ // if((ret = tnet_transport_start(msrp->transport))){ // goto bail; // } // // switch(msrp->setup){ // case msrp_setup_active: // case msrp_setup_actpass: // { // // // // ACTIVE // // // TSK_DEBUG_INFO("connectto(%s:%d)", msrp->remote_ip, msrp->remote_port); // if((msrp->connectedFD = tnet_transport_connectto_2(msrp->transport, msrp->remote_ip, msrp->remote_port)) == TNET_INVALID_FD){ // TSK_DEBUG_ERROR("Failed to connect to the remote party"); // ret = -2; // goto bail; // } // else{ // //TSK_DEBUG_INFO("Msrp connected FD=%d", msrp->connectedFD); // //if((ret = tnet_sockfd_waitUntilWritable(msrp->connectedFD, TDAV_MSRP_CONNECT_TIMEOUT)) && msrp->offerer){ // // TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected to (%s:%d).", TDAV_MSRP_CONNECT_TIMEOUT, msrp->remote_ip, msrp->remote_port); // // goto bail; // //} // /* draft-denis-simple-msrp-comedia-02 - 4.2.3. Setting up the connection // Once the TCP session is established, and if the answerer was the // active connection endpoint, it MUST send an MSRP request. In // particular, if it has no pending data to send, it MUST send an empty // MSRP SEND request. That is necessary for the other endpoint to // authenticate this TCP session. // // ...RFC 4975 - 7.1 // */ // msrp->send_bodiless = tsk_true; // } // break; // } // default: // { // // // // PASSIVE // // // break; // } // } // // // create and start the receiver // if(!msrp->receiver){ // if((msrp->receiver = tmsrp_receiver_create(msrp->config, msrp->connectedFD))){ // tnet_transport_set_callback(msrp->transport, TNET_TRANSPORT_CB_F(tdav_transport_layer_stream_cb), msrp); // if((ret = tmsrp_receiver_start(msrp->receiver, msrp, tdav_msrp_event_proxy_cb))){ // TSK_DEBUG_ERROR("Failed to start the MSRP receiver"); // goto bail; // } // } // } // // // create and start the sender // if(!msrp->sender){ // if((msrp->sender = tmsrp_sender_create(msrp->config, msrp->connectedFD))){ // msrp->sender->chunck_duration = msrp->chunck_duration; // if((ret = tmsrp_sender_start(msrp->sender))){ // TSK_DEBUG_ERROR("Failed to start the MSRP sender"); // goto bail; // } // } // } // //bail: return ret; } int tdav_session_mcptt_pause(tmedia_session_t* self) { TSK_DEBUG_ERROR("Not Implemented"); return -1; } //BYE int tdav_session_mcptt_stop(tmedia_session_t* self) { tdav_session_mcptt_t* mcptt; int ret = 0; if(!self){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } mcptt = (tdav_session_mcptt_t*)self; tsk_object_unref(mcptt->audio_session); tsk_object_unref(mcptt->multicast_audio_session); // // if(msrp->sender){ // if((ret = tmsrp_sender_stop(msrp->sender))){ // TSK_DEBUG_ERROR("Failed to stop the MSRP sender"); // } // } // if(msrp->receiver){ // if((ret = tmsrp_receiver_stop(msrp->receiver))){ // TSK_DEBUG_ERROR("Failed to stop the MSRP receiver"); // } // } // // if(msrp->transport){ // if((ret = tnet_transport_shutdown(msrp->transport))){ // TSK_DEBUG_ERROR("Failed to stop the MSRP transport"); // } // } if((ret = tmcptt_manager_stop(mcptt->mcptt_manager))){ TSK_DEBUG_ERROR("Error stopping MCPTT manager"); return -1; } return 0; } const tsdp_header_M_t* tdav_session_mcptt_get_lo(tmedia_session_t* self) { tmedia_session_t* base = TMEDIA_SESSION(self); tdav_session_mcptt_t* mcptt; tsk_bool_t changed = tsk_false; const char* proto_transport = "udp"; const char* proto = "MCPTT"; char* proto_attr; size_t proto_attr_len = 0; const char* multi = "multimedia"; const char* mstrm = "mstrm"; const char* priority = "mc_priority"; const char* implicit = "mc_implicit_request"; const char* granted = "mc_granted"; char* fmtp_attr; char* fmtp_attr_int; size_t fmtp_attr_len = 0; tsk_istr_t floorid_str; TSK_DEBUG_INFO("tdav_session_mcptt_get_lo"); if(!self || !self->plugin){ TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } mcptt = (tdav_session_mcptt_t*)self; if(!base->M.lo) { //Create INVITE SRC and recive INVITE if((base->M.lo = tsdp_header_M_create(base->plugin->media, mcptt->local_port, proto_transport))) { fmtp_attr_int=(char*)tsk_calloc(fmtp_attr_len, 1); tsdp_header_M_add_headers(base->M.lo, TSDP_FMT_VA_ARGS(proto), tsk_null); proto_attr_len = tsk_strlen(proto) + 1; if(mcptt->is_multimedia) proto_attr_len += tsk_strlen(multi) + 2; proto_attr = (char*)tsk_calloc(proto_attr_len, sizeof(char)); if(mcptt->is_multimedia) tsk_sprintf(&proto_attr, "%s %s=1", proto, multi); else tsk_sprintf(&proto_attr, "%s", proto); tsk_itoa(mcptt->floorid, &floorid_str); if(base->M.ro){ fmtp_attr_len=tsk_strlen(proto)+tsk_strlen(priority)+3; fmtp_attr = (char*)tsk_calloc(fmtp_attr_len, sizeof(char)); if(mcptt->priority_remote>mcptt->priority_local && mcptt->priority_local>0 && mcptt->priority_local<10){ tsk_sprintf(&fmtp_attr, "%s %s=%d", proto,priority,mcptt->priority_local); }else if(mcptt->priority_remote<=mcptt->priority_local && mcptt->priority_remote>0 && mcptt->priority_remote<10){ tsk_sprintf(&fmtp_attr, "%s %s=%d", proto,priority,mcptt->priority_remote); }else { tsk_sprintf(&fmtp_attr, "%s %s=%d", proto,priority,0); } if(mcptt->granted_remote==tsk_true && mcptt->granted_local==tsk_true){ fmtp_attr_len+=1+tsk_strlen(granted); fmtp_attr_int=(char*)tsk_calloc(fmtp_attr_len, sizeof(char)); tsk_sprintf(&fmtp_attr_int, "%s;%s",fmtp_attr, granted); fmtp_attr=tsk_realloc(fmtp_attr, fmtp_attr_len*sizeof(char)); strcpy(fmtp_attr, fmtp_attr_int); } if(mcptt->implicit_remote==tsk_true && mcptt->implicit_local==tsk_true){ fmtp_attr_len+=1+tsk_strlen(implicit); fmtp_attr_int=(char*)tsk_calloc(fmtp_attr_len, sizeof(char)); tsk_sprintf(&fmtp_attr_int, "%s;%s", fmtp_attr, implicit); fmtp_attr=tsk_realloc(fmtp_attr, fmtp_attr_len*sizeof(char)); strcpy(fmtp_attr, fmtp_attr_int); } }else{ fmtp_attr_len=tsk_strlen(proto)+tsk_strlen(priority)+3; fmtp_attr = (char*)tsk_calloc(fmtp_attr_len, sizeof(char)); if(mcptt->priority_local>0 && mcptt->priority_local<10){ tsk_sprintf(&fmtp_attr, "%s %s=%d", proto,priority,mcptt->priority_local); }else{ tsk_sprintf(&fmtp_attr, "%s %s=%d", proto,priority,0); } if(mcptt->granted_local==tsk_true){ fmtp_attr_len+=1+tsk_strlen(granted); fmtp_attr_int=(char*)tsk_calloc(fmtp_attr_len, sizeof(char)); tsk_sprintf(&fmtp_attr_int, "%s;%s",fmtp_attr, granted); fmtp_attr=tsk_realloc(fmtp_attr, fmtp_attr_len*sizeof(char)); strcpy(fmtp_attr, fmtp_attr_int); } if(mcptt->implicit_local==tsk_true){ fmtp_attr_len+=1+tsk_strlen(implicit); fmtp_attr_int=(char*)tsk_calloc(fmtp_attr_len, sizeof(char)); tsk_sprintf(&fmtp_attr_int, "%s;%s", fmtp_attr, implicit); fmtp_attr=tsk_realloc(fmtp_attr, fmtp_attr_len*sizeof(char)); strcpy(fmtp_attr, fmtp_attr_int); } } //strcpy(array2, array1); //mc_priority=(0-7) tsdp_header_M_add_headers(base->M.lo, TSDP_HEADER_A_VA_ARGS("fmtp",fmtp_attr), tsk_null); tsk_free((void**)&fmtp_attr_int); tsk_free((void**)&proto_attr); fmtp_attr=tsk_realloc(fmtp_attr, fmtp_attr_len*sizeof(char)); tsk_free((void**)&fmtp_attr); } }else{//PROCESS INVITE DSC } return self->M.lo; } int tdav_session_mcptt_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m) { tdav_session_mcptt_t* mcptt; const tsdp_header_A_t* A_fmtp; //tsk_bool_t answer; TSK_DEBUG_INFO("tdav_session_mcptt_set_ro"); if(!self || !m){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } self->M.ro = tsk_object_ref((void*)m); mcptt = (tdav_session_mcptt_t*)self; mcptt->remote_port = m->port; if((A_fmtp = tsdp_header_M_findA(m, "fmtp"))){ int index; char num_char; int num; const char* priority = "mc_priority"; const char* implicit = "mc_implicit_request"; const char* granted = "mc_granted"; if((index=tsk_strindexOf(A_fmtp->value,tsk_strlen(A_fmtp->value),granted))>=0){ mcptt->granted_remote=tsk_true; } if((index=tsk_strindexOf(A_fmtp->value,tsk_strlen(A_fmtp->value),implicit))>=0){ mcptt->implicit_remote=tsk_true; } if((index=tsk_strindexOf(A_fmtp->value,tsk_strlen(A_fmtp->value),priority))>=0){ num_char=(A_fmtp->value)[1+index+tsk_strlen(priority)]; num=num_char-'0'; if(num>=0 && num<10){ mcptt->priority_remote=(uint32_t)num; }else{ mcptt->priority_remote=(uint32_t)0; } } } // return 0; } /* ============ Public functions ================= */ int tdav_session_mcptt_request_token (tmedia_session_mcptt_t* self, va_list *app) { <<<<<<< HEAD tdav_session_mcptt_t* mcptt; int ret = 0; if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->mcptt_status != mcptt_status_no_permission) { TSK_DEBUG_ERROR("Incorrect status"); return -1; } if (tdav_session_mcptt_send_request(self, app) < 0) { TSK_DEBUG_ERROR("Error sending REQUEST"); return -1; } /* Start timer T101 */ mcptt->timer_t101.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t101.timeout, tdav_session_mcptt_timer_t101_expired_handler, mcptt); mcptt->counter_c101.curr_value = 1; mcptt->mcptt_status = mcptt_status_pending_request; tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_request_sent, tsk_null); return ret; } int tdav_session_mcptt_release_token (tmedia_session_mcptt_t* self, va_list *app) { tdav_session_mcptt_t* mcptt; int ret = 0; if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(mcptt->audio_session) //Stop RTP TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON. In case someone transmits TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; if (tdav_session_mcptt_send_release(self, app) < 0) { TSK_DEBUG_ERROR("Error sending RELEASE"); return -1; } mcptt->timer_t100.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t100.timeout, tdav_session_mcptt_timer_t100_expired_handler, mcptt); mcptt->counter_c100.curr_value = 1; if (mcptt->mcptt_status == mcptt_status_pending_request) { if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t101.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t101.id); mcptt->timer_t101.id = TSK_INVALID_TIMER_ID; } } if (mcptt->mcptt_status == mcptt_status_queued) { if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t104.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t104.id); mcptt->timer_t104.id = TSK_INVALID_TIMER_ID; } } mcptt->mcptt_status = mcptt_status_pending_release; tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_release_sent, tsk_null); return ret; } int tdav_session_mcptt_request_queue_position (tmedia_session_mcptt_t* self, va_list *app) { tdav_session_mcptt_t* mcptt; int ret = 0; if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(mcptt->audio_session) //Stop RTP TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON. In case someone transmits TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; if (tdav_session_mcptt_send_queue_position_request(self, app) < 0) { TSK_DEBUG_ERROR("Error sending QUEUE POSITION REQUEST"); return -1; } mcptt->timer_t104.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t100.timeout, tdav_session_mcptt_timer_t100_expired_handler, mcptt); mcptt->counter_c104.curr_value = 1; mcptt->mcptt_status = mcptt_status_queued; tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_queue_pos_request_sent, tsk_null); return ret; } int tdav_session_mcptt_send_request (tmedia_session_mcptt_t* self, va_list *app) { tdav_session_mcptt_t* mcptt; ======= /*tdav_session_mcptt_t* mcptt; >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a tmcptt_mcptt_packet_request_t* request_pkt; tsk_size_t rtcp_payload_size = 0; char* rtcp_payload = tsk_null; trtp_rtcp_report_app_t* rtcp_pkt; <<<<<<< HEAD ======= uint64_t ntp_now;*/ >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a int ret = 0; /* if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } request_pkt = tmcptt_mcptt_packet_request_create_null(); request_pkt->floor_priority = tmcptt_mcptt_packet_specific_binary_create_null(); request_pkt->floor_priority->f_id = FID_FLOOR_PRIORITY; request_pkt->floor_priority->f_length = 2; request_pkt->floor_priority->f_h_value = (uint8_t)mcptt->priority_response; request_pkt->floor_priority->f_l_value = 0; request_pkt->floor_indicator = tmcptt_mcptt_packet_specific_binary_16_create_null(); request_pkt->floor_indicator->f_id = FID_FLOOR_INDICATOR; request_pkt->floor_indicator->f_length = 2; request_pkt->floor_indicator->f_value = tdav_session_mcptt_get_floor_indicator(self); rtcp_payload_size = tmcptt_mcptt_packet_request_get_size(request_pkt); rtcp_payload = (char*)tsk_malloc(rtcp_payload_size*sizeof(char)); if(!rtcp_payload) return -1; tmcptt_mcptt_packet_request_serialize_to(request_pkt, rtcp_payload, rtcp_payload_size); rtcp_pkt = trtp_rtcp_report_app_create_2(MCPTT_PROTO_NAME, MCPTT_REQUEST, mcptt->local_ssrc, rtcp_payload, rtcp_payload_size); ret = tmcptt_manager_send_mcptt_packet(mcptt->mcptt_manager, rtcp_pkt); TSK_FREE(rtcp_payload); <<<<<<< HEAD ======= tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_request_sent, tsk_null); */ >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a return ret; } int tdav_session_mcptt_send_release (tmedia_session_mcptt_t* self, va_list *app) { tdav_session_mcptt_t* mcptt; tmcptt_mcptt_packet_release_t* release_pkt; tsk_size_t rtcp_payload_size = 0; char* rtcp_payload = tsk_null; trtp_rtcp_report_app_t* rtcp_pkt; uint32_t ssrc = 0; int ret = 0; if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(mcptt->audio_session) //Stop RTP TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON. In case someone transmits TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; release_pkt = tmcptt_mcptt_packet_release_create_null(); release_pkt->floor_indicator = tmcptt_mcptt_packet_specific_binary_16_create_null(); release_pkt->floor_indicator->f_id = FID_FLOOR_INDICATOR; release_pkt->floor_indicator->f_length = 2; release_pkt->floor_indicator->f_value = tdav_session_mcptt_get_floor_indicator(self); rtcp_payload_size = tmcptt_mcptt_packet_release_get_size(release_pkt); rtcp_payload = (char*)tsk_malloc(rtcp_payload_size*sizeof(char)); if(!rtcp_payload) return -1; tmcptt_mcptt_packet_release_serialize_to(release_pkt, rtcp_payload, rtcp_payload_size); rtcp_pkt = trtp_rtcp_report_app_create_2(MCPTT_PROTO_NAME, MCPTT_RELEASE, mcptt->local_ssrc, rtcp_payload, rtcp_payload_size); ret = tmcptt_manager_send_mcptt_packet(mcptt->mcptt_manager, rtcp_pkt); TSK_FREE(rtcp_payload); return ret; } int tdav_session_mcptt_send_ack (tmedia_session_mcptt_t* self, tmcptt_mcptt_packet_type_t type, va_list *app) { /*tdav_session_mcptt_t* mcptt; tmcptt_mcptt_packet_ack_t* ack_pkt; tsk_size_t rtcp_payload_size = 0; char* rtcp_payload = tsk_null; trtp_rtcp_report_app_t* rtcp_pkt; uint32_t ssrc = 0; */ int ret = 0; /* if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } ack_pkt = tmcptt_mcptt_packet_ack_create(FLR_SOURCE_PARTICIPANT, type); rtcp_payload_size = tmcptt_mcptt_packet_ack_get_size(ack_pkt); rtcp_payload = (char*)tsk_malloc(rtcp_payload_size*sizeof(char)); if(!rtcp_payload) return -1; tmcptt_mcptt_packet_ack_serialize_to(ack_pkt, rtcp_payload, rtcp_payload_size); rtcp_pkt = trtp_rtcp_report_app_create_2(MCPTT_PROTO_NAME, MCPTT_ACK, mcptt->local_ssrc, rtcp_payload, rtcp_payload_size); ret = tmcptt_manager_send_mcptt_packet(mcptt->mcptt_manager, rtcp_pkt); TSK_FREE(rtcp_payload); <<<<<<< HEAD return ret; } int tdav_session_mcptt_send_queue_position_request (tmedia_session_mcptt_t* self, va_list *app) { tdav_session_mcptt_t* mcptt; tmcptt_mcptt_packet_queue_position_request_t* queue_pos_req_pkt; tsk_size_t rtcp_payload_size = 0; char* rtcp_payload = tsk_null; trtp_rtcp_report_app_t* rtcp_pkt; uint32_t ssrc = 0; int ret = 0; if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (mcptt->mcptt_status != mcptt_status_queued) { TSK_DEBUG_ERROR("Invalid MCPTT status"); return -1; } queue_pos_req_pkt = tmcptt_mcptt_packet_queue_position_request_create_null(); rtcp_payload_size = tmcptt_mcptt_packet_queue_position_request_get_size(queue_pos_req_pkt); rtcp_payload = (char*)tsk_malloc(rtcp_payload_size*sizeof(char)); if(!rtcp_payload) return -1; tmcptt_mcptt_packet_queue_position_request_serialize_to(queue_pos_req_pkt, rtcp_payload, rtcp_payload_size); rtcp_pkt = trtp_rtcp_report_app_create_2(MCPTT_PROTO_NAME, MCPTT_QUEUE_POS_REQ, mcptt->local_ssrc, rtcp_payload, rtcp_payload_size); ret = tmcptt_manager_send_mcptt_packet(mcptt->mcptt_manager, rtcp_pkt); TSK_FREE(rtcp_payload); ======= tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_taken_acknowledged, tsk_null); */ >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a return ret; } uint16_t tdav_session_mcptt_get_floor_indicator(tmedia_session_mcptt_t* self) { //tdav_session_mcptt_t* mcptt; uint16_t floor_indicator = 0; /* if(!(mcptt = (tdav_session_mcptt_t*)self)){ TSK_DEBUG_ERROR("Invalid parameter"); return 0; } if (mcptt->session_type == mcptt_session_type_private || mcptt->session_type == mcptt_session_type_group_prearranged || mcptt->session_type == mcptt_session_type_group_chat) floor_indicator = FLR_IND_NORMAL_CALL; if (mcptt->is_broadcast == tsk_true) floor_indicator = FLR_IND_BROADCAST_GRP_CALL; if (mcptt->is_emergency == tsk_true) floor_indicator |= FLR_IND_EMERGENCY_CALL; if (mcptt->is_imminent_peril == tsk_true) floor_indicator |= FLR_IND_IMMINENT_PERIL_CALL; if (mcptt->queueing_enabled == tsk_true) floor_indicator |= FLR_IND_QUEUEING_SUPPORTED; <<<<<<< HEAD if (mcptt->is_dual_floor == tsk_true) floor_indicator |= FLR_IND_DUAL_FLOOR; ======= */ >>>>>>> 3786611ddac22a4cb96f1767a972e3ad4f4aa13a return floor_indicator; } int tdav_session_mcptt_process_taken(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_taken_t* taken_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); if (mcptt == tsk_null) return -1; if (taken_msg == tsk_null) return -1; if (taken_msg->granted_party_id) { TSK_DEBUG_INFO("MCPTT TAKEN client name: %.*s", taken_msg->granted_party_id->f_length, taken_msg->granted_party_id->f_value); msg->user = (char*)tsk_malloc((taken_msg->granted_party_id->f_length + 1) * sizeof(char)); memcpy(msg->user, taken_msg->granted_party_id->f_value, taken_msg->granted_party_id->f_length * sizeof(char)); msg->user[taken_msg->granted_party_id->f_length] = '\0'; } if ((taken_msg->floor_indicator->f_value & FLR_IND_BROADCAST_GRP_CALL) == FLR_IND_BROADCAST_GRP_CALL) msg->is_broadcast_call = tsk_true; switch (mcptt->mcptt_status) { case mcptt_status_no_permission: { if (msg->is_broadcast_call) tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_taken, msg); /* Cannot start timer T103 (End of RTP media). Cannot access RTP packet reception function */ // mcptt->timer_t103.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t103.timeout, tdav_session_mcptt_timer_t103_expired_handler, mcptt); break; } case mcptt_status_pending_request: { if (tsk_strcmp(taken_msg->granted_party_id->f_value, mcptt->local_mcptt_id) != 0) { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_taken, msg); if(mcptt->audio_session) //Stop RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; } if (mcptt->queueing_enabled == tsk_false) { if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t101.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t101.id); mcptt->timer_t101.id = TSK_INVALID_TIMER_ID; } /* Cannot start timer T103 (End of RTP media) */ //mcptt->timer_t103.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t103.timeout, tdav_session_mcptt_timer_t103_expired_handler, mcptt); mcptt->mcptt_status = mcptt_status_no_permission; } } break; } case mcptt_status_pending_release: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_taken, msg); //Start timer T103?? if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t100.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t100.id); mcptt->timer_t100.id = TSK_INVALID_TIMER_ID; } mcptt->mcptt_status = mcptt_status_no_permission; break; } case mcptt_status_queued: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_taken, msg); break; } } return 0; } int tdav_session_mcptt_process_idle(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_idle_t* idle_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); if (mcptt == tsk_null) return -1; if (idle_msg == tsk_null) return -1; if(idle_msg->message_seq_num) TSK_DEBUG_INFO("MCPTT IDLE seq num: %u", idle_msg->message_seq_num->f_value); if ((idle_msg->floor_indicator->f_value & FLR_IND_BROADCAST_GRP_CALL) == FLR_IND_BROADCAST_GRP_CALL) msg->is_broadcast_call = tsk_true; switch (mcptt->mcptt_status) { case mcptt_status_no_permission: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_idle_channel, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t103.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t103.id); mcptt->timer_t103.id = TSK_INVALID_TIMER_ID; } break; } case mcptt_status_pending_release: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_idle_channel, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t100.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t100.id); mcptt->timer_t100.id = TSK_INVALID_TIMER_ID; } if (!msg->is_broadcast_call || (idle_msg->floor_indicator->f_value & FLR_IND_NORMAL_CALL) == FLR_IND_NORMAL_CALL) mcptt->mcptt_status = mcptt_status_no_permission; if (msg->is_broadcast_call) mcptt->mcptt_status = mcptt_status_releasing; break; } case mcptt_status_queued: { mcptt->mcptt_status = mcptt_status_no_permission; break; } } return 0; } int tdav_session_mcptt_process_granted(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_granted_t* granted_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); if (mcptt == tsk_null) return -1; if (granted_msg == tsk_null) return -1; if (granted_msg->duration) { TSK_DEBUG_INFO("MCPTT GRANTED duration: %u", granted_msg->duration->f_value); msg->time = granted_msg->duration->f_value; } if (granted_msg->floor_priority) TSK_DEBUG_INFO("MCPTT GRANTED priority: %u", granted_msg->floor_priority->f_h_value); if ((granted_msg->floor_indicator->f_value & FLR_IND_BROADCAST_GRP_CALL) == FLR_IND_BROADCAST_GRP_CALL) msg->is_broadcast_call = tsk_true; if ((granted_msg->floor_indicator->f_value & FLR_IND_DUAL_FLOOR) == FLR_IND_DUAL_FLOOR) mcptt->is_dual_floor = tsk_true; switch (mcptt->mcptt_status) { case mcptt_status_pending_request: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_granted, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t103.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t103.id); mcptt->timer_t103.id = TSK_INVALID_TIMER_ID; } if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t101.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t101.id); mcptt->timer_t101.id = TSK_INVALID_TIMER_ID; } mcptt->mcptt_status = mcptt_status_permission; if(mcptt->audio_session) //Start RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_false; if(mcptt->multicast_audio_session) //Multicast channel OFF. We should not hear ourselves { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_true; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; //Just unicast uplink stream } break; } case mcptt_status_queued: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_granted, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t104.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t104.id); mcptt->timer_t104.id = TSK_INVALID_TIMER_ID; } mcptt->timer_t132.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t132.timeout, tdav_session_mcptt_timer_t132_expired_handler, mcptt); mcptt->mcptt_status = mcptt_status_permission; if(mcptt->audio_session) //Start RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_false; if(mcptt->multicast_audio_session) //Multicast channel OFF. We should not hear ourselves { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_true; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; //Just unicast uplink stream } break; } } return 0; } int tdav_session_mcptt_process_deny(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_deny_t* deny_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); tsk_size_t size = 0; if (mcptt == tsk_null) return -1; if (deny_msg == tsk_null) return -1; if (deny_msg->reject_cause) TSK_DEBUG_INFO("MCPTT DENY reject cause: %u (%s)", deny_msg->reject_cause->f_bin_value, deny_msg->reject_cause->f_txt_value); msg->reason_code = deny_msg->reject_cause->f_bin_value; size = deny_msg->reject_cause->f_length - sizeof(uint16_t); if (size > 0) { msg->reason_phrase = (char*)tsk_malloc((size + 1) * sizeof(char)); memcpy(msg->reason_phrase, deny_msg->reject_cause, size); msg->reason_phrase[size] = '\0'; } switch (mcptt->mcptt_status) { case mcptt_status_pending_request: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_denied, msg); /* Stop timer T101 (Floor request) */ if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t101.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t101.id); mcptt->timer_t101.id = TSK_INVALID_TIMER_ID; } mcptt->mcptt_status = mcptt_status_no_permission; if(mcptt->audio_session) //Stop RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; } break; } case mcptt_status_queued: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_token_denied, msg); /* Stop timer T104 (Floor queue position request) */ if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t104.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t104.id); mcptt->timer_t104.id = TSK_INVALID_TIMER_ID; } mcptt->mcptt_status = mcptt_status_no_permission; if(mcptt->audio_session) //Stop RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; } break; } } return 0; } int tdav_session_mcptt_process_revoke(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_revoke_t* revoke_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); tsk_size_t size = 0; va_list ap; if (mcptt == tsk_null) return -1; if (revoke_msg == tsk_null) return -1; if (revoke_msg->reject_cause) TSK_DEBUG_INFO("MCPTT REVOKE reject cause: %u (%s)", revoke_msg->reject_cause->f_bin_value, revoke_msg->reject_cause->f_txt_value); msg->reason_code = revoke_msg->reject_cause->f_bin_value; size = revoke_msg->reject_cause->f_length - sizeof(uint16_t); if (size > 0) { msg->reason_phrase = (char*)tsk_malloc((size + 1) * sizeof(char)); memcpy(msg->reason_phrase, revoke_msg->reject_cause, size); msg->reason_phrase[size] = '\0'; } switch (mcptt->mcptt_status) { case mcptt_status_permission: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_permission_revoked, msg); va_start(ap, "token"); tdav_session_mcptt_send_release(TMEDIA_SESSION_MCPTT(mcptt), &ap); va_end(ap); mcptt->timer_t100.id = tsk_timer_manager_schedule(mcptt->h_timer, mcptt->timer_t100.timeout, tdav_session_mcptt_timer_t100_expired_handler, mcptt); mcptt->counter_c100.curr_value = 1; mcptt->mcptt_status = mcptt_status_pending_release; if(mcptt->audio_session) //Stop RTP transmission TMEDIA_SESSION(mcptt->audio_session)->lo_held = tsk_true; if(mcptt->multicast_audio_session) //Multicast channel ON { TMEDIA_SESSION(mcptt->multicast_audio_session)->ro_held = tsk_false; TMEDIA_SESSION(mcptt->multicast_audio_session)->lo_held = tsk_true; } break; } case mcptt_status_pending_release: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_permission_revoked, msg); break; } } return 0; } int tdav_session_mcptt_process_queue_position_info(tdav_session_mcptt_t* mcptt, tmcptt_mcptt_packet_queue_position_info_t* queue_position_info_msg) { tmcptt_message_t* msg = tmcptt_message_create_null(); tsk_size_t size = 0; if (mcptt == tsk_null) return -1; if (queue_position_info_msg == tsk_null) return -1; if (queue_position_info_msg->queue_info) TSK_DEBUG_INFO("MCPTT QUEUE POSITION INFO : position: %u, priority: %u", queue_position_info_msg->queue_info->f_h_value, queue_position_info_msg->queue_info->f_l_value); msg->queue_position = queue_position_info_msg->queue_info->f_h_value; msg->queue_priority = queue_position_info_msg->queue_info->f_l_value; switch (mcptt->mcptt_status) { case mcptt_status_pending_request: { tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_queued, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t104.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t104.id); mcptt->timer_t104.id = TSK_INVALID_TIMER_ID; } mcptt->mcptt_status = mcptt_status_queued; break; } case mcptt_status_queued: { /* If queue position info == 65534, MCPTT client is not queued * If queue position info == 65535, MCPTT server unable to determine position */ if (!(msg->queue_position == 255 && msg->queue_priority == 254)) //If client is queued tdav_session_mcptt_alert_user(mcptt, tmcptt_event_type_queued, msg); if (TSK_TIMER_ID_IS_VALID(mcptt->timer_t104.id)) { tsk_timer_manager_cancel(mcptt->h_timer, mcptt->timer_t104.id); mcptt->timer_t104.id = TSK_INVALID_TIMER_ID; } break; } } return 0; } /*Constructor*/ static tsk_object_t* tdav_session_mcptt_ctor(tsk_object_t * self, va_list * app) { tdav_session_mcptt_t *session = self; if(session){ TMEDIA_SESSION_MCPTT(session)->request_token = tdav_session_mcptt_request_token; TMEDIA_SESSION_MCPTT(session)->release_token = tdav_session_mcptt_release_token; session->floorid = 0; session->is_multimedia = tsk_true; session->local_ip = tsk_null; session->local_port = 0; session->remote_ip = tsk_null; session->remote_port = 0; session->local_ssrc = 0; session->mcptt_status = mcptt_status_start_stop; session->is_broadcast = tsk_false; session->is_emergency = tsk_false; session->is_imminent_peril = tsk_false; session->is_dual_floor = tsk_false; session->queueing_enabled = tsk_false; if(!(session->h_timer = tsk_timer_manager_create())){ TSK_DEBUG_ERROR("Failed to create timer manager"); return tsk_null; } session->timer_t100.id = TSK_INVALID_TIMER_ID; session->timer_t100.timeout = MCPTT_TIMER_T100_DEFAULT_VALUE; session->timer_t101.id = TSK_INVALID_TIMER_ID; session->timer_t101.timeout = MCPTT_TIMER_T101_DEFAULT_VALUE; session->timer_t103.id = TSK_INVALID_TIMER_ID; session->timer_t103.timeout = MCPTT_TIMER_T103_DEFAULT_VALUE; session->timer_t104.id = TSK_INVALID_TIMER_ID; session->timer_t104.timeout = MCPTT_TIMER_T103_DEFAULT_VALUE; session->timer_t132.id = TSK_INVALID_TIMER_ID; session->timer_t132.timeout = MCPTT_TIMER_T132_DEFAULT_VALUE; session->counter_c100.curr_value = 1; session->counter_c100.max_value = MCPTT_COUNTER_C100_DEFAULT_VALUE; session->counter_c101.curr_value = 1; session->counter_c101.max_value = MCPTT_COUNTER_C101_DEFAULT_VALUE; session->counter_c104.curr_value = 1; session->counter_c104.max_value = MCPTT_COUNTER_C104_DEFAULT_VALUE; } return self; } /* destructor */ static tsk_object_t* tdav_session_mcptt_dtor(tsk_object_t * self) { tdav_session_mcptt_t *session = self; if(session){ if(session->remote_ip) TSK_FREE(session->remote_ip); /* deinit base */ tmedia_session_deinit(self); } return self; } /* object definition */ static const tsk_object_def_t tdav_session_mcptt_def_s = { sizeof(tdav_session_mcptt_t), tdav_session_mcptt_ctor, tdav_session_mcptt_dtor, tmedia_session_cmp, }; /* plugin definition*/ static const tmedia_session_plugin_def_t tdav_session_mcptt_plugin_def_s = { &tdav_session_mcptt_def_s, tmedia_mcptt, "application", tdav_session_mcptt_set, tdav_session_mcptt_get, tdav_session_mcptt_prepare, tdav_session_mcptt_start, tdav_session_mcptt_pause, tdav_session_mcptt_stop, /* Audio part */ { tsk_null }, tdav_session_mcptt_get_lo, tdav_session_mcptt_set_ro }; const tmedia_session_plugin_def_t *tdav_session_mcptt_plugin_def_t = &tdav_session_mcptt_plugin_def_s; #endif /* !defined(HAVE_TINYMSRP) || HAVE_TINYMSRP */