TcpCirChannel.java
上传用户:szyujian
上传日期:2016-09-20
资源大小:320k
文件大小:8k
源码类别:

android开发

开发平台:

C/C++

  1. /*
  2.  * Copyright (C) 2007-2008 Esmertec AG.
  3.  * Copyright (C) 2007-2008 The Android Open Source Project
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package com.android.im.imps;
  18. import java.io.BufferedReader;
  19. import java.io.IOException;
  20. import java.io.InputStreamReader;
  21. import java.net.Socket;
  22. import java.net.UnknownHostException;
  23. import java.util.Vector;
  24. import com.android.im.engine.ImErrorInfo;
  25. import com.android.im.engine.ImException;
  26. import android.os.SystemClock;
  27. import android.util.Log;
  28. /**
  29.  * An implementation of CIR channel with standalone TCP/IP banding.
  30.  */
  31. class TcpCirChannel extends CirChannel implements Runnable{
  32.     public static final int PING_INTERVAL = 20 * 60 * 1000; // 20 min
  33.     private static final int OK_TIMEOUT = 30000;
  34.     private String mAddress;
  35.     private int mPort;
  36.     private boolean mDone;
  37.     private Socket mSocket;
  38.     private boolean mWaitForOK;
  39.     private long mLastActive;
  40.     private String mUser;
  41.     private BufferedReader mReader;
  42.     private static Vector<TcpCirChannel> sChannels;
  43.     static {
  44.         sChannels = new Vector<TcpCirChannel>();
  45.     }
  46.     public static Vector<TcpCirChannel> getChannels(){
  47.         return sChannels;
  48.     }
  49.     protected TcpCirChannel(ImpsConnection connection) {
  50.         super(connection);
  51.         mAddress = connection.getSession().getCirTcpAddress();
  52.         mPort = connection.getSession().getCirTcpPort();
  53.         mUser = connection.getSession().getLoginUser().getName();
  54.     }
  55.     @Override
  56.     public synchronized void connect() throws ImException {
  57.         try {
  58.             connectServer();
  59.             sChannels.add(this);
  60.             new Thread(this, "TcpCirChannel").start();
  61.         } catch (UnknownHostException e) {
  62.             throw new ImException(ImErrorInfo.UNKNOWN_SERVER,
  63.                     "Can't find the TCP CIR server");
  64.         } catch (IOException e) {
  65.             throw new ImException(ImErrorInfo.CANT_CONNECT_TO_SERVER,
  66.                     "Can't connect to the TCP CIR server");
  67.         }
  68.     }
  69.     @Override
  70.     public synchronized void shutdown() {
  71.         if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  72.             ImpsLog.log(mUser + " Shutting down CIR channel");
  73.         }
  74.         mDone = true;
  75.         sChannels.remove(this);
  76.         try {
  77.             if(mSocket != null) {
  78.                 mSocket.close();
  79.             }
  80.         } catch (IOException e) {
  81.             e.printStackTrace();
  82.         }
  83.     }
  84.     public void run() {
  85.         while (!mDone) {
  86.             try {
  87.                 if (mWaitForOK && SystemClock.elapsedRealtime() - mLastActive
  88.                         > OK_TIMEOUT) {
  89.                     // OMA-TS-IMPS_CSP_Transport-V1_3-20070123-A 8.1.3:
  90.                     // If client doesn't receive an "OK" message or detects
  91.                     // that the connection is broken, it MUST open a new
  92.                     // TCP/IP connection and send the "HELO" message again.
  93.                     connectServer();
  94.                 }
  95.                 String line = mReader.readLine();
  96.                 mLastActive = SystemClock.elapsedRealtime();
  97.                 if (line == null) {
  98.                     // socket closed by the server
  99.                     reconnect();
  100.                 } else if ("OK".equals(line)) {
  101.                     mWaitForOK = false;
  102.                     if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  103.                         ImpsLog.log(mUser + " << TCP CIR: OK Received");
  104.                     }
  105.                     // TODO: Since we just have one thread per TCP CIR
  106.                     // connection now, the session cookie is ignored.
  107.                 } else if (line.startsWith("WVCI")) {
  108.                     if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  109.                         ImpsLog.log(mUser + " << TCP CIR: CIR Received");
  110.                     }
  111.                     if (!mDone) {
  112.                         mConnection.sendPollingRequest();
  113.                     }
  114.                 }
  115.             } catch (IOException e) {
  116.                 ImpsLog.logError("TCP CIR channel get:" + e);
  117.                 if(!mDone){
  118.                     reconnect();
  119.                 }
  120.             }
  121.         }
  122.         if (mReader != null) {
  123.             try {
  124.                 mReader.close();
  125.             } catch (IOException e) {
  126.                 e.printStackTrace();
  127.             }
  128.         }
  129.         if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  130.             ImpsLog.log(mUser + " CIR channel thread quit");
  131.         }
  132.     }
  133.     @Override
  134.     public void reconnect() {
  135.         if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  136.             ImpsLog.log(mUser + " CIR channel reconnecting");
  137.         }
  138.         long waitTime = 3000;
  139.         while (!mDone) { // Keep trying to connect the server until shutdown
  140.             try {
  141.                 try {
  142.                     Thread.sleep(waitTime);
  143.                 } catch (InterruptedException e) {
  144.                 }
  145.                 connectServer();
  146.                 // Send a polling request to make sure we don't miss anything
  147.                 // while CIR is down.
  148.                 if(!mDone) {
  149.                     mConnection.sendPollingRequest();
  150.                 }
  151.                 return;
  152.             } catch (IOException e) {
  153.                 waitTime *= 3;
  154.                 if(waitTime > 27000) {
  155.                     waitTime = 3000;
  156.                     if(!mDone){
  157.                         mConnection.sendPollingRequest();
  158.                     }
  159.                 }
  160.                 if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  161.                     ImpsLog.log(mUser + " CIR channel reconnect fail, retry after "
  162.                         + waitTime / 1000 + " seconds");
  163.                 }
  164.             }
  165.         }
  166.     }
  167.     private synchronized void connectServer() throws IOException {
  168.         if(!mDone) {
  169.             if (mSocket != null) {
  170.                 try {
  171.                     mSocket.close();
  172.                 } catch (IOException e) {
  173.                     // ignore
  174.                 }
  175.             }
  176.             mSocket = new Socket(mAddress, mPort);
  177.             if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  178.                 ImpsLog.log(mUser + " >> TCP CIR: HELO");
  179.             }
  180.             sendData("HELO " + mConnection.getSession().getID() + "rn");
  181.             if (mReader != null) {
  182.                 try {
  183.                     mReader.close();
  184.                 } catch (IOException e) {
  185.                     // ignore
  186.                 }
  187.             }
  188.             mReader = new BufferedReader(
  189.                     new InputStreamReader(mSocket.getInputStream(), "UTF-8"),
  190.                     8192);
  191.         }
  192.     }
  193.     public synchronized void ping() {
  194.         long time = SystemClock.elapsedRealtime();
  195.         if(!mDone && time - mLastActive > PING_INTERVAL) {
  196.             if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  197.                 ImpsLog.log(mUser + " >> TCP CIR: PING");
  198.             }
  199.             try {
  200.                 sendData("PING rn");
  201.             } catch (IOException e) {
  202.                 if (Log.isLoggable(ImpsLog.TAG, Log.DEBUG)) {
  203.                     ImpsLog.log("Failed to send PING, try to reconnect");
  204.                 }
  205.                 reconnect();
  206.             }
  207.         }
  208.     }
  209.     private void sendData(String s) throws IOException {
  210.         mSocket.getOutputStream().write(s.getBytes("UTF-8"));
  211.         mWaitForOK = true;
  212.         mLastActive = SystemClock.elapsedRealtime();
  213.     }
  214. }