📄 impsconnection.java
字号:
/* * 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 com.android.im.imps;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import com.android.im.engine.ChatGroupManager;import com.android.im.engine.ChatSessionManager;import com.android.im.engine.Contact;import com.android.im.engine.ContactListManager;import com.android.im.engine.ImConnection;import com.android.im.engine.ImErrorInfo;import com.android.im.engine.ImException;import com.android.im.engine.LoginInfo;import com.android.im.engine.Presence;import com.android.im.imps.ImpsConnectionConfig.CirMethod;import com.android.im.imps.ImpsConnectionConfig.TransportType;/** * An implementation of ImConnection of Wireless Village IMPS protocol. */public class ImpsConnection extends ImConnection { ImpsConnectionConfig mConfig; DataChannel mDataChannel; private CirChannel mCirChannel; private PrimitiveDispatcherThread mDispatcherThread; ImpsSession mSession; ImpsTransactionManager mTransactionManager; private ImpsChatSessionManager mChatSessionManager; private ImpsContactListManager mContactListManager; private ImpsChatGroupManager mChatGroupManager; private boolean mReestablishing; /** * Constructs a new WVConnection with a WVConnectionConfig object. * * @param config the configuration. * @throws ImException if there's an error in the configuration. */ public ImpsConnection(ImpsConnectionConfig config) { super(); mConfig = config; mTransactionManager = new ImpsTransactionManager(this); mChatSessionManager = new ImpsChatSessionManager(this); mContactListManager = new ImpsContactListManager(this); mChatGroupManager = new ImpsChatGroupManager(this); } /** * Gets the configuration of this connection. * * @return the configuration. */ ImpsConnectionConfig getConfig() { return mConfig; } synchronized void shutdownOnError(ImErrorInfo error) { if(mState == DISCONNECTED) { return; } if (mCirChannel != null) { mCirChannel.shutdown(); } if (mDispatcherThread != null) { mDispatcherThread.shutdown(); } if (mDataChannel != null) { mDataChannel.shutdown(); } if (mContactListManager != null && !mReestablishing) { mContactListManager.reset(); } setState(mReestablishing ? SUSPENDED: DISCONNECTED, error); mReestablishing = false; } void shutdown(){ shutdownOnError(null); } @Override public int getCapability() { return CAPABILITY_GROUP_CHAT | CAPABILITY_SESSION_REESTABLISHMENT; } @Override public void loginAsync(LoginInfo loginInfo) { if (!checkAndSetState(DISCONNECTED)) { return; } try { mSession = new ImpsSession(this, loginInfo); } catch (ImException e) { setState(DISCONNECTED, e.getImError()); return; } doLogin(); } @Override public void reestablishSessionAsync( HashMap<String, String> cookie) { if (!checkAndSetState(SUSPENDED)) { return; } mReestablishing = true; try { mSession = new ImpsSession(this, cookie); } catch (ImException e) { setState(DISCONNECTED, e.getImError()); return; } doLogin(); } @Override public void networkTypeChanged() { if (mCirChannel != null) { mCirChannel.reconnect(); } } private synchronized boolean checkAndSetState(int state) { if(mState != state){ return false; } setState(LOGGING_IN, null); return true; } private void doLogin() { try { initDataChannel(); mDataChannel.connect(); } catch (ImException e) { ImErrorInfo error = e.getImError(); if(error == null){ error = new ImErrorInfo(ImErrorInfo.UNKNOWN_LOGIN_ERROR, e.getMessage()); } shutdownOnError(error); return; } mDispatcherThread = new PrimitiveDispatcherThread(mDataChannel); mDispatcherThread.start(); LoginTransaction login = new LoginTransaction(); login.startAuthenticate(); } @Override public HashMap<String, String> getSessionContext() { if(mState != LOGGED_IN) { return null; } else { return mSession.getContext(); } } class LoginTransaction extends MultiPhaseTransaction { LoginTransaction() { // We're not passing completion to ImpsAsyncTransaction. Instead // we'll handle the notification in LoginTransaction. super(mTransactionManager); } public void startAuthenticate() { Primitive login = buildBasicLoginReq(); if (mConfig.use4wayLogin()) { // first login request of 4 way login String[] supportedDigestSchema = mConfig.getPasswordDigest().getSupportedDigestSchema(); for (String element : supportedDigestSchema) { login.addElement(ImpsTags.DigestSchema, element); } } else { // 2 way login login.addElement(ImpsTags.Password, mSession.getPassword()); } sendRequest(login); } @Override public TransactionStatus processResponse(Primitive response) { if (response.getElement(ImpsTags.SessionID) != null) { // If server chooses authentication based on network, we might // got the final Login-Response before the 2nd Login-Request. String sessionId = response.getElementContents(ImpsTags.SessionID); String keepAliveTime = response.getElementContents(ImpsTags.KeepAliveTime); String capablityReqeust = response.getElementContents(ImpsTags.CapabilityRequest); long keepAlive = ImpsUtils.parseLong(keepAliveTime, mConfig.getDefaultKeepAliveInterval()); // make sure we always have time to send keep-alive requests. // see buildBasicLoginReq(). keepAlive -= 5; mSession.setId(sessionId); mSession.setKeepAliveTime(keepAlive); mSession.setCapablityRequestRequired(ImpsUtils.isTrue(capablityReqeust)); onAuthenticated(); return TransactionStatus.TRANSACTION_COMPLETED; } else { return sendSecondLogin(response); } } @Override public TransactionStatus processResponseError(ImpsErrorInfo error) { if (error.getCode() == ImpsConstants.STATUS_UNAUTHORIZED && error.getPrimitive() != null) { if (mConfig.use4wayLogin()) { // Not really an error. Send the 2nd Login-Request. return sendSecondLogin(error.getPrimitive()); } else { // We have already sent password in 2way login, while OZ's // yahoo gateway server returns "401 - Further authorization // required" instead of "409 - Invalid password" if the // password only contains spaces. shutdownOnError(new ImErrorInfo(409, "Invalid password")); return TransactionStatus.TRANSACTION_COMPLETED; } } else if(error.getCode() == ImpsConstants.STATUS_COULD_NOT_RECOVER_SESSION) { // The server could not recover the session, create a new // session and try to login again. LoginInfo loginInfo = mSession.getLoginInfo(); try { mSession = new ImpsSession(ImpsConnection.this, loginInfo); } catch (ImException ignore) { // This shouldn't happen since we have tried to login with // the loginInfo } startAuthenticate(); return TransactionStatus.TRANSACTION_COMPLETED; } else { shutdownOnError(error); return TransactionStatus.TRANSACTION_COMPLETED; } } private TransactionStatus sendSecondLogin(Primitive res) { try { Primitive secondLogin = buildBasicLoginReq(); String nonce = res.getElementContents(ImpsTags.Nonce); String digestSchema = res.getElementContents(ImpsTags.DigestSchema); String digestBytes = mConfig.getPasswordDigest().digest(digestSchema, nonce, mSession.getPassword()); secondLogin.addElement(ImpsTags.DigestBytes, digestBytes); sendRequest(secondLogin); return TransactionStatus.TRANSACTION_CONTINUE; } catch (ImException e) { ImpsLog.logError(e); shutdownOnError(new ImErrorInfo(ImErrorInfo.UNKNOWN_ERROR, e.toString())); return TransactionStatus.TRANSACTION_COMPLETED; } } private void onAuthenticated() { if(mSession.isCapablityRequestRequired()) { mSession.negotiateCapabilityAsync(new AsyncCompletion(){ public void onComplete() { onCapabilityNegotiated(); } public void onError(ImErrorInfo error) { shutdownOnError(error); } }); } else { onCapabilityNegotiated(); } } void onCapabilityNegotiated() { mDataChannel.setServerMinPoll(mSession.getServerPollMin()); if(getConfig().getCirChannelBinding() != CirMethod.NONE) { try { setupCIRChannel(); } catch (ImException e) { shutdownOnError(new ImErrorInfo( ImErrorInfo.UNSUPPORTED_CIR_CHANNEL, e.toString())); return; } } mSession.negotiateServiceAsync(new AsyncCompletion(){ public void onComplete() { onServiceNegotiated(); } public void onError(ImErrorInfo error) { shutdownOnError(error); } }); } void onServiceNegotiated() { mDataChannel.startKeepAlive(mSession.getKeepAliveTime()); retrieveUserPresenceAsync(new AsyncCompletion() { public void onComplete() { setState(LOGGED_IN, null); if (mReestablishing) { ImpsContactListManager listMgr= (ImpsContactListManager) getContactListManager(); listMgr.subscribeToAllListAsync(); mReestablishing = false; } } public void onError(ImErrorInfo error) { // Just continue. initUserPresenceAsync already made a // default mUserPresence for us. onComplete(); } }); } } @Override public void logoutAsync() { setState(LOGGING_OUT, null); // Shutdown the CIR channel first. if(mCirChannel != null) { mCirChannel.shutdown();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -