随笔-295  评论-26  文章-1  trackbacks-0

 
package org.jivesoftware.xiff.core

 import flash.events.DataEvent;
 import flash.events.Event;
 import flash.events.EventDispatcher;
 import flash.events.IOErrorEvent;
 import flash.events.SecurityErrorEvent;
 import flash.events.TimerEvent;
 import flash.net.XMLSocket;
 import flash.utils.Timer;
 import flash.xml.XMLDocument;
 import flash.xml.XMLNode;
 
 import org.jivesoftware.xiff.data.IExtension;
 import org.jivesoftware.xiff.data.IQ;
 import org.jivesoftware.xiff.data.Message;
 import org.jivesoftware.xiff.data.Presence;
 import org.jivesoftware.xiff.data.XMPPStanza;
 import org.jivesoftware.xiff.data.auth.AuthExtension;
 import org.jivesoftware.xiff.data.forms.FormExtension;
 import org.jivesoftware.xiff.data.register.RegisterExtension;
 import org.jivesoftware.xiff.events.*;
 import org.jivesoftware.xiff.exception.SerializationException;

 /**
  * 当密码修改成功的时候被触发
  *
  * @eventType org.jivesoftware.xiff.events.ChangePasswordSuccessEvent.PASSWORD_SUCCESS
  */
    [Event(name="changePasswordSuccess", type="org.jivesoftware.xiff.events.ChangePasswordSuccessEvent")]
   
    /**
     * 当成功的链接到服务器上的时候触发
     *
     * @eventType org.jivesoftware.xiff.events.ConnectionSuccessEvent.CONNECT_SUCCESS
     */
    [Event(name="connection", type="org.jivesoftware.xiff.events.ConnectionSuccessEvent")]
   
    /**
     * 当与服务器断开的时候将会被触发
     *
     * @eventType org.jivesoftware.xiff.events.DisconnectionEvent.DISCONNECT
     */
    [Event(name="disconnection", type="org.jivesoftware.xiff.events.DisconnectionEvent")]
   
    /**
     * Dispatched when there is some type of XMPP error.
     * 当有xmpp 错误的时候将会被触发
     * @eventType org.jivesoftware.xiff.events.XIFFErrorEvent.XIFF_ERROR
     */
    [Event(name="error", type="org.jivesoftware.xiff.events.XIFFErrorEvent")]
   
    /**
     * Dispatched whenever there is incoming XML data.
     * 当有传入的数据的时候将会被触发
     * @eventType org.jivesoftware.xiff.events.IncomingDataEvent.INCOMING_DATA
     */
    [Event(name="incomingData", type="org.jivesoftware.xiff.events.IncomingDataEvent")]
   
    /**
     * Dispatched on successful authentication (login) with the server.
     * 当有用户登陆成功的时候将会被触发
     * @eventType org.jivesoftware.xiff.events.LoginEvent.LOGIN
     */
    [Event(name="login", type="org.jivesoftware.xiff.events.LoginEvent")]
   
    /**
     * Dispatched on incoming messages.
     *  当有进入的消息的时候将会被触发
     * @eventType org.jivesoftware.xiff.events.MessageEvent.MESSAGE
     */
    [Event(name="message", type="org.jivesoftware.xiff.events.MessageEvent")]
   
    /**
     * Dispatched whenever data is sent to the server.
     * 当有数据被传往服务器端的时候触发
     * @eventType org.jivesoftware.xiff.events.OutgoingDataEvent.OUTGOING_DATA
     */
    [Event(name="outgoingData", type="org.jivesoftware.xiff.events.OutgoingDataEvent")]
   
    /**
     * Dispatched on incoming presence data.
     *  当进入是否在线相关数据的时候触发
     * @eventType org.jivesoftware.xiff.events.PresenceEvent.PRESENCE
     */
    [Event(name="presence", type="org.jivesoftware.xiff.events.PresenceEvent")]
   
    /**
     * Dispatched on when new user account registration is successful.
     * 当用户注册成功的时候触发
     * @eventType org.jivesoftware.xiff.events.RegistrationSuccessEvent.REGISTRATION_SUCCESS
     */
    [Event(name="registrationSuccess", type="org.jivesoftware.xiff.events.RegistrationSuccessEvent")]
   
    /**
     * This class is used to connect to and manage data coming from an XMPP server. Use one instance
     * of this class per connection.
     * XMPPConnection这个类被用做连接和管理从服务器端发来的数据,每一个连接一个实例
     */
 public class XMPPConnection extends EventDispatcher
 {
  /**
   * @private
   * 是否匿名登陆
   */
  protected var _useAnonymousLogin:Boolean;
  
  /**
   * @private
   *xmlsocket
   */
  protected var _socket:XMLSocket;
  
  /**
   * @private
   * 服务器地址或者名称
   */
  protected var myServer:String;
  
  /**
   * @private
   * 用户名
   */
  protected var myUsername:String;
  
  /**
   * @private
   * 绑定的资源名称  比如smark linkq msn 等
   * */
  protected var myResource:String;
  
  /**
   * @private
   * 用户密码
   */
  protected var myPassword:String;
 
  /**
   * @private
   * 登陆端口
   */
  protected var myPort:Number;
  
  /**
   * 是否已经激活
   * @private
   */
  protected var _active:Boolean;
  
  /**
   * 是否已经登陆
   * @private
   */
  protected var loggedIn:Boolean;
  
  /**
   * 是否忽略空白字符
   * @private
   */
  protected var ignoreWhitespace:Boolean;
  
  /**
   * @private
   * 打开流的标签
   */
  protected var openingStreamTag:String;
  
  /**
   * @private
   * 关闭流的标签
   */
  protected var closingStreamTag:String;

  /**
   * @private
   * 会话id
   */
  protected var sessionID:String;
  
  /**
   * @private
   */
  protected var pendingIQs:Object;
  
  /**
   * @private
   */
  protected var _expireTagSearch:Boolean;
  
  protected static var _openConnections:Array = [];
  
  public function XMPPConnection()
  { 
   
   // Hash to hold callbacks for IQs
   pendingIQs = new Object();
   
   _useAnonymousLogin = false;
   active = false;
   loggedIn = false;
   ignoreWhitespace = true;
   //初始化为忽略空白字符
   resource = "xiff";
   //初始化资源为xiff
   port = 5222;
   
   AuthExtension.enable();
   RegisterExtension.enable();
   FormExtension.enable();
  }
  
  /**
   * Connects to the server.
   * 链接到服务器端
   * @param streamType (Optional) The type of initial stream negotiation, either <flash:stream> or <stream:stream>.
   * Some servers, like Jabber, Inc.'s XCP and Jabberd 1.4 expect <flash:stream> from a Flash client instead of the standard <stream:stream>.
   * The options for this parameter are: "flash", "terminatedFlash", "standard" and "terminatedStandard". The default is "terminatedStandard".
   *返回是否找到服务器
   * @return A boolean indicating whether the server was found.
   */
  public function connect( streamType:String = "terminatedStandard" ):Boolean
  {
   
   // Create the socket 创建一个socket连接字
   _socket = _createXmlSocket();
   
   active = false;
   loggedIn = false;
   
   ///  创建流样式  <stream:flash>
   // Stream type lets user set opening/closing tag - some servers (jadc2s) prefer <stream:flash> to the standard
   // <stream:stream>
   switch( streamType ) {
    /////在xiff中用flash
    case "flash":
     openingStreamTag = new String( "<?xml version=\"1.0\"?><flash:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:flash=\"http://www.jabber.com/streams/flash\" version=\"1.0\">" );
     closingStreamTag = new String( "</flash:stream>" );
     break;
     
    case "terminatedFlash":
     openingStreamTag = new String( "<?xml version=\"1.0\"?><flash:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:flash=\"http://www.jabber.com/streams/flash\" version=\"1.0\" />" );
     closingStreamTag = new String( "</flash:stream>" );
     break;
     
    case "standard":
     openingStreamTag = new String( "<?xml version=\"1.0\"?><stream:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">" );
     closingStreamTag = new String( "</stream:stream>" );
     break;
   
    case "terminatedStandard":
    default:
     openingStreamTag = new String( "<?xml version=\"1.0\"?><stream:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" />" );
     closingStreamTag = new String( "</stream:stream>" );
     break;
   }
   //链接到服务器如果成功返回true
   _socket.connect( server, port );
   return true;
  }
  
  /**
   * 关闭与服务器的连接
   * Disconnects from the server if currently connected. After disconnect,
   * a <code>DisconnectionEvent.DISCONNECT</code> event is broadcast.
   */
  public function disconnect():void
  {
   //如果链接是活动的,发送一个关闭流  设置活动状态为false
   if( isActive() ) {
    sendXML( closingStreamTag );
    _socket.close();
    active = false;
    loggedIn = false;
    var event:DisconnectionEvent = new DisconnectionEvent();
    dispatchEvent(event);
    //将关闭连接这个事件分发( 广播)
   }
  }
  
  /**
   * Sends data to the server. If the data to send cannot be serialized properly, this method throws a <code>SerializeException</code>.
   *发送数据给服务器,如果数据不能被序列号则不能被发送
   * @param o The data to send. This must be an instance of a class that implements the ISerializable interface.
  * 参数必须是已经实现了ISerriable接口的实例
   *  * @see org.jivesoftware.xiff.data.ISerializable
   * @example The following example sends a basic chat message to the user with the JID "sideshowbob@springfieldpenitentiary.gov".<br />
   * <pre>var msg:Message = new Message( "sideshowbob@springfieldpenitentiary.gov", null, "Hi Bob.", "<b>Hi Bob.</b>", Message.CHAT_TYPE );
   * myXMPPConnection.send( msg );</pre>
   */
  public function send( o:XMPPStanza ):void
  {
   if( isActive() ) {
    ///主要是处理  IQ(info 、query)
    if( o is IQ ) {
                 var iq:IQ = o as IQ;
                 if ((iq.callbackName != null && iq.callbackScope != null) || iq.callback != null)
                 {
                  addIQCallbackToPending( iq.id, iq.callbackName, iq.callbackScope, iq.callback );
                 }  
    }
    var root:XMLNode = o.getNode().parentNode;
    if (root == null) {
     root = new XMLDocument();
    }
 
    if (o.serialize(root)) {
     sendXML( root.firstChild );
    } else {
     throw new SerializationException();
    }
   }
  }
  ///发送一个空包,保持这个联结
  public function sendKeepAlive():void
  {
   if( isActive() ) {
    sendXML(" ");
   }
  }
  
  /**
   * Determines whether the connection with the server is currently active. (Not necessarily logged in.
   * For login status, use the <code>isLoggedIn()</code> method.)
   * 检测这个连接是否是活动的
   * @return A boolean indicating whether the connection is active.
   * @see org.jivesoftware.xiff.core.XMPPConnection#isLoggedIn
   */
  public function isActive():Boolean
  {
   return active;
  }
  
  /**
   * Determines whether the user is connected and logged into the server.
   * 判断用户是否已经登陆
   * @return A boolean indicating whether the user is logged in.
   * @see org.jivesoftware.xiff.core.XMPPConnection#isActive
   */
  public function isLoggedIn():Boolean
  {
   return loggedIn;
  }
  
  /**
   * Issues a request for the information that must be submitted for registration with the server.
   * 发布一个请求去获取必须提交的信息以用来向服务器注册,注册用户时用到
   * When the data returns, a <code>RegistrationFieldsEvent.REG_FIELDS</code> event is dispatched
   * containing the requested data.
   */
  public function getRegistrationFields():void
  {
   var regIQ:IQ = new IQ( new JID(server), IQ.GET_TYPE, XMPPStanza.generateID("reg_info_"), "getRegistrationFields_result", this, null);
   regIQ.addExtension(new RegisterExtension(regIQ.getNode()));
 
   send( regIQ );
  }
  
  /**
   * Registers a new account with the server, sending the registration data as specified in the fieldMap paramter.
   * 向服务注册一个新的帐号,发送注册所需的数据
   * @param fieldMap An object map containing the data to use for registration. The map should be composed of
   * attribute:value pairs for each registration data item.
   * @param key (Optional) If a key was passed in the "data" field of the "registrationFields" event,
   * that key must also be passed here.
   * required field needed for registration.
   */
  public function sendRegistrationFields( fieldMap:Object, key:String ):void
  {
   var regIQ:IQ = new IQ( new JID(server), IQ.SET_TYPE, XMPPStanza.generateID("reg_attempt_"), "sendRegistrationFields_result", this, null );
   var ext:RegisterExtension = new RegisterExtension(regIQ.getNode());
 
   for( var i:String in fieldMap ) {
    ext[i] = fieldMap[i];
   }
   if (key != null) {
    ext.key = key;
   }
 
   regIQ.addExtension(ext);
   send( regIQ );
  }
  
  /**
   * Changes the user's account password on the server. If the password change is successful,
   * the class will broadcast a <code>ChangePasswordSuccessEvent.PASSWORD_SUCCESS</code> event.
   *变更用户帐号密码, 如果成功将会触发事件:ChangePasswordSuccessEvent.PASSWORD_SUCCESS
   * @param newPassword The new password
   */
  public function changePassword( newPassword:String ):void
  {
   var passwdIQ:IQ = new IQ( new JID(server), IQ.SET_TYPE, XMPPStanza.generateID("pswd_change_"), "changePassword_result", this, null );
   var ext:RegisterExtension = new RegisterExtension(passwdIQ.getNode());
 
   ext.username = jid.toBareJID();
   ext.password = newPassword;
 
   passwdIQ.addExtension(ext);
   send( passwdIQ );
  }
  
  /**
   * Gets the fully qualified JID (user@server/resource) of the user. A fully-qualified JID includes
   * the resource. A bare JID does not. To get the bare JID, use the <code>getBareJID()</code> method.
   * 返回一个完整的jid user@server/resource
   * @return The fully qualified JID
   * @see #getBareJID
   */
  public function get jid():JID
  {
   return new JID(myUsername + "@" + myServer + "/" + myResource);
  }
  
  /**
   * @private  修改密码的返回情况
   */
  protected function changePassword_result( resultIQ:IQ ):void
  {
   if( resultIQ.type == IQ.RESULT_TYPE ) {
    var event:ChangePasswordSuccessEvent = new ChangePasswordSuccessEvent();
    dispatchEvent(event);
   }
   else {
    // We weren't expecting this
    ////400  修改密码错误
    dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
   }
  }
  
  /**
   * @private 注册用户的返回情况
   */
  protected function getRegistrationFields_result( resultIQ:IQ ):void
  {
   try
   {
    var ext:RegisterExtension = resultIQ.getAllExtensionsByNS(RegisterExtension.NS)[0];
    var fields:Array = ext.getRequiredFieldNames(); //TODO, phase this out
    
    var event:RegistrationFieldsEvent = new RegistrationFieldsEvent();
    event.fields = fields;
    event.data = ext;
   }
   catch (e:Error)
    {
     trace(e.getStackTrace());
    }
  }
  
  /**
   * @private
   */
  protected function sendRegistrationFields_result( resultIQ:IQ ):void
  {
   if( resultIQ.type == IQ.RESULT_TYPE ) {

    var event:RegistrationSuccessEvent = new RegistrationSuccessEvent();
    dispatchEvent( event );
   }
   else {
    // We weren't expecting this
    dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
   }
  }
  
  // Listener function from the ListenerXMLSocket
  /**
   * @private
   */
  protected function socketConnected(ev:Event):void
  {
   active = true;
   sendXML( openingStreamTag );
   var event:ConnectionSuccessEvent = new ConnectionSuccessEvent();
   dispatchEvent( event );
  }
  
  /**
   * @private
   */
  protected function socketReceivedData( ev:DataEvent ):void
  {
   // parseXML is more strict in AS3 so we must check for the presence of flash:stream
   // the unterminated tag should be in the first string of xml data retured from the server
   if (!_expireTagSearch)
   {
    var pattern:RegExp = new RegExp("<flash:stream");
    var resultObj:Object = pattern.exec(ev.data);
    if (resultObj != null) // stop searching for unterminated node
    {
     ev.data = ev.data.concat("</flash:stream>");
     _expireTagSearch = true;
    }
   }
   
   if(ev.data == "</flash:stream>")
   {
    socketClosed(null);
    return; 
   } 
   
   var xmlData:XMLDocument = new XMLDocument();
   xmlData.ignoreWhite = this.ignoreWhite;
   xmlData.parseXML( ev.data );
   
   var event:IncomingDataEvent = new IncomingDataEvent();
   event.data = xmlData;
   dispatchEvent( event );
   
   // Read the data and send it to the appropriate parser
   var firstNode:XMLNode = xmlData.firstChild;
   var nodeName:String = firstNode.nodeName.toLowerCase();
   //trace("RECV: " + firstNode);
   switch( nodeName )
   {
    case "stream:stream":
    case "flash:stream":
     _expireTagSearch = false;
     handleStream( firstNode );
     break;
     
    case "stream:error":
     handleStreamError( firstNode );
     break;
     
    case "iq":
     handleIQ( firstNode );
     break;
     
    case "message":
     handleMessage( firstNode );
     break;
     
    case "presence":
     handlePresence( firstNode );
     break;
     
    case "stream:features":
     break;
     
    default:
     // silently ignore lack of or unknown stanzas
     // if the app designer wishes to handle raw data they
     // can on "incomingData".
 
     // Use case: received null byte, XMLSocket parses empty document
     // sends empty document
     
     // I am enabling this for debugging
     dispatchError( "undefined-condition", "Unknown Error", "modify", 500 );
     break;
   }
  }
  
  /**
   * @private
   */
  protected function socketClosed(e:Event):void
  { 
   var event:DisconnectionEvent = new DisconnectionEvent();
   dispatchEvent( event );
  }
  
  /**
   * @private
   */
  protected function handleStream( node:XMLNode ):void
  {
   sessionID = node.attributes.id;
   server = node.attributes.from;
   
   if(_useAnonymousLogin) {
    // Begin anonymous login
    sendAnonymousLogin();
   } else if( username != null && username.length > 0 ) {
    // Begin login sequence
    beginAuthentication();
   } else {
    //get registration fields
    getRegistrationFields();
   }
  }
  
  /**
   * @private
   */
  protected function handleStreamError( node:XMLNode ):void
  {
   dispatchError( "service-unavailable", "Remote Server Error", "cancel", 502 );
   
   // Cancel everything by closing connection
   try {
    _socket.close();
   }
   catch (error:Error){
    
   }
   active = false;
   loggedIn = false;
   var event:DisconnectionEvent = new DisconnectionEvent();
   
   dispatchEvent( event );
  }
  
  protected function set active(flag:Boolean):void
  {
   if(flag)
   {
    _openConnections.push(this);
   }
   else
   {
    _openConnections.splice(_openConnections.indexOf(this), 1);
   }
   _active = flag;
  }
  
  protected function get active():Boolean
  {
   return _active;
  }
  
  public static function get openConnections():Array
  {
   return _openConnections;
  }
  
  /**
   * @private
   */
  protected function handleIQ( node:XMLNode ):IQ
  {
   var iq:IQ = new IQ();
   // Populate the IQ with the incoming data
   if( !iq.deserialize( node ) ) {
    throw new SerializationException();
   }
   
   // If it's an error, handle it
   
   if( iq.type == IQ.ERROR_TYPE && !pendingIQs[iq.id]) {
    dispatchError( iq.errorCondition, iq.errorMessage, iq.errorType, iq.errorCode );
   }
   else {
    
    // Start the callback for this IQ if one exists
    if( pendingIQs[iq.id] !== undefined ) {
     var callbackInfo:* = pendingIQs[iq.id];
     
     if(callbackInfo.methodScope && callbackInfo.methodName) {
      callbackInfo.methodScope[callbackInfo.methodName].apply( callbackInfo.methodScope, [iq] );
     }   
     if (callbackInfo.func != null) {
      callbackInfo.func( iq );
     }
     pendingIQs[iq.id] = null;
     delete pendingIQs[iq.id];
    }
    else {
     var exts:Array = iq.getAllExtensions();
     for (var ns:String in exts) {
      // Static type casting
      var ext:IExtension = exts[ns] as IExtension;
      if (ext != null) {
       var event:IQEvent = new IQEvent(ext.getNS());
       event.data = ext;
       event.iq = iq;
       dispatchEvent( event );
      }
     }
    }
   }
         return iq;
  }
  
  /**
   * @private
   */
  protected function handleMessage( node:XMLNode ):Message
  {
   var msg:Message = new Message();
   //trace(msg); 
   // Populate with data
   if( !msg.deserialize( node ) ) {
    throw new SerializationException();
   }
   // ADDED in error handling for messages
   if( msg.type == Message.ERROR_TYPE ) {
    dispatchError( msg.errorCondition, msg.errorMessage, msg.errorType, msg.errorCode );
   }
   else
   {
    var event:MessageEvent = new MessageEvent();
    event.data = msg;
    dispatchEvent( event );  
   }
         return msg;
  }
  
  /**
   * @private
   */
  private var presenceQueue:Array = [];
  private var presenceQueueTimer:Timer;
  protected function handlePresence( node:XMLNode ):Presence
  {
   if(!presenceQueueTimer)
   {
    presenceQueueTimer = new Timer(1, 1);
    presenceQueueTimer.addEventListener(TimerEvent.TIMER_COMPLETE, flushPresenceQueue);
   }
   
   var pres:Presence = new Presence();
   
   // Populate
   if( !pres.deserialize( node ) ) {
    throw new SerializationException();
   }
   
   presenceQueue.push(pres);
   
   presenceQueueTimer.reset();
   presenceQueueTimer.start();

         return pres;
  }
  
  protected function flushPresenceQueue(evt:TimerEvent):void
  {
   var event:PresenceEvent = new PresenceEvent();
   event.data = presenceQueue;
   dispatchEvent( event );
   presenceQueue = [];
  }
  
  /**
   * @private
   */
  protected function onIOError(event:IOErrorEvent):void{
   /*
   this fires the standard dispatchError method. need to add
   the appropriate error code
   */
   dispatchError( "service-unavailable", "Service Unavailable", "cancel", 503 );
  }
  
  /**
   * @private
   */
  protected function securityError(event:SecurityErrorEvent):void{
   trace("there was a security error of type: " + event.type + "\nError: " + event.text);
   dispatchError( "not-authorized", "Not Authorized", "auth", 401 );
  }
  
  /**
   * @private
   */
  protected function dispatchError( condition:String, message:String, type:String, code:Number ):void
  {
   var event:XIFFErrorEvent = new XIFFErrorEvent();
   event.errorCondition = condition;
   event.errorMessage = message;
   event.errorType = type;
   event.errorCode = code;
   dispatchEvent( event );
  }
  
  /**
   * @private
   */
  protected function sendXML( someData:* ):void
  {
   //trace("SEND: " + someData);
   // Data is untyped because it could be a string or XML
   _socket.send( someData );
   var event:OutgoingDataEvent = new OutgoingDataEvent();
   event.data = someData;
   dispatchEvent( event );
  }
  
  // anonymous login
  /**
   * @private
   */
  protected function sendAnonymousLogin():void
  {
   var anonIQ:IQ = new IQ(null, IQ.SET_TYPE, XMPPStanza.generateID("log_anom_"), "sendAnonymousLogin_result", this, null );
   var authExt:AuthExtension = new AuthExtension(anonIQ.getNode());
   anonIQ.addExtension(authExt);
   send(anonIQ);
  }
  
  /**
   * @private
   */
  protected function sendAnonymousLogin_result(resultIQ:IQ):void
  {resultIQ
   if( resultIQ.type == IQ.RESULT_TYPE ) {
    // update resource
    var jid:JID = resultIQ.to;
    resource = jid.resource;
    username = jid.node;
    // dispatch login event
    loggedIn = true;
    var event:LoginEvent = new LoginEvent();
    dispatchEvent( event );
   }
  }
  
  /**
   * @private
   */
  protected function beginAuthentication():void
  {
   var authIQ:IQ = new IQ( null, IQ.GET_TYPE, XMPPStanza.generateID("log_user_"), "beginAuthentication_result", this, null );
   var authExt:AuthExtension = new AuthExtension(authIQ.getNode());
   authExt.username = username
   
   authIQ.addExtension(authExt);
   send( authIQ );
  }
  
  /**
   * @private
   */
  protected function beginAuthentication_result( resultIQ:IQ ):void
  {
   var connectionType:String = "none";
 
   // Begin authentication procedure
   if( resultIQ.type == IQ.RESULT_TYPE ) {
    var authIQ:IQ = new IQ( null, IQ.SET_TYPE, XMPPStanza.generateID("log_user2_"), "sendAuthentication_result", this, null );
    try
    {
     var resultAuth:* = resultIQ.getAllExtensionsByNS(AuthExtension.NS)[0];
     var responseAuth:AuthExtension = new AuthExtension(authIQ.getNode());
     responseAuth.password = password;
     responseAuth.username = username;
     responseAuth.resource = resource;
     authIQ.addExtension(responseAuth);
     send( authIQ );
    }
    catch (e:Error)
    {
     trace("Error : null trapped. Resuming.");
    }
   }
   else {
    // We weren't expecting this
    dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
   }
  }
  
  /**
   * @private
   */
  protected function sendAuthentication_result( resultIQ:IQ ):void
  {
   if( resultIQ.type == IQ.RESULT_TYPE ) {
    loggedIn = true;
    var event:LoginEvent = new LoginEvent();
    dispatchEvent( event );
   }
   else {
    // We weren't expecting this
    dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
   }
  }
  
  /**
   * @private
   */
  protected function addIQCallbackToPending( id:String, callbackName:String, callbackScope:Object, callbackFunc:Function ):void
  {
   pendingIQs[id] = {methodName:callbackName, methodScope:callbackScope, func:callbackFunc};
  }
  
  /**
   * The XMPP server to use for connection.
   */
  public function get server():String
  {
   return myServer;
  }
  
  /**
   * @private
   */
  public function set server( theServer:String ):void
  {
   myServer = theServer;
  }
  
  /**
   * The username to use for connection. If this property is null when <code>connect()</code> is called,
   * the class will fetch registration field data rather than attempt to login.
   */
  public function get username():String
  {
   return myUsername;
  }
  
  /**
   * @private
   */
  public function set username( theUsername:String ):void
  {
   myUsername = theUsername;
  }
  
  /**
   * The password to use when logging in.
   */
  public function get password():String
  {
   return myPassword;
  }
  
  public function set password( thePassword:String ):void
  {
   myPassword = thePassword;
  }
  
  /**
   * The resource to use when logging in. A resource is required (defaults to "XIFF") and
   * allows a user to login using the same account simultaneously (most likely from multiple machines).
   * Typical examples of the resource include "Home" or "Office" to indicate the user's current location.
   */
  public function get resource():String
  {
   return myResource;
  }
  
  /**
   * @private
   */
  public function set resource( theResource:String ):void
  {
   if( theResource.length > 0 )
   {
    myResource = theResource;
   }
  }
  
  /**
   * Whether to use anonymous login or not.
   */
  public function get useAnonymousLogin():Boolean
  {
   return _useAnonymousLogin;
  }
  
  /**
   * @private
   */
  public function set useAnonymousLogin(value:Boolean):void
  {
   // set only if not connected
   if(!isActive()) _useAnonymousLogin = value;
  }
  
  /**
   * The port to use when connecting. The default XMPP port is 5222.
   */
  public function get port():Number
  {
   return myPort;
  }
  
  public function set port( portNum:Number ):void
  {
   myPort = portNum;
  }
 
  /**
   * Determines whether whitespace will be ignored on incoming XML data.
   * Behaves the same as <code>XML.ignoreWhite</code>
   */
  public function get ignoreWhite():Boolean
  {
   return ignoreWhitespace;
  }
 
  public function set ignoreWhite( val:Boolean ):void
  {
   ignoreWhitespace = val;
  }
  
  private function _createXmlSocket():XMLSocket {
   var socket:XMLSocket = new XMLSocket(server, port);
   socket.addEventListener(Event.CONNECT,socketConnected);
   socket.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
   socket.addEventListener(Event.CLOSE,socketClosed);
   socket.addEventListener(DataEvent.DATA,socketReceivedData);
   socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityError);
   return socket;
  }
 }
}



大盘预测 国富论
posted on 2008-03-26 14:59 华梦行 阅读(3251) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: