/* * ClientConnection.java * * Created on 13 Февраль 2011 г., 16:39 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package protocol.net; import java.util.Vector; import jimm.Jimm; import jimm.JimmException; import jimm.chat.message.PlainMessage; import jimm.modules.*; import protocol.Protocol; /** * * @author Vladimir Kryukov */ public abstract class ClientConnection implements Runnable { private long keepAliveInterval; private boolean usePong; protected boolean connect; private Vector<PlainMessage> messages = new Vector<PlainMessage>(); // ping only private long nextPingTime; private long pongTime; private static final int PING_INTERVAL = 90 /* sec */; private static final int PONG_TIMEOUT = 4 * 60 /* sec */; protected final void setPingInterval(long interval) { keepAliveInterval = Math.min(keepAliveInterval, interval); nextPingTime = Jimm.getCurrentGmtTime() + keepAliveInterval; } protected final long getPingInterval() { return keepAliveInterval; } protected final void usePong() { if (Jimm.getJimm().phone.isCedar()) { return; } usePong = true; updateTimeout(); } private void initPingValues() { usePong = false; keepAliveInterval = PING_INTERVAL; nextPingTime = Jimm.getCurrentGmtTime() + keepAliveInterval; } public final void start() { new Thread(this).start(); } public final void run() { initPingValues(); JimmException exception = null; try { getProtocol().setConnectingProgress(0); connect(); while (isConnected()) { boolean doing = processPacket(); if (!doing) { sleep(250); doPingIfNeeded(); } } } catch (JimmException e) { exception = e; } catch (OutOfMemoryError err) { exception = new JimmException(100, 2); } catch (Exception ex) { // #sijapp cond.if modules_DEBUGLOG is "true" # if (null != getProtocol()) { DebugLog.panic("die " + getId(), ex); } // #sijapp cond.end# exception = new JimmException(100, 1); } if (null != exception) { try { Protocol p = getProtocol(); if (null != p) { p.processException(exception); } } catch (Exception ex) { // #sijapp cond.if modules_DEBUGLOG is "true" # DebugLog.panic("die2 " + getId(), ex); // #sijapp cond.end# } } disconnect(); try { closeSocket(); } catch (Exception e) { // #sijapp cond.if modules_DEBUGLOG is "true" # DebugLog.panic("die3 " + getId(), e); // #sijapp cond.end# } connect = false; } // #sijapp cond.if modules_DEBUGLOG is "true" # private String getId() { Protocol p = getProtocol(); if (null != p) { return p.getUserId(); } return "" + this; } // #sijapp cond.end# private void sleep(long ms) { try { Thread.sleep(ms); } catch (Exception ignored) { } } private void doPingIfNeeded() throws JimmException { long now = Jimm.getCurrentGmtTime(); if (usePong && (pongTime + PONG_TIMEOUT < now)) { throw new JimmException(120, 9); } if (nextPingTime <= now) { if (usePong) { pingForPong(); } else { ping(); } nextPingTime = now + keepAliveInterval; } } protected final void updateTimeout() { pongTime = Jimm.getCurrentGmtTime(); } public final boolean isConnected() { return connect; } public final void addMessage(PlainMessage msg) { messages.addElement(msg); markMessageSent(-1, -1); } private PlainMessage getMessage(long msgId) { if (-1 < msgId) { for (int i = 0; i < messages.size(); ++i) { PlainMessage m = (PlainMessage)messages.elementAt(i); if (m.getMessageId() == msgId) { return m; } } } return null; } public final boolean isMessageExist(long msgId) { return null != getMessage(msgId); } public final void markMessageSent(long msgId, int status) { PlainMessage msg = getMessage(msgId); if (null != msg) { msg.setSendingState(status); if (PlainMessage.NOTIFY_FROM_CLIENT == status) { messages.removeElement(msg); } } long date = Jimm.getCurrentGmtTime() - 5 * 60; for (int i = messages.size() - 1; i >= 0; --i) { PlainMessage m = (PlainMessage)messages.elementAt(i); if (date > m.getNewDate()) { messages.removeElement(m); } } } protected void pingForPong() throws JimmException { } public abstract void disconnect(); protected abstract Protocol getProtocol(); protected abstract void closeSocket(); protected abstract void connect() throws JimmException; protected abstract void ping() throws JimmException; protected abstract boolean processPacket() throws JimmException; }