invitedialog.java

来自「结构非常清晰的SIP协议栈」· Java 代码 · 共 722 行 · 第 1/3 页

JAVA
722
字号
         else contact_url=new NameAddress(new SipURL(contact,sip_provider.getViaAddress(),sip_provider.getPort()));
         invite.setContactHeader(new ContactHeader(contact_url));
      }
      reInvite(invite);
   }


   /** Re-invites the remote user.
     * <p>Starts a new InviteTransactionClient and changes the dialog state information */
   public void reInvite(Message invite)
   {  printLog("inside reInvite(invite)",LogLevel.MEDIUM);
      if (!statusIs(D_CALL)) return;
      // else
      changeStatus(D_ReINVITING);
      invite_req=invite;
      update(Dialog.UAC,invite_req);
      InviteTransactionClient invite_tc=new InviteTransactionClient(sip_provider,invite_req,this);                
      invite_tc.request();
   }

   /** Re-invites the remote user with offer/answer in 2xx/ack
     * <p>Starts a new InviteTransactionClient and changes the dialog state information */
   public void reInviteWithoutOffer(Message invite)
   {  invite_offer=false;
      reInvite(invite);
   }

   /** Re-invites the remote user with offer/answer in 2xx/ack
     * <p>Starts a new InviteTransactionClient and changes the dialog state information */
   public void reInviteWithoutOffer(String contact, String session_descriptor)
   {  invite_offer=false;
      reInvite(contact,session_descriptor);
   }

   /** Sends the ack when offer/answer is in 2xx/ack */
   public void ackWithAnswer(String contact, String session_descriptor)
   {  if (contact!=null) setLocalContact(new NameAddress(contact));
      Message ack=MessageFactory.create2xxAckRequest(this,session_descriptor);
      ackWithAnswer(ack);
   }

   /** Sends the ack when offer/answer is in 2xx/ack */
   public void ackWithAnswer(Message ack)
   {  ack_req=ack;
      // reset the offer/answer flag to the default value
      invite_offer=true;
      AckTransactionClient ack_tc=new AckTransactionClient(sip_provider,ack,null);
      ack_tc.request();
   }

         
   /** Responds with <i>resp</i>.
     * This method can be called when the InviteDialog is in D_INVITED or D_BYED states.
     * <p>
     * If the CSeq method is INVITE and the response is 2xx,
     * it moves to state D_ACCEPTED, adds a new listener to the SipProviderListener,
     * and creates new AckTransactionServer
     * <p>
     * If the CSeq method is INVITE and the response is not 2xx,
     * it moves to state D_REFUSED, and sends the response. */
   public void respond(Message resp)
   //private void respond(Message resp)
   {  printLog("inside respond(resp)",LogLevel.MEDIUM);
      String method=resp.getCSeqHeader().getMethod();
      if (method.equals(SipMethods.INVITE))
      {  if (!verifyStatus(statusIs(D_INVITED)||statusIs(D_ReINVITED)))
         {  printLog("respond(): InviteDialog not in (re)invited state: No response now",LogLevel.HIGH);
            return;
         }
      
         int code=resp.getStatusLine().getCode();
         // 1xx provisional responses
         if (code>=100 && code<200)
         {  invite_ts.respondWith(resp);
            return;
         }
         // For all final responses establish the dialog
         if (code>=200)
         {  //changeStatus(D_ACCEPTED);
            update(Dialog.UAS,resp);
         }
         // 2xx success responses         
         if (code>=200 && code<300)
         {  if(statusIs(D_INVITED)) changeStatus(D_ACCEPTED); else changeStatus(D_ReACCEPTED);
            // terminates the INVITE Transaction server and activates an ACK Transaction server
            invite_ts.terminate();
            ConnectionIdentifier conn_id=invite_ts.getConnectionId();
            ack_ts=new AckTransactionServer(sip_provider,conn_id,resp,this);
            ack_ts.respond();
            //if (statusIs(D_ReACCEPTED)) listener.onDlgReInviteAccepted(this);
            //else listener.onDlgAccepted(this);         
            return;
         }
         else
         // 300-699 failure responses         
         //if (code>=300)
         {  if(statusIs(D_INVITED)) changeStatus(D_REFUSED); else changeStatus(D_ReREFUSED);
            invite_ts.respondWith(resp);
            //if (statusIs(D_ReREFUSED)) listener.onDlgReInviteRefused(this);
            //else listener.onDlgRefused(this);         
            return;
         }
      }
      if (method.equals(SipMethods.BYE))
      {  if (!verifyStatus(statusIs(D_BYED))) return;
         bye_ts.respondWith(resp);
      }
   } 
   
   /** Responds with <i>code</i> and <i>reason</i>.
     * This method can be called when the InviteDialog is in D_INVITED, D_ReINVITED states */
   public void respond(int code, String reason, String contact, String sdp)
   {  printLog("inside respond("+code+","+reason+")",LogLevel.MEDIUM);
      if (statusIs(D_INVITED) || statusIs(D_ReINVITED))
      {  NameAddress contact_address=null;
         if (contact!=null) contact_address=new NameAddress(contact);
         Message resp=MessageFactory.createResponse(invite_req,code,reason,contact_address);
         resp.setBody(sdp);
         respond(resp);
      }
      else
      printWarning("Dialog isn't in \"invited\" state: cannot respond ("+code+"/"+getStatus()+"/"+getDialogID()+")",LogLevel.MEDIUM);
   }

   /** Signals that the phone is ringing.
     * This method should be called when the InviteDialog is in D_INVITED or D_ReINVITED state */
   public void ring()
   {  printLog("inside ring()",LogLevel.MEDIUM);
      respond(180,SipResponses.reasonOf(180),null,null);
   }

   /** Accepts the incoming call.
     * This method should be called when the InviteDialog is in D_INVITED or D_ReINVITED state */
   public void accept(String contact, String sdp)
   {  printLog("inside accept(sdp)",LogLevel.MEDIUM);
      respond(200,SipResponses.reasonOf(200),contact,sdp);
   }
   
   /** Refuses the incoming call.
     * This method should be called when the InviteDialog is in D_INVITED or D_ReINVITED state */
   public void refuse(int code, String reason)
   {  printLog("inside refuse("+code+","+reason+")",LogLevel.MEDIUM);
      respond(code,reason,null,null);
   }

   /** Refuses the incoming call.
     * This method should be called when the InviteDialog is in D_INVITED or D_ReINVITED state */
   public void refuse()
   {  printLog("inside refuse()",LogLevel.MEDIUM);
      //refuse(480,"Temporarily Unavailable");
      //refuse(603,"Decline");
      refuse(403,SipResponses.reasonOf(403));
   }

   /** Termiante the call.
     * This method should be called when the InviteDialog is in D_CALL state
     * <p>
     * Increments the Cseq, moves to state D_BYEING, and creates new BYE TransactionClient */
   public void bye()
   {  printLog("inside bye()",LogLevel.MEDIUM);
      if (statusIs(D_CALL))
      {  Message bye=MessageFactory.createByeRequest(this);
         bye(bye);        
      }
   }

   /** Termiante the call.
     * This method should be called when the InviteDialog is in D_CALL state
     * <p>
     * Increments the Cseq, moves to state D_BYEING, and creates new BYE TransactionClient */
   public void bye(Message bye)
   {  printLog("inside bye(bye)",LogLevel.MEDIUM);
      if (statusIs(D_CALL))
      {  changeStatus(D_BYEING);
         //dialog_state.incLocalCSeq(); // done by MessageFactory.createRequest()
         TransactionClient tc=new TransactionClient(sip_provider,bye,this);
         tc.request();
         //listener.onDlgByeing(this);         
      }
   }

   /** Cancel the ongoing call request or a call listening.
     * This method should be called when the InviteDialog is in D_INVITING or D_ReINVITING state
     * or in the D_WAITING state */
   public void cancel()
   {  printLog("inside cancel()",LogLevel.MEDIUM);
      if (statusIs(D_INVITING) || statusIs(D_ReINVITING))
      {  Message cancel=MessageFactory.createCancelRequest(invite_req);
         cancel(cancel);
      }
      else
      if (statusIs(D_WAITING) || statusIs(D_ReWAITING))
      {  invite_ts.terminate();
      }      
   }

   /** Cancel the ongoing call request or a call listening.
     * This method should be called when the InviteDialog is in D_INVITING or D_ReINVITING state
     * or in the D_WAITING state */
   public void cancel(Message cancel)
   {  printLog("inside cancel(cancel)",LogLevel.MEDIUM);
      if (statusIs(D_INVITING) || statusIs(D_ReINVITING))
      {  //changeStatus(D_CANCELING);
         TransactionClient tc=new TransactionClient(sip_provider,cancel,null);
         tc.request();
      }
      else
      if (statusIs(D_WAITING) || statusIs(D_ReWAITING))
      {  invite_ts.terminate();
      }      
   }

   /** Redirects the incoming call
     * , specifing the <i>code</i> and <i>reason</i>.
     * This method can be called when the InviteDialog is in D_INVITED or D_ReINVITED state */
   public void redirect(int code, String reason, String contact)
   {  printLog("inside redirect("+code+","+reason+","+contact+")",LogLevel.MEDIUM);
      respond(code,reason,contact,null);
   }

   // ************** Inherited from SipProviderListener **************

   /** Inherited from class SipProviderListener.
     * Called when a new message is received (out of any ongoing transaction)
     * for the current InviteDialog.
     * Always checks for out-of-date methods (CSeq header sequence number).
     * <p>
     * If the message is ACK(2xx/INVITE) request, it moves to D_CALL state, and fires <i>onDlgAck(this,body,msg)</i>.
     * <p>
     * If the message is 2xx(INVITE) response, it create a new AckTransactionClient
     * <p>
     * If the message is BYE,
     * it moves to D_BYED state, removes the listener from SipProvider, fires onDlgBye(this,msg)
     * then it responds with 200 OK, moves to D_CLOSE state and fires onDlgClose(this)
     */
   public void onReceivedMessage(SipProvider sip_provider, Message msg)
   {  printLog("inside onReceivedMessage(sip_provider,message)",LogLevel.MEDIUM);
      if (msg.isRequest() && !(msg.isAck() || msg.isCancel()) && msg.getCSeqHeader().getSequenceNumber()<=getRemoteCSeq())
      {  printLog("Request message is too late (CSeq too small): Message discarded",LogLevel.HIGH);
         return;
      }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?