void AmZRTP::on_zrtp_protocol_event(zrtp_stream_t *stream, zrtp_protocol_event_t event) { DBG("on_zrtp_protocol_event(stream [%p])\n", stream); if (NULL==stream) { ERROR("event received without stream context.\n"); return; } void* udata = zrtp_stream_get_userdata(stream); if (NULL == udata) { ERROR("ZRTP on_send_packet without session set context.\n"); return; } AmSession* sess = reinterpret_cast<AmSession*>(udata); sess->postEvent(new AmZRTPProtocolEvent(event, stream)); }
void AmSessionContainer::startSessionUAS(AmSipRequest& req) { as_mut.lock(); try { AmSession* session = getSession(req.callid,req.from_tag); if( session ){ // it's a forked-and-merged INVITE // reply 482 Loop detected throw AmSession::Exception(482, "Loop detected"); } else { // Call-ID and From-Tag are unknown: it's a new session AmSession* session; if((session = createSession(req)) != 0){ // update session's local tag (ID) if not already set session->setLocalTag(); const string& local_tag = session->getLocalTag(); // by default each session is in its own callgroup session->setCallgroup(local_tag); if (AmConfig::LogSessions) { INFO("Starting UAS session %s app %s\n", session->getLocalTag().c_str(), req.cmd.c_str()); } session->start(); addSession_unsafe(req.callid,req.from_tag,local_tag,session); session->postEvent(new AmSipRequestEvent(req)); } } } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); }
void zrtp_event_callback(zrtp_event_t event, zrtp_stream_ctx_t *stream_ctx) { if (NULL==stream_ctx) { ERROR("event received without stream context.\n"); return; } AmSession* sess = reinterpret_cast<AmSession*>(stream_ctx->stream_usr_data); if (NULL==sess) { ERROR("event received without session set up.\n"); return; } sess->postEvent(new AmZRTPEvent(event, stream_ctx)); }
void AmSessionContainer::startSessionUAS(AmSipRequest& req) { as_mut.lock(); try { AmSession* session = getSession(req.callid,req.from_tag); if( session ){ // it's a forked-and-merged INVITE // reply 482 Loop detected throw AmSession::Exception(482, "Loop detected"); } else { // Call-ID and From-Tag are unknown: it's a new session AmSession* session; if((session = createSession(req)) != 0){ string local_tag = AmSession::getNewId(); session->setLocalTag(local_tag); session->setCallgroup(local_tag); session->start(); addSession_unsafe(req.callid,req.from_tag,local_tag,session); session->postEvent(new AmSipRequestEvent(req)); } //else //throw AmSession::Exception(500,"internal error"); } } // catch(const AmSession::SessionTimerException& e){ // ERROR("%i %s\n",e.code,e.reason.c_str()); // AmSipDialog::reply_error(req,e.code,e.reason,e.getErrorHeaders()); // } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); AmSipDialog::reply_error(req,e.code,e.reason); } catch(const string& err){ ERROR("startSession: %s\n",err.c_str()); AmSipDialog::reply_error(req,500,err); } catch(...){ ERROR("unexpected exception\n"); AmSipDialog::reply_error(req,500,"unexpected exception"); } as_mut.unlock(); }
bool AmSessionContainer::postEvent(const string& callid, const string& remote_tag, AmEvent* event) { // DBG("postEvent: callid = %s; remote_tag = %s\n", // callid.c_str(),remote_tag.c_str()); as_mut.lock(); AmSession* s = getSession(callid,remote_tag); as_mut.unlock(); if(!s){ delete event; return false; } s->postEvent(event); return true; }
bool AmSessionContainer::postEvent(const string& local_tag, AmEvent* event) { // DBG("postEvent: local_tag = %s\n",local_tag.c_str()); as_mut.lock(); AmSession* s = getSession(local_tag); as_mut.unlock(); if (s != NULL) { s->postEvent(event); return true; } // try session factories AmSessionFactory* sf = AmPlugIn::instance()->getFactory4App(local_tag); if (sf != NULL) { sf->postEvent(event); return true; } delete event; return false; }
void AmMediaProcessorThread::processAudio(unsigned int ts) { for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* input = s->getInput(); if(s->rtp_str.checkInterval(ts)){ //DBG("ts = %u\n",ts); int ret = s->rtp_str.receive(ts); if(ret < 0){ switch(ret){ case RTP_DTMF: case RTP_UNKNOWN_PL: case RTP_PARSE_ERROR: break; case RTP_TIMEOUT: postRequest(new SchedRequest(AmMediaProcessor::RemoveSession,s)); s->postEvent(new AmRtpTimeoutEvent()); break; case RTP_BUFFER_SIZE: default: ERROR("AmRtpAudio::receive() returned %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); break; } } else { unsigned int f_size = s->rtp_str.getFrameSize(); int size = s->rtp_str.get(ts,buffer,f_size); if (input) { int ret = input->put(ts,buffer,size); if(ret < 0){ DBG("input->put() returned: %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } if (s->isDtmfDetectionEnabled()) s->putDtmfAudio(buffer, size, ts); } } s->unlockAudio(); } for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* output = s->getOutput(); if(output && s->rtp_str.sendIntReached()){ int size = output->get(ts,buffer,s->rtp_str.getFrameSize()); if(size <= 0){ DBG("output->get() returned: %i\n",size); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); //removeSession(s); } else if(!s->rtp_str.mute){ if(s->rtp_str.put(ts,buffer,size)<0) postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); // removeSession(s); } } s->unlockAudio(); } }
void AmMediaProcessorThread::processAudio(unsigned int ts) { // receiving for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); // todo: get frame size/checkInterval from local audio if local in+out (?) unsigned int frame_length = s->rtp_str.getFrameLength(); // ms // complete frame time reached? if (s->rtp_str.checkInterval(ts)) { s->lockAudio(); int rcvd_audio_len = -1; // get/receive audio if (!s->getAudioLocal(AM_AUDIO_IN)) { // input is not local - receive from rtp stream if (s->rtp_str.receiving || s->rtp_str.getPassiveMode()) { int ret = s->rtp_str.receive(ts); if(ret < 0){ switch(ret){ case RTP_DTMF: case RTP_UNKNOWN_PL: case RTP_PARSE_ERROR: break; case RTP_TIMEOUT: postRequest(new SchedRequest(AmMediaProcessor::RemoveSession,s)); s->postEvent(new AmRtpTimeoutEvent()); break; case RTP_BUFFER_SIZE: default: ERROR("AmRtpAudio::receive() returned %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); break; } } else { rcvd_audio_len = s->rtp_str.get(ts,buffer,frame_length); if (s->isDtmfDetectionEnabled() && rcvd_audio_len > 0) s->putDtmfAudio(buffer, rcvd_audio_len, ts); } } } else { // input is local - get audio from local_in AmAudio* local_input = s->getLocalInput(); if (local_input) { rcvd_audio_len = local_input->get(ts,buffer,frame_length); } } // process received audio if (rcvd_audio_len >= 0) { AmAudio* input = s->getInput(); if (input) { int ret = input->put(ts,buffer,rcvd_audio_len); if(ret < 0){ DBG("input->put() returned: %i\n",ret); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } } s->unlockAudio(); } } // sending for(set<AmSession*>::iterator it = sessions.begin(); it != sessions.end(); it++){ AmSession* s = (*it); s->lockAudio(); AmAudio* output = s->getOutput(); if(output && s->rtp_str.sendIntReached()){ unsigned int frame_length = s->rtp_str.getFrameLength(); int size = output->get(ts,buffer,frame_length); if(size <= 0){ DBG("output->get() returned: %i\n",size); postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } else { if (!s->getAudioLocal(AM_AUDIO_OUT)) { // audio should go to RTP if(!s->rtp_str.mute){ if(s->rtp_str.put(ts,buffer,size)<0) postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } else { // output is local - audio should go in local_out AmAudio* local_output = s->getLocalOutput(); if (local_output) { if (local_output->put(ts,buffer,size)) { postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s)); } } } } } s->unlockAudio(); } }