useragent.java

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

JAVA
778
字号
   } 
   

   /** Creates a new session descriptor */
   /*private void newSession(int media_port)
   {  SessionDescriptor local_sdp=new SessionDescriptor(user_profile.from_url,sip_provider.getAddress());
      int audio_port=media_port;
      int video_port=media_port+2;
      //PATCH [040902] if (audio || !video) local_sdp.addMedia(new MediaField("audio",audio_port,0,"RTP/AVP","0"),new AttributeField("rtpmap","0 PCMU/8000"));
      //PATCH [040902] if (video || !(audio || video)) local_sdp.addMedia(new MediaField("video",video_port,0,"RTP/AVP","7"),new AttributeField("rtpmap","17"));
      local_sdp.addMedia(new MediaField("audio",audio_port,0,"RTP/AVP","0"),new AttributeField("rtpmap","0 PCMU/8000"));
      local_session=local_sdp.toString();
   }*/

   
   /** Makes a new call (acting as UAC). */
   public void call(String target_url)
   {  changeStatus(UA_OUTGOING_CALL);
      call=new ExtendedCall(sip_provider,user_profile.from_url,user_profile.contact_url,user_profile.username,user_profile.realm,user_profile.passwd,this);      
      // in case of incomplete url (e.g. only 'user' is present), try to complete it
      target_url=sip_provider.completeNameAddress(target_url).toString();
      if (user_profile.no_offer) call.call(target_url);
      else call.call(target_url,local_session);
   }   


   /** Waits for an incoming call (acting as UAS). */
   public void listen()
   {  changeStatus(UA_IDLE);
      call=new ExtendedCall(sip_provider,user_profile.from_url,user_profile.contact_url,user_profile.username,user_profile.realm,user_profile.passwd,this);      
      call.listen();  
   } 


   /** Closes an ongoing, incoming, or pending call */
   public void hangup()
   {  if (clip_ring!=null) clip_ring.stop();      
      closeMediaApplication();
      if (call!=null) call.hangup();
      changeStatus(UA_IDLE);
   } 


   /** Closes an ongoing, incoming, or pending call */
   public void accept()
   {  if (clip_ring!=null) clip_ring.stop();
      if (call!=null) call.accept(local_session);
   }   


   /** Redirects an incoming call */
   public void redirect(String redirection)
   {  if (clip_ring!=null) clip_ring.stop();
      if (call!=null) call.redirect(redirection);
   }   


   /** Launches the Media Application (currently, the RAT audio tool) */
   protected void launchMediaApplication()
   {
      // exit if the Media Application is already running  
      if (audio_app!=null || video_app!=null)
      {  printLog("DEBUG: media application is already running",LogLevel.HIGH);
         return;
      }
      SessionDescriptor local_sdp=new SessionDescriptor(call.getLocalSessionDescriptor());
      String local_media_address=(new Parser(local_sdp.getConnection().toString())).skipString().skipString().getString();
      int local_audio_port=0;
      int local_video_port=0;
      // parse local sdp
      for (Enumeration e=local_sdp.getMediaDescriptors().elements(); e.hasMoreElements(); )
      {  MediaField media=((MediaDescriptor)e.nextElement()).getMedia();
         if (media.getMedia().equals("audio")) 
            local_audio_port=media.getPort();
         if (media.getMedia().equals("video")) 
            local_video_port=media.getPort();
      }
      // parse remote sdp
      SessionDescriptor remote_sdp=new SessionDescriptor(call.getRemoteSessionDescriptor());
      String remote_media_address=(new Parser(remote_sdp.getConnection().toString())).skipString().skipString().getString();
      int remote_audio_port=0;              
      int remote_video_port=0;              
      for (Enumeration e=remote_sdp.getMediaDescriptors().elements(); e.hasMoreElements(); )
      {  MediaField media=((MediaDescriptor)e.nextElement()).getMedia();
         if (media.getMedia().equals("audio")) 
            remote_audio_port=media.getPort();
         if (media.getMedia().equals("video")) 
            remote_video_port=media.getPort();
      }

      // select the media direction (send_only, recv_ony, fullduplex)
      int dir=0;
      if (user_profile.recv_only) dir=-1;
      else
      if (user_profile.send_only) dir=1;
      
      if (user_profile.audio && local_audio_port!=0 && remote_audio_port!=0)
      {  // create an audio_app and start it
         if (user_profile.use_rat)
         {  audio_app=new RATLauncher(user_profile.bin_rat,local_audio_port,remote_media_address,remote_audio_port,log);
         }
         else 
         if (user_profile.use_jmf)
         {  // try to use JMF audio app
            try
            {  Class myclass=Class.forName("local.ua.JMFAudioLauncher");
               Class[] parameter_types={ java.lang.Integer.TYPE, Class.forName("java.lang.String"), java.lang.Integer.TYPE, java.lang.Integer.TYPE, Class.forName("org.zoolu.tools.Log") };
               Object[] parameters={ new Integer(local_audio_port), remote_media_address, new Integer(remote_audio_port), new Integer(dir), log };
               java.lang.reflect.Constructor constructor=myclass.getConstructor(parameter_types);
               audio_app=(MediaLauncher)constructor.newInstance(parameters);
            }
            catch (Exception e)
            {  printException(e,LogLevel.HIGH);
               printLog("Error trying to create the JMFAudioLauncher",LogLevel.HIGH);
            }
         }
         // else
         if (audio_app==null)
         {  // for testing..
            String audio_in=null;
            if (user_profile.send_tone) audio_in=JAudioLauncher.TONE;
            else if (user_profile.send_file!=null) audio_in=user_profile.send_file;
            String audio_out=null;
            if (user_profile.recv_file!=null) audio_out=user_profile.recv_file;        
            //audio_app=new JAudioLauncher(local_audio_port,remote_media_address,remote_audio_port,dir,log);
            audio_app=new JAudioLauncher(local_audio_port,remote_media_address,remote_audio_port,dir,audio_in,audio_out,user_profile.audio_sample_rate,user_profile.audio_sample_size,user_profile.audio_frame_size,log);
         }
         audio_app.startMedia();
      }
      if (user_profile.video && local_video_port!=0 && remote_video_port!=0)
      {  // create a video_app and start it
         if (user_profile.use_vic)
         {  video_app=new VICLauncher(user_profile.bin_vic,local_video_port,remote_media_address,remote_video_port,log);
         }
         else 
         if (user_profile.use_jmf)
         {  // try to use JMF video app
            try
            {  Class myclass=Class.forName("local.ua.JMFVideoLauncher");
               Class[] parameter_types={ java.lang.Integer.TYPE, Class.forName("java.lang.String"), java.lang.Integer.TYPE, java.lang.Integer.TYPE, Class.forName("org.zoolu.tools.Log") };
               Object[] parameters={ new Integer(local_video_port), remote_media_address, new Integer(remote_video_port), new Integer(dir), log };
               java.lang.reflect.Constructor constructor=myclass.getConstructor(parameter_types);
               video_app=(MediaLauncher)constructor.newInstance(parameters);
            }
            catch (Exception e)
            {  printException(e,LogLevel.HIGH);
               printLog("Error trying to create the JMFVideoLauncher",LogLevel.HIGH);
            }
         }
         // else
         if (video_app==null)
         {  printLog("No external video application nor JMF has been provided: Video not started",LogLevel.HIGH);
            return;
         }
         video_app.startMedia();
      }
   }
 
   
   /** Close the Media Application  */
   protected void closeMediaApplication()
   {  if (audio_app!=null)
      {  audio_app.stopMedia();
         audio_app=null;
      }
      if (video_app!=null)
      {  video_app.stopMedia();
         video_app=null;
      }
   }


   // ********************** Call callback functions **********************
   
   /** Callback function called when arriving a new INVITE method (incoming call) */
   public void onCallIncoming(Call call, NameAddress callee, NameAddress caller, String sdp, Message invite)
   {  printLog("onCallIncoming()",LogLevel.LOW);
      if (call!=this.call) {  printLog("NOT the current call",LogLevel.LOW);  return;  }
      printLog("INCOMING",LogLevel.HIGH);
      //System.out.println("DEBUG: inside UserAgent.onCallIncoming(): sdp=\n"+sdp);
      changeStatus(UA_INCOMING_CALL);
      call.ring();
      if (sdp!=null)
      {  // Create the new SDP
         SessionDescriptor remote_sdp=new SessionDescriptor(sdp);     
         SessionDescriptor local_sdp=new SessionDescriptor(local_session);
         SessionDescriptor new_sdp=new SessionDescriptor(remote_sdp.getOrigin(),remote_sdp.getSessionName(),local_sdp.getConnection(),local_sdp.getTime());
         new_sdp.addMediaDescriptors(local_sdp.getMediaDescriptors());
         new_sdp=SdpTools.sdpMediaProduct(new_sdp,remote_sdp.getMediaDescriptors());
         new_sdp=SdpTools.sdpAttirbuteSelection(new_sdp,"rtpmap");
         local_session=new_sdp.toString();
      }
      // play "ring" sound
      if (clip_ring!=null) clip_ring.loop();
      if (listener!=null) listener.onUaCallIncoming(this,callee,caller);
   }  


   /** Callback function called when arriving a new Re-INVITE method (re-inviting/call modify) */
   public void onCallModifying(Call call, String sdp, Message invite)
   {  printLog("onCallModifying()",LogLevel.LOW);
      if (call!=this.call) {  printLog("NOT the current call",LogLevel.LOW);  return;  }
      printLog("RE-INVITE/MODIFY",LogLevel.HIGH);
      // to be implemented.
      // currently it simply accepts the session changes (see method onCallModifying() in CallListenerAdapter)
      super.onCallModifying(call,sdp,invite);
   }


   /** Callback function that may be overloaded (extended). Called when arriving a 180 Ringing */
   public void onCallRinging(Call call, Message resp)
   {  printLog("onCallRinging()",LogLevel.LOW);
      if (call!=this.call && call!=call_transfer) {  printLog("NOT the current call",LogLevel.LOW);  return;  }
      printLog("RINGING",LogLevel.HIGH);
      // play "on" sound
      if (clip_on!=null) clip_on.replay();
      if (listener!=null) listener.onUaCallRinging(this);
   }


   /** Callback function called when arriving a 2xx (call accepted) */
   public void onCallAccepted(Call call, String sdp, Message resp)
   {  printLog("onCallAccepted()",LogLevel.LOW);
      if (call!=this.call && call!=call_transfer) {  printLog("NOT the current call",LogLevel.LOW);  return;  }
      printLog("ACCEPTED/CALL",LogLevel.HIGH);
      changeStatus(UA_ONCALL);
      if (user_profile.no_offer)
      {  // Create the new SDP
         SessionDescriptor remote_sdp=new SessionDescriptor(sdp);
         SessionDescriptor local_sdp=new SessionDescriptor(local_session);
         SessionDescriptor new_sdp=new SessionDescriptor(remote_sdp.getOrigin(),remote_sdp.getSessionName(),local_sdp.getConnection(),local_sdp.getTime());
         new_sdp.addMediaDescriptors(local_sdp.getMediaDescriptors());
         new_sdp=SdpTools.sdpMediaProduct(new_sdp,remote_sdp.getMediaDescriptors());
         new_sdp=SdpTools.sdpAttirbuteSelection(new_sdp,"rtpmap");


         // update the local SDP  
         local_session=new_sdp.toString();
         // answer with the local sdp
         call.ackWithAnswer(local_session);
      }
      // play "on" sound
      if (clip_on!=null) clip_on.replay();
      if (listener!=null) listener.onUaCallAccepted(this);

      launchMediaApplication();
      
      if (call==call_transfer)
      {  StatusLine status_line=resp.getStatusLine();
         int code=status_line.getCode();
         String reason=status_line.getReason();
         this.call.notify(code,reason);
      }
   }


   /** Callback function called when arriving an ACK method (call confirmed) */
   public void onCallConfirmed(Call call, String sdp, Message ack)
   {  printLog("onCallConfirmed()",LogLevel.LOW);
      if (call!=this.call) {  printLog("NOT the current call",LogLevel.LOW);  return;  }

⌨️ 快捷键说明

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