iOS推送javaPNS源码解析六,连接管理类

连接管理类ConnectionToAppleServer,话说客户端服务器都准备完了,该连接了,连接到服务器的类设计方式是:由于连接到服务器是一个动作对象,该对象有很多方法,并且要实例化各种连接配置,所以顶级类设计为了一个抽象类。

连接这个类使用了TLS加密连接,为了掩饰本人不好的加密基础,这个类的源码如下

/* KeyManagerFactory 使用的算法,默认是sun公司的suunx509,除非特定的ibM环境才换成ibmx509 */
 private static final String ALGORITHM = ((Security.getProperty(“ssl.KeyManagerFactory.algorithm”) == null) ? “sunx509″ : Security.getProperty(“ssl.KeyManagerFactory.algorithm”));

 /* 使用TLS协议 */
 private static final String PROTOCOL = “TLS”;

 /* PKCS12,对应p12证书 */
 public static final String KEYSTORE_TYPE_PKCS12 = “PKCS12″;
 /* 数字证书库*/
 public static final String KEYSTORE_TYPE_JKS = “JKS”;

 static {

//加密使用的是BouncyCastleProvider
  Security.addProvider(new BouncyCastleProvider());
 }

 private KeyStore keyStore;
 private SSLSocketFactory socketFactory;
 private AppleServer server;

//三个属性
//属性的set/get方法和类构造方法就不在一一说。

//创建SSLSocketFacotry

protected SSLSocketFactory createSSLSocketFactoryWithTrustManagers(TrustManager[] trustManagers) throws KeystoreException {

  logger.debug(“Creating SSLSocketFactory”);
  // 获取key管理器并初始化
  try {
   KeyStore keystore = getKeystore();
   KeyManagerFactory kmf = KeyManagerFactory.getInstance(ALGORITHM);
   try {
    char[] password = KeystoreManager.getKeystorePasswordForSSL(server);
    kmf.init(keystore, password);
   } catch (Exception e) {
    e = KeystoreManager.wrapKeystoreException(e);
    throw e;
   }

   // 获取 SSLContext 去创建SSLSocketFactory   
   SSLContext sslc = SSLContext.getInstance(PROTOCOL);

//初始化SSLContext 
   sslc.init(kmf.getKeyManagers(), trustManagers, null);

//获取创建工厂

   return sslc.getSocketFactory();
  } catch (Exception e) {
   throw new KeystoreException(“Keystore exception: ” + e.getMessage(), e);
  }
 }
 public SSLSocketFactory createSSLSocketFactory() throws KeystoreException {
  return createSSLSocketFactoryWithTrustManagers(new TrustManager[] { new ServerTrustingTrustManager() });
 }

//ServerTrustingTrustManager信任所有服务器
 public SSLSocketFactory getSSLSocketFactory() throws KeystoreException {
  if (socketFactory == null) socketFactory = createSSLSocketFactory();
  return socketFactory;
 }

//获取SSLSocket连接

public SSLSocket getSSLSocket() throws KeystoreException, CommunicationException {
  SSLSocketFactory socketFactory = getSSLSocketFactory();
  logger.debug(“Creating SSLSocket to ” + getServerHost() + “:” + getServerPort());

  try {
   if (ProxyManager.isUsingProxy(server)) {

//如果服务器配置了代理就去校验
    return tunnelThroughProxy(socketFactory);
   } else {

//否则创建一个
    return (SSLSocket) socketFactory.createSocket(getServerHost(), getServerPort());
   }
  } catch (Exception e) {
   throw new CommunicationException(“Communication exception: ” + e, e);
  }
 }

//校验原有的服务器代理信息

private SSLSocket tunnelThroughProxy(SSLSocketFactory socketFactory) throws UnknownHostException, IOException {
  SSLSocket socket;

  //如果已经设置那么根据设置好的地址和端口
  String tunnelHost = ProxyManager.getProxyHost(server);
  Integer tunnelPort = ProxyManager.getProxyPort(server);

  Socket tunnel = new Socket(tunnelHost, tunnelPort);
  doTunnelHandshake(tunnel, getServerHost(), getServerPort());

  /* overlay the tunnel socket with SSL */
  socket = (SSLSocket) socketFactory.createSocket(tunnel, getServerHost(), getServerPort(), true);

  /* 添加握手回调函数监听*/
  socket.addHandshakeCompletedListener(new HandshakeCompletedListener() {
   public void handshakeCompleted(HandshakeCompletedEvent event) {
    logger.debug(“Handshake finished!”);
    logger.debug(“\t CipherSuite:” + event.getCipherSuite());
    logger.debug(“\t SessionId ” + event.getSession());
    logger.debug(“\t PeerHost ” + event.getSession().getPeerHost());
   }
  });

  return socket;
 }

//判断是否服务器能正常访问
 private void doTunnelHandshake(Socket tunnel, String host, int port) throws IOException {

  OutputStream out = tunnel.getOutputStream();

  String msg = “CONNECT ” + host + “:” + port + ” HTTP/1.0\n” + “User-Agent: BoardPad Server” + “\r\n\r\n”;
  byte b[] = null;
  try { //We really do want ASCII7 — the http protocol doesn’t change with locale.
   b = msg.getBytes(“ASCII7″);
  } catch (UnsupportedEncodingException ignored) { //If ASCII7 isn’t there, something serious is wrong, but Paranoia Is Good ™
   b = msg.getBytes();
  }
  out.write(b);
  out.flush();

  // We need to store the reply so we can create a detailed error message to the user.
  byte reply[] = new byte[200];
  int replyLen = 0;
  int newlinesSeen = 0;
  boolean headerDone = false; //Done on first newline

  InputStream in = tunnel.getInputStream();

  while (newlinesSeen < 2) {
   int i = in.read();
   if (i < 0) {
    throw new IOException(“Unexpected EOF from proxy”);
   }
   if (i == ‘\n’) {
    headerDone = true;
    ++newlinesSeen;
   } else if (i != ‘\r’) {
    newlinesSeen = 0;
    if (!headerDone && replyLen < reply.length) {
     reply[replyLen++] = (byte) i;
    }
   }
  }

  /*
   * Converting the byte array to a string is slightly wasteful
   * in the case where the connection was successful, but it’s
   * insignificant compared to the network overhead.
   */
  String replyStr;
  try {
   replyStr = new String(reply, 0, replyLen, “ASCII7″);
  } catch (UnsupportedEncodingException ignored) {
   replyStr = new String(reply, 0, replyLen);
  }

  /* We check for Connection Established because our proxy returns HTTP/1.1 instead of 1.0 */
  if (replyStr.toLowerCase().indexOf(“200 connection established”) == -1) {
   throw new IOException(“Unable to tunnel through. Proxy returns \”” + replyStr + “\””);
  }

  /* tunneling Handshake was successful! */
 }

 

它的子类有两个一个是反馈服务器连接ConnectionToFeedbackServer一个是推送服务器连接ConnectionToNotificationServer。由于子类只是提供了服务器地址和端口,故不再说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值