Package net.solosky.maplefetion.client.dialog

Source Code of net.solosky.maplefetion.client.dialog.LiveV1ChatDialog

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Project  : MapleFetion2
* Package  : net.solosky.maplefetion.client.dialog
* File     : LiveV1ChatDialog.java
* Author   : solosky < solosky772@qq.com >
* Created  : 2010-1-14
* License  : Apache License 2.0
*/
package net.solosky.maplefetion.client.dialog;

import net.solosky.maplefetion.FetionConfig;
import net.solosky.maplefetion.FetionContext;
import net.solosky.maplefetion.bean.Buddy;
import net.solosky.maplefetion.bean.Message;
import net.solosky.maplefetion.client.response.SendChatMessageResponseHandler;
import net.solosky.maplefetion.event.action.ActionEventListener;
import net.solosky.maplefetion.net.RequestTimeoutException;
import net.solosky.maplefetion.net.TransferException;
import net.solosky.maplefetion.sipc.SipcNotify;
import net.solosky.maplefetion.sipc.SipcOutMessage;
import net.solosky.maplefetion.sipc.SipcRequest;
import net.solosky.maplefetion.sipc.SipcStatus;
import net.solosky.maplefetion.util.CallHelper;
import net.solosky.maplefetion.util.ObjectWaiter;
import net.solosky.maplefetion.util.ResponseFuture;

/**
*
* 第一版和在线好友聊天对话框
*
* <pre>
* 这个对话框是以前飞信版本采用的和在线好友聊天的协议,是通过服务器建立会话的
* 飞信在2008版本升级为第二版,采用了另外一个聊天服务器建立会话, 现在这种对话主要用在HTTP通信模式下和在线好友建立会话
*
* 这中对话建立的方式比较简单:
*
* 假如A邀请B建立会话,简单的流程是这样的:
*   1. A给主服务器说,我要和B建立会话,这是我的IP,服务器说,请稍等我去通知B;
*   2. 过了一会儿,服务器说,我已经成功的邀请了B;
*   3. A回复给主服务器说,我已经知道了,谢谢;
*   之后双方就可以互相发送信息。。。
*  
* 加入A被B邀请进入会话,流程如下:
*   1. 主服务器告诉A,B想邀请你进入会话,你同意不;
*   2. A回复主服务器,我同意加入会话;
*   会话就建立成功了。。
*  
*   任何一方离开,都会给对方发送离开通知,并结束这个对话。
* </pre>
*
*
* @author solosky <solosky772@qq.com>
*/
public class LiveV1ChatDialog extends ChatDialog
{

  /**
   * callHelper
   */
  private CallHelper callHelper;

  /**
   * 邀请通知
   */
  private SipcNotify inviteNotify;
 
  /**
   * 等待对方确认的等待对象
   */
  private ObjectWaiter<Boolean> ackWaiter;

  /**
   * 主动建立会话
   *
   * @param mainBuddy
   * @param client
   */
  public LiveV1ChatDialog(Buddy mainBuddy, FetionContext client)
  {
    super(mainBuddy, client);
    this.callHelper = new CallHelper();
    this.ackWaiter  = new ObjectWaiter<Boolean>();
  }

