www.pudn.com > fsm.rar > fsm_uas4req.c


/*
  The oSIP library implements the Session Initiation Protocol (SIP -rfc2543-)
  Copyright (C) 2001  Aymeric MOIZARD jack@atosc.org
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include 
#include 

#include "fsm.h"
#include 
#include 

#ifdef __VXWORKS_OS__
#include 
#endif

static statemachine_t *uas_4req;


statemachine_t *
fsm_getfsm_uas4req()
{
  return uas_4req;
}

int
fsm_load_uas4req() {

  transition_t *transition;

  uas_4req       = (statemachine_t *) smalloc(sizeof(statemachine_t));
  uas_4req->transitions = (list_t *)  smalloc(sizeof(list_t));
  list_init(uas_4req->transitions);

  transition         = (transition_t *) smalloc(sizeof(transition_t));
  transition->state  = INITIAL;
  transition->type  = RCV_REQUEST;
  transition->method = (void(*)(void *,void *))&uas_rcvrequest;
  list_add(uas_4req->transitions,transition,-1);

  transition         = (transition_t *) smalloc(sizeof(transition_t));
  transition->state  = PROCEEDING;
  transition->type  = RCV_REQUEST;
  transition->method = (void(*)(void *,void *))&uas_r_rcvretransmitrequest;
  list_add(uas_4req->transitions,transition,-1);

  transition         = (transition_t *) smalloc(sizeof(transition_t));
  transition->state  = PROCEEDING;
  transition->type  = SND_STATUS_1XX;
  transition->method = (void(*)(void *,void *))&uas_send1XX;
  list_add(uas_4req->transitions,transition,-1);

  transition         = (transition_t *) smalloc(sizeof(transition_t));
  transition->state  = PROCEEDING;
  transition->type  = SND_STATUS_23456XX;
  transition->method = (void(*)(void *,void *))&uas_r_send23456XX;
  list_add(uas_4req->transitions,transition,-1);

  transition         = (transition_t *) smalloc(sizeof(transition_t));
  transition->state  = COMPLETED;
  transition->type  = RCV_REQUEST;
  transition->method = (void(*)(void *,void *))&uas_r_rcvretransmitrequest;
  list_add(uas_4req->transitions,transition,-1);

  return 0;
}


void
uas_rcvrequest(sipevent_t *sipevent,transaction_t *transaction)
{
  DEBUG(msg_logrequest(sipevent->sip,"RCV %s f:%s t:%s cseq:%s callid:%s\n"));

  transaction->lastrequest = sipevent->sip;
  transaction->state = PROCEEDING;

  transaction->retransmissioncounter = 1;
  fifo_add(((osip_t *)transaction->config)->uas_timerff,transaction);

  /* invoke the right callback! */
  if (MSG_IS_INVITE(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvinvite != NULL)
	((osip_t *)transaction->config)->cb_rcvinvite(sipevent,transaction);
    }
  else if (MSG_IS_BYE(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvbye != NULL)
	((osip_t *)transaction->config)->cb_rcvbye(sipevent,transaction);
    }
  else if (MSG_IS_REGISTER(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvregister != NULL)
	((osip_t *)transaction->config)->cb_rcvregister(sipevent,transaction);
    }
  else if (MSG_IS_CANCEL(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvcancel != NULL)
	((osip_t *)transaction->config)->cb_rcvcancel(sipevent,transaction);
    }
  else if (MSG_IS_OPTIONS(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvoptions != NULL)
	((osip_t *)transaction->config)->cb_rcvoptions(sipevent,transaction);
    }
  else if (MSG_IS_INFO(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvinfo != NULL)
	((osip_t *)transaction->config)->cb_rcvinfo(sipevent,transaction);
    }
  else if (MSG_IS_PRACK(sipevent->sip))
    {
      if (((osip_t *)transaction->config)->cb_rcvprack != NULL)
	((osip_t *)transaction->config)->cb_rcvprack(sipevent,transaction);
    }
  else
    {
      if (((osip_t *)transaction->config)->cb_rcvunkrequest != NULL)
	((osip_t *)transaction->config)->cb_rcvunkrequest(sipevent,transaction);
    }
}

void
uas_r_rcvretransmitrequest(sipevent_t *sipevent,transaction_t *transaction)
{
  ua_retransmitresponse(sipevent,transaction);
}

void
uas_r_send23456XX(sipevent_t *sipevent,transaction_t *transaction)
{
  if (uas_send23456XX(sipevent,transaction)==-1)
    return ;

  transaction->completed_time = time(NULL);
  transaction->state = COMPLETED;
}


/* COMMON METHODS FOR incoming INVITE and OTHERREQ */

void
ua_retransmitresponse(sipevent_t *sipevent,transaction_t *transaction)
{
  /* invoke the right callback! */
  if (((osip_t *)transaction->config)->cb_rcvreq_retransmission != NULL)
    ((osip_t *)transaction->config)->cb_rcvreq_retransmission(transaction);
  DEBUG(msg_logrequest(sipevent->sip,"RCV (retransmission) %s f:%s t:%s cseq:%s callid:%s\n"));
  
  if (transaction->lastresponse!=NULL)
    {
      int i;
      i = udp_send_response(transaction->lastresponse);
      if (i==-1)
	{
	  TRACE(trace(__FILE__,__LINE__,TRACE_LEVEL1,NULL,"Error Could not retransmit response.\n"));
	  if (((osip_t *)transaction->config)->cb_network_error != NULL)
	    ((osip_t *)transaction->config)->cb_network_error(transaction);
	}
      else
	/* invoke the right callback! */
	{
	  if (((osip_t *)transaction->config)->cb_sndresp_retransmission != NULL)
	    ((osip_t *)transaction->config)->cb_sndresp_retransmission(transaction);
	}
    }
  else
    /* if no response is given by user, retransmission has no effect */
    {
      TRACE(trace(__FILE__,__LINE__,TRACE_LEVEL4,NULL,"Retransmission has no effect. (Response is not ready?)\n"));
    }

  msg_free(sipevent->sip);
  sfree(sipevent->sip);
}

void
uas_send1XX(sipevent_t *sipevent,transaction_t *transaction)
{
  int i;
  i = udp_send_response(sipevent->sip);
  if (i==-1)
    {
    TRACE(trace(__FILE__,__LINE__,TRACE_LEVEL1,NULL,"Error Could not send new response.\n"));
    if (((osip_t *)transaction->config)->cb_network_error != NULL)
      ((osip_t *)transaction->config)->cb_network_error(transaction);
    msg_free(sipevent->sip);
    sfree(sipevent->sip);
    return ;
    }
  
  /* invoke the right callback! */
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd1xx != NULL)
    ((osip_t *)transaction->config)->cb_snd1xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister1xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack1xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest1xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest1xx(sipevent,transaction);
  }
#endif

  if (transaction->lastresponse!=NULL)
    {
    msg_free(transaction->lastresponse);
    sfree(transaction->lastresponse);
    }
  transaction->lastresponse = sipevent->sip;
}

int
uas_send23456XX(sipevent_t *sipevent,transaction_t *transaction)
{
  int i;
  i = udp_send_response(sipevent->sip);
  if (i==-1)
    {
    TRACE(trace(__FILE__,__LINE__,TRACE_LEVEL1,NULL,"response not sent.\n"));
    if (((osip_t *)transaction->config)->cb_network_error != NULL)
      ((osip_t *)transaction->config)->cb_network_error(transaction);
 
    msg_free(sipevent->sip);
    sfree(sipevent->sip);
    return -1;
    }
  
  if (transaction->lastresponse!=NULL)
    {
    msg_free(transaction->lastresponse);
    sfree(transaction->lastresponse);
    }
  transaction->lastresponse = sipevent->sip;

  /* AMD/ bug: fixed 26/09/2001 */
  if (MSG_IS_INVITE(transaction->lastrequest))
      transaction->state = ANSWERED;
  else /* for other requests type, it's all done! */
    {
      transaction->state = COMPLETED;
      transaction->completed_time = time(NULL);
    }

  /* invoke the right callback! */
  if (MSG_IS_STATUS_2XX(sipevent->sip))
    {
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd2xx != NULL)
    ((osip_t *)transaction->config)->cb_snd2xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister2xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack2xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest2xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest2xx(sipevent,transaction);
  }
#endif
    }
  else if (MSG_IS_STATUS_3XX(sipevent->sip))
    {
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd3xx != NULL)
    ((osip_t *)transaction->config)->cb_snd3xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister3xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack3xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest3xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest3xx(sipevent,transaction);
  }
#endif
    }
  else if (MSG_IS_STATUS_4XX(sipevent->sip))
    {
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd4xx != NULL)
    ((osip_t *)transaction->config)->cb_snd4xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister4xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack4xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest4xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest4xx(sipevent,transaction);
  }
#endif
    }
  else if (MSG_IS_STATUS_5XX(sipevent->sip))
    {
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd5xx != NULL)
    ((osip_t *)transaction->config)->cb_snd5xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister5xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack5xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest5xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest5xx(sipevent,transaction);
  }
#endif
    }
  else if (MSG_IS_STATUS_6XX(sipevent->sip))
    {
#ifndef EXTENDED_CALLBACKS
  if (((osip_t *)transaction->config)->cb_snd6xx != NULL)
    ((osip_t *)transaction->config)->cb_snd6xx(sipevent,transaction);
#else
  if (MSG_IS_RESPONSEFOR(sipevent->sip,"INVITE")) {
    if (((osip_t *)transaction->config)->cb_sndinvite6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinvite6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"BYE")) {
    if (((osip_t *)transaction->config)->cb_sndbye6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndbye6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"CANCEL")) {
    if (((osip_t *)transaction->config)->cb_sndcancel6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndcancel6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"INFO")) {
    if (((osip_t *)transaction->config)->cb_sndinfo6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndinfo6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"OPTIONS")) {
    if (((osip_t *)transaction->config)->cb_sndoptions6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndoptions6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"REGISTER")) {
    if (((osip_t *)transaction->config)->cb_sndregister6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndregister6xx(sipevent,transaction);
  } else if (MSG_IS_RESPONSEFOR(sipevent->sip,"PRACK")) {
    if (((osip_t *)transaction->config)->cb_sndprack6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndprack6xx(sipevent,transaction);
  } else {
    if (((osip_t *)transaction->config)->cb_sndunkrequest6xx != NULL)
      ((osip_t *)transaction->config)->cb_sndunkrequest6xx(sipevent,transaction);
  }
#endif
    }
  else
    { TRACE(trace(__FILE__,__LINE__,TRACE_LEVEL1,NULL,"Unknown response code?\n"));}
  return 0;
}