/* * Copyright (C) 2007-2008 Esmertec AG. Copyright (C) 2007-2008 The Android Open * Source Project * * Licensed 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. */ package info.guardianproject.otr.app.im.engine; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import android.content.Context; /** * An <code>ImConnection</code> is an abstract representation of a connection to * the IM server. */ public abstract class ImConnection { /** Connection state that indicates the connection is not connected yet. */ public static final int DISCONNECTED = 0; /** Connection state that indicates the user is logging into the server. */ public static final int LOGGING_IN = 1; /** Connection state that indicates the user has logged into the server. */ public static final int LOGGED_IN = 2; /** Connection state that indicates the user is logging out the server. */ public static final int LOGGING_OUT = 3; /** Connection state that indicate the connection is suspending. */ public static final int SUSPENDING = 4; /** Connection state that indicate the connection has been suspended. */ public static final int SUSPENDED = 5; /** The capability of supporting group chat. */ public static final int CAPABILITY_GROUP_CHAT = 1; /** The capability of supporting session re-establishment. */ public static final int CAPABILITY_SESSION_REESTABLISHMENT = 2; /** The current state of the connection. */ protected int mState; protected CopyOnWriteArrayList<ConnectionListener> mConnectionListeners; protected Presence mUserPresence; protected Context mContext; protected ImConnection(Context context) { mConnectionListeners = new CopyOnWriteArrayList<ConnectionListener>(); mState = DISCONNECTED; mContext = context; } public void addConnectionListener(ConnectionListener listener) { if (listener != null) { mConnectionListeners.add(listener); } } public void removeConnectionListener(ConnectionListener listener) { mConnectionListeners.remove(listener); } public abstract Contact getLoginUser(); public String getLoginUserName() { Contact loginUser = getLoginUser(); return loginUser == null ? null : loginUser.getName(); } public abstract int[] getSupportedPresenceStatus(); public Presence getUserPresence() { if (mState == SUSPENDING || mState == SUSPENDED) { return new Presence(); } if (mState != LOGGED_IN) { // In most cases we have a valid mUserPresence instance also // in the LOGGING_OUT state. However there is one exception: // if logout() is called before login finishes, the state may // jump from LOGGING_IN directly to LOGGING_OUT, skipping the // LOGGED_IN state. In this case we won't have a valid Presence // in the LOGGING_OUT state. return null; } return new Presence(mUserPresence); } public abstract void initUser (long providerId, long accountId) throws ImException; public void updateUserPresenceAsync(Presence newPresence) throws ImException { if (mState != LOGGED_IN) { throw new ImException(ImErrorInfo.NOT_LOGGED_IN, "NOT logged in"); } doUpdateUserPresenceAsync(newPresence); } /** * Tells the engine that the network type has changed, e.g. switch from gprs * to wifi. The engine should drop all the network connections created * before because they are not available anymore. * * The engine might also need to redo authentication on the new network * depending on the underlying protocol. */ public void networkTypeChanged() { } /** Tells the current state of the connection. */ public int getState() { return mState; } /** * Sets the state of the connection. * * @param state the new state of the connection. * @param error the error information which caused the state change or null. */ protected void setState(int state, ImErrorInfo error) { if (state < DISCONNECTED || state > SUSPENDED) { throw new IllegalArgumentException("Invalid state: " + state); } if (mState != state) { mState = state; for (ConnectionListener listener : mConnectionListeners) { listener.onStateChanged(state, error); } } } protected void notifyUserPresenceUpdated() { for (ConnectionListener listener : mConnectionListeners) { listener.onUserPresenceUpdated(); } } protected void notifyUpdateUserPresenceError(ImErrorInfo error) { for (ConnectionListener listener : mConnectionListeners) { listener.onUpdatePresenceError(error); } } /** * Gets bit-or of capabilities supported by the underlying protocol. Valid * capability bits are: {@value #CAPABILITY_GROUP_CHAT}, * {@value #CAPABILITY_SESSION_REESTABLISHMENT} * * @return bit-or of capabilities supported by the underlying protocol */ public abstract int getCapability(); /** * Log in to the IM server, using the settings stored in Imps. * * @param accountId the ID to get the Account record * @param passwordTemp a one time use password, not to be saved * @param providerId the ID to get the ProviderSettings record * @param retry whether or not to retry the connection upon failure */ public abstract void loginAsync(long accountId, String passwordTemp, long providerId, boolean retry); /** * Re-establish previous session using the session context persisted by the * client. Only sessions that were dropped unexpectedly(e.g. power loss, * crash, etc) can be re-established using the stored session context. If * the session was terminated normally by either user logging out or server * initiated disconnection, it can't be re-established again therefore the * stored context should be removed by the client. <p> The client can query * if session re-establishment is supported through {@link #getCapability()} * . * * @param sessionContext the session context which was fetched from previous * session by {@link #getSessionContext()} and persisted by the * client. * @throws UnsupportedOperationException if session re-establishment is not * supported by the underlying protocol. */ public abstract void reestablishSessionAsync(Map<String, String> sessionContext); /** Log out from the IM server. */ public abstract void logoutAsync(); /** Immediate logout */ public abstract void logout(); /** Suspend connection with the IM server. */ public abstract void suspend(); /** * Gets the cookie of the current session. The client could store the * context and use it to re-establish the session by * {@link #reestablishSessionAsync(Map)} . The stored context MUST be * removed upon the connection logout/disconnect. * * @return the context of the current session or <code>null</code> if the * user has not logged in yet. * @throws UnsupportedOperationException if session re-establishment is not * supported by the underlying protocol. */ public abstract Map<String, String> getSessionContext(); /** * Gets the instance of ChatSessionManager for the connection. * * @return the instance of ChatSessionManager for the connection. */ public abstract ChatSessionManager getChatSessionManager(); /** * Gets the instance of ContactListManager for the connection. * * @return the instance of ContactListManager for the connection. */ public abstract ContactListManager getContactListManager(); /** * Gets the instance of ChatGroupManager for the connection. * * @return the instance of ChatGroupManager for the connection. * @throws UnsupportedOperationException if group chat is not supported by * the underlying protocol. */ public abstract ChatGroupManager getChatGroupManager(); /** * Whether this connection is going over Tor or not. * @return boolean */ public abstract boolean isUsingTor(); protected abstract void doUpdateUserPresenceAsync(Presence presence); /** * Handle a heartbeat. * * @param heartbeatInterval the number of heartbeats before a ping should be sent. */ public abstract void sendHeartbeat(long heartbeatInterval); public abstract void setProxy(String type, String host, int port); }