  /**
   * 被邀请建立会话
   *
   * @param inviteNotify
   * @param client
   */
  public LiveV1ChatDialog(SipcNotify inviteNotify, FetionContext client)
  {
    super(client);
    this.inviteNotify = inviteNotify;
    this.ackWaiter    = new ObjectWaiter<Boolean>();
    this.callHelper   = new CallHelper(inviteNotify.getCallID());
    this.mainBuddy    = client.getFetionStore().getBuddyByUri(
            inviteNotify.getFrom());
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * net.solosky.maplefetion.client.dialog.ChatDialog#isMutipartySupported()
   */
  @Override
  public boolean isMutipartySupported()
  {
    return false;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * net.solosky.maplefetion.client.dialog.ChatDialog#sendChatMessage(java
   * .lang.String, net.solosky.maplefetion.client.dialog.ActionEventListener)
   */
  @Override
  public void sendChatMessage(Message message, ActionEventListener listener)
  {
    this.ensureOpened();
    SipcRequest req = this.getMessageFactory().createSendChatMessageRequest(this.mainBuddy.getUri(), message);
    callHelper.set(req);
    req.setResponseHandler(new SendChatMessageResponseHandler(context, this, listener));
    this.process(req);
    this.updateActiveTime();
  }

  /*
   * (non-Javadoc)
   *
   * @see net.solosky.maplefetion.client.dialog.Dialog#doCloseDialog()
   */
  @Override
  protected void doCloseDialog() throws Exception
  {
    if(!this.context
        .getDialogFactory()
        .getServerDialog()
        .getProcessorChain()
        .isChainClosed()) {
              this.bye();
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see net.solosky.maplefetion.client.dialog.Dialog#doOpenDialog()
   */
  @Override
  protected void doOpenDialog() throws Exception
  {
    //只有主动打开对话才会发出邀请请求,如果是被动邀请,什么也不需要做
    if (!this.isBeenInvited()) {
      this.invite();
      this.ack();
    }else {
      int waitTimeout = FetionConfig.getInteger("fetion.dialog.wait-buddy-enter-timeout")*1000;
      this.ackWaiter.waitObject(waitTimeout);
    }


  }

  /*
   * (non-Javadoc)
   *
   * @see
   * net.solosky.maplefetion.client.dialog.Dialog#process(net.solosky.maplefetion
   * .sipc.SipcOutMessage)
   */
  @Override
  public void process(SipcOutMessage out)
  {
    this.context.getDialogFactory().getServerDialog().process(out);
  }

  /*
   * (non-Javadoc)
   *
   * @see net.solosky.maplefetion.client.dialog.Dialog#getMessageFactory()
   */
  @Override
  public MessageFactory getMessageFactory()
  {
    return this.context.getDialogFactory().getServerDialog()
            .getMessageFactory();
  }

  /**
   * 邀请对方加入会话
   *
   * @throws TransferException
   * @throws RequestTimeoutException
   * @throws InterruptedException
   * @throws IllegalResponseException
   */
  private void invite() throws TransferException, RequestTimeoutException,
          InterruptedException, IllegalResponseException
  {
    SipcRequest request = this.getMessageFactory()
            .createInviteRequest(
                    this.mainBuddy.getUri(),
                    this.context.getTransferFactory()
                            .getDefaultTransferLocalPort());
    this.callHelper.set(request);
    ResponseFuture future = ResponseFuture.wrap(request);
    this.process(request);

    int status = future.waitResponse().getStatusCode();
    if (status == SipcStatus.TRYING) {
      assertStatus(future.waitResponse().getStatusCode(),
              SipcStatus.ACTION_OK);
    } else if (status == SipcStatus.ACTION_OK) {
    } else {
      throw new IllegalResponseException("Unexpected response status");
    }
  }

  /**
   * 确认会话已经建立
   *
   * @throws TransferException
   */
  private void ack() throws TransferException
  {
    // 这个请求不需要回复
    SipcRequest request = this.getMessageFactory().createAckRequest(
            this.mainBuddy.getUri());
    this.callHelper.set(request);
    this.process(request);
  }

  /**
   * 离开对话
   *
   * @throws TransferException
   */
  private void bye() throws TransferException
  {
    SipcRequest request = this.getMessageFactory().createLogoutRequest(
            this.mainBuddy.getUri());
    this.process(request);
  }

  /**
   * 用户是否被邀请进入这个对话框的
   *
   * @return
   */
  public boolean isBeenInvited()
  {
    return this.inviteNotify != null;
  }
 
  public String toString()
    {
      return "[LiveV1ChatDialog - " +
          "MainBuddy="+mainBuddy.getDisplayName()+", "+mainBuddy.getUri()+" ]";
    }
 
  /**
   * 当服务器返回会话确认的时候回调
   * 只有当邀请加入会话的时候才会回调
   */
    public void dialogOpened()
    {
      this.setState(DialogState.OPENED);
      this.ackWaiter.objectArrive(true);
    }

}
TOP

Related Classes of net.solosky.maplefetion.client.dialog.LiveV1ChatDialog

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.