void WebConferenceDialog::connectConference(const string& room) {
  // set the conference id ('conference room') 
  conf_id = room;

  // disconnect in/out for safety 
  setInOut(NULL, NULL);

  // we need to be in the same callgroup as the other 
  // people in the conference (important if we have multiple
  // MediaProcessor threads
  changeCallgroup(conf_id);

  // get a channel from the status 
  if (channel.get() == NULL) 
    channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag()));
  else 
    AmConferenceStatus::postConferenceEvent(conf_id,
					    ConfNewParticipant,getLocalTag());

  // clear the playlist
  play_list.close();

  // add the channel to our playlist
  play_list.addToPlaylist(new AmPlaylistItem(channel.get(),
					     channel.get()));

  // set the playlist as output and input 
  if (muted)
    setInOut(NULL, &play_list);  
  else
    setInOut(&play_list,&play_list);

}
void AnswerMachineDialog::process(AmEvent* event)
{
    AmAudioEvent* ae = dynamic_cast<AmAudioEvent*>(event);
    if(ae){

	switch(ae->event_id){

	case AmAudioEvent::noAudio:

	    switch(status){

	    case 0:
		playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));
		
		{AmArgArray di_args,ret;
		di_args.push(RECORD_TIMER);
		di_args.push(AnswerMachineFactory::MaxRecordTime);
		di_args.push(getLocalTag().c_str());

		user_timer->invoke("setTimer",di_args,ret);}
		status = 1;
		break;

	    case 1:
		a_beep.rewind();
		playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
		status = 2;
		break;

	    case 2:
		dlg.bye();
		sendMailNotification();
		setStopped();
		break;

	    }
	    break;

	case AmAudioEvent::cleared:
	    DBG("AmAudioEvent::cleared\n");
	    break;

	default:
	    DBG("Unknown event id %i\n",ae->event_id);
	    break;
	}

	return;
    }

    AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event);
    if(plugin_event && plugin_event->name == "timer_timeout" &&
       plugin_event->data.get(0).asInt() == RECORD_TIMER) {

	    // clear list
	    playlist.close();
    }
    else
	AmSession::process(event);
}
void AmB2BCalleeSession::onB2BEvent(B2BEvent* ev)
{
  if(ev->event_id == B2BConnectLeg){
    B2BConnectEvent* co_ev = dynamic_cast<B2BConnectEvent*>(ev);
    if (!co_ev)
      return;

    MONITORING_LOG3(getLocalTag().c_str(), 
		    "b2b_leg", other_id.c_str(),
		    "to", co_ev->remote_party.c_str(),
		    "ruri", co_ev->remote_uri.c_str());


    dlg.remote_party = co_ev->remote_party;
    dlg.remote_uri   = co_ev->remote_uri;

    if (co_ev->relayed_invite) {
      relayed_req[dlg.cseq] = AmSipTransaction("INVITE", co_ev->r_cseq);
    }

    dlg.sendRequest("INVITE",co_ev->content_type,co_ev->body,co_ev->hdrs,SIP_FLAGS_VERBATIM);

    return;
  }    

  AmB2BSession::onB2BEvent(ev);
}
Beispiel #4
0
bool AmSession::removeTimer(int timer_id) {

  DBG("removing timer %d\n", timer_id);
  AmAppTimer::instance()->removeTimer(getLocalTag(), timer_id);

  return true;
}
Beispiel #5
0
bool AmSession::removeTimers() {

  DBG("removing timers\n");
  AmAppTimer::instance()->removeTimers(getLocalTag());

  return true;
}
void WebConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status) 
{
  //int status = dlg.getStatus();

  AmSession::onSipReply(reply,old_dlg_status);

  if ((old_dlg_status < AmSipDialog::Connected) && 
      (dlg.getStatus() == AmSipDialog::Disconnected)) {
    DBG("Call failed.\n");
    setStopped();
  }

  // update status to map
  if (is_dialout) {
    // map AmSipDialog state to WebConferenceState
    ConferenceRoomParticipant::ParticipantStatus rep_st = 
      ConferenceRoomParticipant::Connecting;
    switch (dlg.getStatus()) {
    case AmSipDialog::Pending: {
      rep_st = ConferenceRoomParticipant::Connecting;
      if (reply.code == 180) 
	rep_st  = ConferenceRoomParticipant::Ringing;
    } break;
    case AmSipDialog::Connected: 
      rep_st = ConferenceRoomParticipant::Connected; break;
    case AmSipDialog::Disconnecting: 
      rep_st = ConferenceRoomParticipant::Disconnecting; break;    
    case AmSipDialog::Disconnected: 
      rep_st = ConferenceRoomParticipant::Finished; break;    
    }
    DBG("is dialout: updateing status\n");
    factory->updateStatus(dlg.user, getLocalTag(), 
			  rep_st, int2str(reply.code) + " " + reply.reason);
  }
}
Beispiel #7
0
void AmB2BSession::setRtpRelayMode(RTPRelayMode mode)
{
  DBG("enabled RTP relay mode for B2B call '%s'\n",
      getLocalTag().c_str());

  rtp_relay_mode = mode;
}
void ConferenceDialog::setupAudio()
{
  if(!ConferenceFactory::JoinSound.empty()) {
	
    JoinSound.reset(new AmAudioFile());
    if(JoinSound->open(ConferenceFactory::JoinSound,
		       AmAudioFile::Read))
      JoinSound.reset(0);
  }

  if(!ConferenceFactory::DropSound.empty()) {
	
    DropSound.reset(new AmAudioFile());
    if(DropSound->open(ConferenceFactory::DropSound,
		       AmAudioFile::Read))
      DropSound.reset(0);
  }


  play_list.close();// !!!

  if(dialout_channel.get()){

    DBG("adding dialout_channel to the playlist (dialedout = %i)\n",dialedout);
    play_list.addToPlaylist(new AmPlaylistItem(dialout_channel.get(),
					       dialout_channel.get()));
  }
  else {

    channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag()));

    play_list.addToPlaylist(new AmPlaylistItem(channel.get(),
					       channel.get()));
  }

  setInOut(&play_list,&play_list);
    
  setCallgroup(conf_id);
  
  MONITORING_LOG(getLocalTag().c_str(), "conf_id", conf_id.c_str());
	
  if(dialedout || !allow_dialout) {
    DBG("Dialout not enabled or dialout channel. Disabling DTMF detection.\n");
    setDtmfDetectionEnabled(false);
  }
}
Beispiel #9
0
void AmSession::setStopped(bool wakeup) {
  if (!sess_stopped.get()) {
    sess_stopped.set(true); 
    onStop();
  }
  if (wakeup) 
    AmSessionContainer::instance()->postEvent(getLocalTag(), 
					      new AmEvent(0));
}
void WebConferenceDialog::onKicked() {
  DBG("########## WebConference::onKick #########\n");
  dlg.bye(); 
  disconnectConference();
  factory->updateStatus(conf_id, 
			getLocalTag(), 
			ConferenceRoomParticipant::Disconnecting,
			"disconnect");
}
Beispiel #11
0
void AmB2BCalleeSession::onB2BEvent(B2BEvent* ev)
{
  if(ev->event_id == B2BConnectLeg){
    B2BConnectEvent* co_ev = dynamic_cast<B2BConnectEvent*>(ev);
    if (!co_ev)
      return;

    MONITORING_LOG3(getLocalTag().c_str(), 
		    "b2b_leg", getOtherId().c_str(),
		    "to", co_ev->remote_party.c_str(),
		    "ruri", co_ev->remote_uri.c_str());


    dlg->setRemoteParty(co_ev->remote_party);
    dlg->setRemoteUri(co_ev->remote_uri);

    if (co_ev->relayed_invite) {
      AmSipRequest fake_req;
      fake_req.method = SIP_METH_INVITE;
      fake_req.cseq = co_ev->r_cseq;
      relayed_req[dlg->cseq] = fake_req;
    }

    AmMimeBody body(co_ev->body);
    try {
      updateLocalBody(body);
    } catch (const string& s) {
      relayError(SIP_METH_INVITE, co_ev->r_cseq, co_ev->relayed_invite, 500, 
          SIP_REPLY_SERVER_INTERNAL_ERROR);
      throw;
    }

    int res = dlg->sendRequest(SIP_METH_INVITE, &body,
			co_ev->hdrs, SIP_FLAGS_VERBATIM);
    if (res < 0) {
      DBG("sending INVITE failed, relaying back error reply\n");
      relayError(SIP_METH_INVITE, co_ev->r_cseq, co_ev->relayed_invite, res);

      if (co_ev->relayed_invite)
	relayed_req.erase(dlg->cseq);

      setStopped();
      return;
    }

    saveSessionDescription(co_ev->body);

    // save CSeq of establising INVITE
    est_invite_cseq = dlg->cseq - 1;
    est_invite_other_cseq = co_ev->r_cseq;

    return;
  }    

  AmB2BSession::onB2BEvent(ev);
}
void ConferenceDialog::createDialoutParticipant(const string& uri_user)
{
  string uri;

  uri = "sip:" + uri_user + dialout_suffix;

  dialout_channel.reset(AmConferenceStatus::getChannel(getLocalTag(),getLocalTag()));

  dialout_id = AmSession::getNewId();
    
  ConferenceDialog* dialout_session = 
    new ConferenceDialog(conf_id,
			 AmConferenceStatus::getChannel(getLocalTag(),
							dialout_id));

  AmSipDialog& dialout_dlg = dialout_session->dlg;

  dialout_dlg.local_tag    = dialout_id;
  dialout_dlg.callid       = AmSession::getNewId() + "@" + AmConfig::LocalIP;

  if (from_header.length() > 0) {
    dialout_dlg.local_party  = from_header;
  } else {
    dialout_dlg.local_party  = dlg.local_party;
  }
  dialout_dlg.remote_party = uri;
  dialout_dlg.remote_uri   = uri;

  string body;
  int local_port = dialout_session->rtp_str.getLocalPort();
  dialout_session->sdp.genRequest(AmConfig::LocalIP,local_port,body);

  if (extra_headers.length() == 0) {
    extra_headers = "";
  }

  dialout_dlg.sendRequest("INVITE","application/sdp",body,extra_headers);

  dialout_session->start();

  AmSessionContainer* sess_cont = AmSessionContainer::instance();
  sess_cont->addSession(dialout_id,dialout_session);
}
void WebConferenceDialog::onSessionStart(const AmSipRequest& req) { 
  // direct room access?
  if (conf_id.empty()) {
    state = EnteringPin;    
    prompts.addToPlaylist(ENTER_PIN,  (long)this, play_list);
    // set the playlist as input and output
    setInOut(&play_list,&play_list);
  } else {
    DBG("########## direct connect conference #########\n"); 
    factory->newParticipant(conf_id, 
			    getLocalTag(), 
			    dlg.remote_party);
    factory->updateStatus(conf_id, 
			  getLocalTag(), 
			  ConferenceRoomParticipant::Connected,
			  "direct access: entered");
    state = InConference;
    connectConference(conf_id);
  }
}
void WebConferenceDialog::onBye(const AmSipRequest& req)
{
  if (InConference == state) {
    factory->updateStatus(conf_id, 
			  getLocalTag(), 
			  ConferenceRoomParticipant::Disconnecting,
			  req.method);
  }

  disconnectConference();
}
WebConferenceDialog::~WebConferenceDialog()
{
  prompts.cleanup((long)this);
  play_list.close(false);
  if (is_dialout || (InConference == state)) {
    factory->updateStatus(is_dialout?dlg.user:conf_id, 
			  getLocalTag(), 
			  ConferenceRoomParticipant::Finished,
			  "");
  }
}
void EarlyRecordDialog::onEarlySessionStart(const AmSipReply& req) {
  DBG("Early Session Start\n");
  msg_filename = "/tmp/" + getLocalTag() + ".wav";
  
  if(a_msg.open(msg_filename,AmAudioFile::Write,false))
    throw string("EarlyRecordDialog: couldn't open ") + 
      msg_filename + string(" for writing");
  
  setInput(&a_msg);
  setMute(true);
}
void DtmfTesterDialog::startSession(){
 
  if(wav_file.open(filename,AmAudioFile::Read))
    throw string("DtmfTesterDialog::onSessionStart: Cannot open file\n");

  string rec_fname = "/tmp/dtmftest_"+getLocalTag()+".wav";
  if(rec_file.open(rec_fname,AmAudioFile::Write))
    throw string("DtmfTesterDialog::onSessionStart: Cannot open rec_file\n");

  play_list.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
  setInOut(&rec_file, &play_list);
}
Beispiel #18
0
bool AmSession::setTimer(int timer_id, double timeout) {
  if (timeout <= 0.005) {
    DBG("setting timer %d with immediate timeout - posting Event\n", timer_id);
    AmTimeoutEvent* ev = new AmTimeoutEvent(timer_id);
    postEvent(ev);
    return true;
  }

  DBG("setting timer %d with timeout %f\n", timer_id, timeout);
  AmAppTimer::instance()->setTimer(getLocalTag(), timer_id, timeout);

  return true;
}
Beispiel #19
0
void AmB2BSession::relayError(const string &method, unsigned cseq, bool forward, int sip_code, const char *reason)
{
  if (method != "ACK") {
    AmSipReply n_reply;
    n_reply.code = sip_code;
    n_reply.reason = reason;
    n_reply.cseq = cseq;
    n_reply.cseq_method = method;
    n_reply.from_tag = dlg->getLocalTag();
    DBG("relaying B2B SIP reply %d %s\n", sip_code, reason);
    relayEvent(new B2BSipReplyEvent(n_reply, forward, method, getLocalTag()));
  }
}
Beispiel #20
0
void AmB2BSession::relayError(const string &method, unsigned cseq,
			      bool forward, int err_code)
{
  if (method != "ACK") {
    AmSipReply n_reply;
    errCode2RelayedReply(n_reply, err_code, 500);
    n_reply.cseq = cseq;
    n_reply.cseq_method = method;
    n_reply.from_tag = dlg->getLocalTag();
    DBG("relaying B2B SIP error reply %u %s\n", n_reply.code, n_reply.reason.c_str());
    relayEvent(new B2BSipReplyEvent(n_reply, forward, method, getLocalTag()));
  }
}
void AmB2ABCallerSession::relayEvent(AmEvent* ev)
{
  if(other_id.empty()){
    B2ABConnectLegEvent* co_ev  = dynamic_cast<B2ABConnectLegEvent*>(ev);   
    if( co_ev ) {
      setupCalleeSession(createCalleeSession(), co_ev);
      if (other_id.length()) {
	MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", other_id.c_str());
      }
    }
  }

  AmB2ABSession::relayEvent(ev);
}
void EarlyRecordDialog::onSessionStart(const AmSipReply& req)
{
  setInOut(NULL, NULL);

  a_msg.close();

  // replay the recorded early media
  msg_filename = "/tmp/" + getLocalTag() + ".wav";
  
  if(a_msg.open(msg_filename,AmAudioFile::Read,false))
    throw string("EarlyRecordDialog: couldn't open ") + 
      msg_filename + string(" for writing");

  setOutput(&a_msg);
}
void AmB2ABCalleeSession::onB2ABEvent(B2ABEvent* ev)
{
  if(ev->event_id == B2ABConnectLeg){

    try {
      B2ABConnectLegEvent* co_ev = dynamic_cast<B2ABConnectLegEvent*>(ev);
      assert(co_ev);

      MONITORING_LOG4(getLocalTag().c_str(), 
		      "b2b_leg", other_id.c_str(),
		      "from",    co_ev->local_party.c_str(),
		      "to",      co_ev->remote_party.c_str(),
		      "ruri",    co_ev->remote_uri.c_str());

      dlg.local_party  = co_ev->local_party;
      dlg.local_uri    = co_ev->local_uri;
			
      dlg.remote_party = co_ev->remote_party;
      dlg.remote_uri   = co_ev->remote_uri;

      setCallgroup(co_ev->callgroup);
			
      setNegotiateOnReply(true);
      if (sendInvite(co_ev->headers)) {
	throw string("INVITE could not be sent\n");
      }

      return;
    } 
    catch(const AmSession::Exception& e){
      ERROR("%i %s\n",e.code,e.reason.c_str());
      relayEvent(new B2ABConnectOtherLegExceptionEvent(e.code,e.reason));
      setStopped();
    }
    catch(const string& err){
      ERROR("startSession: %s\n",err.c_str());
      relayEvent(new B2ABConnectOtherLegExceptionEvent(500,err));
      setStopped();
    }
    catch(...){
      ERROR("unexpected exception\n");
      relayEvent(new B2ABConnectOtherLegExceptionEvent(500,"unexpected exception"));
      setStopped();
    }
  }    

  AmB2ABSession::onB2ABEvent(ev);
}
void ConferenceDialog::connectMainChannel()
{
  dialout_id = "";
  dialedout = false;
  dialout_channel.reset(NULL);
    
  play_list.close();

  if(!channel.get())
    channel.reset(AmConferenceStatus
		  ::getChannel(conf_id,
			       getLocalTag()));

  play_list.addToPlaylist(new AmPlaylistItem(channel.get(),
					     channel.get()));
}
void AmB2ABCallerSession::connectCallee(const string& remote_party,
					const string& remote_uri,
					const string& local_party,
					const string& local_uri,
					const string& headers)
{
  if(callee_status != None)
    terminateOtherLeg();

  B2ABConnectLegEvent* ev = new B2ABConnectLegEvent(remote_party,remote_uri,
						    local_party,local_uri,
						    getLocalTag(), // callgroup
						    headers);  // extra headers

  relayEvent(ev);
  callee_status = NoReply;
}
WebConferenceDialog::~WebConferenceDialog()
{
  // provide statistics
  if ((connect_ts == -1)||(disconnect_ts == -1)) {
    factory->callStats(false, 0);
  } else {
    factory->callStats(true, disconnect_ts - connect_ts);
  }

  prompts.cleanup((long)this);
  play_list.close(false);
  if (is_dialout || (InConference == state)) {
    factory->updateStatus(is_dialout?dlg.user:conf_id, 
			  getLocalTag(), 
			  ConferenceRoomParticipant::Finished,
			  "");
  }
}
AmB2ABCalleeSession* ServiceLineCallerDialog::createCalleeSession() {
  ServiceLineCalleeDialog* sess = new ServiceLineCalleeDialog(getLocalTag());

  AmSessionEventHandlerFactory* uac_auth_f = 
    AmPlugIn::instance()->getFactory4Seh("uac_auth");
  
  if (NULL != uac_auth_f) {
    DBG("UAC Auth enabled for new serviceline session.\n");
    AmSessionEventHandler* h = uac_auth_f->getHandler(sess);
    if (h != NULL )
      sess->addHandler(h);
    else {
      ERROR("unable to set SIP UAC auth for new session.");
    } 
  } else {
    ERROR("unable to get SIP UAC auth."
	  "(uac_auth module loaded?)\n");
  }
  return sess;
}
void AmB2BCallerSession::relayEvent(AmEvent* ev)
{
  if(other_id.empty()){

    if(dynamic_cast<B2BEvent*>(ev)){

      B2BSipEvent*     sip_ev = dynamic_cast<B2BSipEvent*>(ev);
      B2BConnectEvent* co_ev  = dynamic_cast<B2BConnectEvent*>(ev);
	    
      if( (sip_ev && sip_ev->forward) || co_ev ) {
	createCalleeSession();
	if (other_id.length()) {
	  MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", other_id.c_str());
	}
      }
    }
  }

  AmB2BSession::relayEvent(ev);
}
Beispiel #29
0
int AmB2BCallerSession::relayEvent(AmEvent* ev)
{
  if(getOtherId().empty() && !getStopped()){

    bool create_callee = false;
    B2BSipEvent* sip_ev = dynamic_cast<B2BSipEvent*>(ev);
    if (sip_ev && sip_ev->forward)
      create_callee = true;
    else
      create_callee = dynamic_cast<B2BConnectEvent*>(ev) != NULL;

    if (create_callee) {
      createCalleeSession();
      if (getOtherId().length()) {
	MONITORING_LOG(getLocalTag().c_str(), "b2b_leg", getOtherId().c_str());
      }
    }

  }

  return AmB2BSession::relayEvent(ev);
}
void ConferenceDialog::disconnectDialout()
{
  if(dialedout){
	
    if(dialout_channel.get()){
	    
      AmSessionContainer::instance()
	->postEvent(dialout_channel->getConfID(),
		    new DialoutConfEvent(DoConfDisconnect,
					 dialout_channel->getConfID()));
    }
  }
  else {

    AmSessionContainer::instance()
      ->postEvent(dialout_id,
		  new DialoutConfEvent(DoConfDisconnect,
				       getLocalTag()));
    
    connectMainChannel();
  }
}