PageRenderTime 3816ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/mgandroid-teamtalk/src/com/mogujie/tt/imlib/IMLoginManager.java

https://gitlab.com/lisit1003/TTAndroidClient
Java | 506 lines | 352 code | 126 blank | 28 comment | 44 complexity | 7b8781dbe16d21c86455524d2204ff17 MD5 | raw file
  1. package com.mogujie.tt.imlib;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.apache.http.Header;
  5. import org.jboss.netty.channel.StaticChannelPipeline;
  6. import org.json.JSONArray;
  7. import org.json.JSONException;
  8. import org.json.JSONObject;
  9. import android.content.Context;
  10. import android.content.Intent;
  11. import android.os.Handler;
  12. import android.os.Message;
  13. import android.util.Log;
  14. import com.loopj.android.http.AsyncHttpClient;
  15. import com.loopj.android.http.JsonHttpResponseHandler;
  16. import com.loopj.android.http.PersistentCookieStore;
  17. import com.loopj.android.http.RequestParams;
  18. import com.mogujie.tt.cache.biz.CacheHub;
  19. import com.mogujie.tt.config.ProtocolConstant;
  20. import com.mogujie.tt.config.SysConstant;
  21. import com.mogujie.tt.entity.User;
  22. import com.mogujie.tt.imlib.common.ErrorCode;
  23. import com.mogujie.tt.imlib.db.IMDbManager;
  24. import com.mogujie.tt.imlib.network.LoginServerHandler;
  25. import com.mogujie.tt.imlib.network.MsgServerHandler;
  26. import com.mogujie.tt.imlib.network.SocketThread;
  27. import com.mogujie.tt.imlib.proto.LoginPacket;
  28. import com.mogujie.tt.imlib.proto.MsgServerPacket;
  29. import com.mogujie.tt.imlib.proto.MsgServerPacket.PacketRequest.Entity;
  30. import com.mogujie.tt.log.Logger;
  31. import com.mogujie.tt.packet.base.DataBuffer;
  32. import com.mogujie.tt.ui.utils.Md5Helper;
  33. public class IMLoginManager extends IMManager {
  34. private static IMLoginManager inst;
  35. public static IMLoginManager instance() {
  36. synchronized (IMLoginManager.class) {
  37. if (inst == null) {
  38. inst = new IMLoginManager();
  39. }
  40. return inst;
  41. }
  42. }
  43. private static final int LOGIN_ERROR_TOKEN_EXPIRED = 6;
  44. private Logger logger = Logger.getLogger(IMLoginManager.class);
  45. private String loginUserName;
  46. private String loginPwd;
  47. private String loginId;
  48. private SocketThread loginServerThread;
  49. private List<String> msgServerAddrs;
  50. private int msgServerPort;
  51. private SocketThread msgServerThread;
  52. // todo eric make it to ContactEntity too
  53. private User loginUser;
  54. private static final int MSG_SERVER_DISCONNECTED_EVENT = -1;
  55. private boolean loggined = false;
  56. private boolean everLogined = false;
  57. private boolean identityChanged = false;
  58. private boolean retryReqLoginServerAddrsFlag = false;
  59. private boolean logoutFlag = false;
  60. private int msgServerErrorCode = 0;
  61. public boolean isLogout() {
  62. return logoutFlag;
  63. }
  64. public void setLogout(boolean logout) {
  65. logger.d("login#setLogout");
  66. this.logoutFlag = logout;
  67. // logger.d("login#setLogout:%s", Log.getStackTraceString(new Throwable()));
  68. }
  69. private AsyncHttpClient client = new AsyncHttpClient();
  70. private PersistentCookieStore myCookieStore;
  71. private static Handler handler = new Handler() {
  72. @Override
  73. public void handleMessage(Message msg) {
  74. // TODO Auto-generated method stub
  75. if (msg.what == MSG_SERVER_DISCONNECTED_EVENT) {
  76. IMLoginManager.instance().disconnectMsgServer();
  77. }
  78. // // todo eric don't put ui stuff here
  79. // Toast.makeText(ctx, "网络发生错误,已和服务器断开连接",
  80. // Toast.LENGTH_LONG).show();
  81. super.handleMessage(msg);
  82. }
  83. };
  84. private static final int STATUS_REQ_LOGIN_SERVER_ADDRS = -1;
  85. private static final int STATUS_CONNECT_LOGIN_SERVER = 0;
  86. private static final int STATUS_REQ_MSG_SERVER_ADDRS = 1;
  87. private static final int STATUS_CONNECT_MSG_SERVER = 2;
  88. private static final int STATUS_LOGINING_MSG_SERVER = 3;
  89. private static final int STATUS_LOGIN_OK = 4;
  90. private static final int STATUS_LOGIN_FAILED = 5;
  91. private static final int STATUS_MSG_SERVER_DISCONNECTED = 6;
  92. private int currentStatus = STATUS_REQ_LOGIN_SERVER_ADDRS;
  93. @Override
  94. public void setContext(Context context) {
  95. super.setContext(context);
  96. myCookieStore = new PersistentCookieStore(ctx);
  97. client.setCookieStore(myCookieStore);
  98. }
  99. public void logOut() {
  100. // if not login, do nothing
  101. // send logOuting message, so reconnect won't react abnormally
  102. // but when reconnect start to work again?use isEverLogined
  103. // close the socket
  104. // send logOuteOk message
  105. // mainactivity jumps to login page
  106. logger.d("login#logOut");
  107. logger.d("login#stop reconnecting");
  108. // everlogined is enough to stop reconnecting
  109. setEverLogined(false);
  110. // ctx.sendBroadcast(new Intent(IMActions.ACTION_LOGOUTING));
  111. setLogout(true);
  112. disconnectMsgServer();
  113. logger.d("login#send logout finish message");
  114. ctx.sendBroadcast(new Intent(IMActions.ACTION_LOGOUT));
  115. }
  116. public boolean isEverLogined() {
  117. return everLogined;
  118. }
  119. public void setEverLogined(boolean everLogined) {
  120. this.everLogined = everLogined;
  121. }
  122. public boolean isLoggined() {
  123. return loggined;
  124. }
  125. public User getLoginUser() {
  126. return loginUser;
  127. }
  128. public boolean isDoingLogin() {
  129. return currentStatus <= STATUS_LOGINING_MSG_SERVER;
  130. }
  131. public String getLoginId() {
  132. return loginId;
  133. }
  134. public void setLoginId(String loginId) {
  135. logger.d("login#setLoginId -> loginId:%s", loginId);
  136. this.loginId = loginId;
  137. }
  138. public IMLoginManager() {
  139. logger.d("login#creating IMLoginManager");
  140. }
  141. public boolean reloginFromStart() {
  142. logger.d("login#reloginFromStart");
  143. if (isDoingLogin()) {
  144. logger.d("login#isDoingLogin, no need");
  145. return false;
  146. }
  147. login(loginUserName, loginPwd, true, true);
  148. return true;
  149. }
  150. public boolean relogin() {
  151. logger.d("login#relogin");
  152. connectLoginServer();
  153. return true;
  154. }
  155. public void login(String userName, String password,
  156. boolean userNameChanged, boolean pwdChanged) {
  157. if (ctx != null) {
  158. ctx.sendBroadcast(new Intent(IMActions.ACTION_DOING_LOGIN));
  159. }
  160. logger.i("login#login -> userName:%s, userNameChanged:%s, pwdChanged:%s", userName, userNameChanged, pwdChanged);
  161. loginUserName = userName;
  162. loginPwd = password;
  163. if(pwdChanged){
  164. loginPwd = Md5Helper.encode(password);
  165. }else{
  166. loginPwd = password;
  167. }
  168. identityChanged = userNameChanged || pwdChanged;
  169. connectLoginServer();
  170. }
  171. private void connectLoginServer() {
  172. currentStatus = STATUS_CONNECT_LOGIN_SERVER;
  173. String ip = ProtocolConstant.LOGIN_IP1;
  174. int port = ProtocolConstant.LOGIN_PORT;
  175. logger.i("login#connect login server -> (%s:%d)", ip, port);
  176. if (loginServerThread != null) {
  177. loginServerThread.close();
  178. loginServerThread = null;
  179. }
  180. loginServerThread = new SocketThread(ip, port, new LoginServerHandler());
  181. loginServerThread.start();
  182. }
  183. public void cancel() {
  184. // todo eric
  185. logger.i("login#cancel");
  186. }
  187. public void onLoginServerUnconnected() {
  188. logger.i("login#onLoginServerUnConnected");
  189. IMLoginManager.instance().onLoginFailed(ErrorCode.E_CONNECT_LOGIN_SERVER_FAILED);
  190. }
  191. public void onLoginFailed(int errorCode) {
  192. logger.i("login#onLoginFailed -> errorCode:%d", errorCode);
  193. currentStatus = STATUS_LOGIN_FAILED;
  194. loggined = false;
  195. Intent intent = new Intent(IMActions.ACTION_LOGIN_RESULT);
  196. intent.putExtra(SysConstant.lOGIN_ERROR_CODE_KEY, errorCode);
  197. if (errorCode == ErrorCode.E_MSG_SERVER_ERROR_CODE) {
  198. intent.putExtra(SysConstant.KEY_MSG_SERVER_ERROR_CODE, msgServerErrorCode);
  199. }
  200. if (ctx != null) {
  201. logger.i("login#broadcast login failed");
  202. ctx.sendBroadcast(intent);
  203. }
  204. }
  205. public void onLoginOk() {
  206. logger.i("login#onLoginOk");
  207. setLogout(false);
  208. currentStatus = STATUS_LOGIN_OK;
  209. loggined = true;
  210. everLogined = true;
  211. if (identityChanged) {
  212. IMDbManager.instance(ctx).saveLoginIdentity(loginUserName, loginPwd);
  213. }
  214. Intent intent = new Intent(IMActions.ACTION_LOGIN_RESULT);
  215. intent.putExtra(SysConstant.lOGIN_ERROR_CODE_KEY, ErrorCode.S_OK);
  216. if (ctx != null) {
  217. logger.i("login#broadcast login ok");
  218. ctx.sendBroadcast(intent);
  219. }
  220. }
  221. public void onLoginServerConnected() {
  222. logger.i("login#onLoginServerConnected");
  223. reqMsgServerAddrs();
  224. }
  225. public void onLoginServerDisconnected() {
  226. logger.e("login#onLoginServerDisconnected");
  227. // todo eric is enum capable of comparing just like int?
  228. if (currentStatus < STATUS_CONNECT_MSG_SERVER) {
  229. logger.e("login server disconnected unexpectedly");
  230. onLoginFailed(ErrorCode.E_REQ_MSG_SERVER_ADDRS_FAILED);
  231. }
  232. }
  233. public void reqMsgServerAddrs() {
  234. logger.i("login#reqMsgServerAddrs");
  235. currentStatus = STATUS_REQ_MSG_SERVER_ADDRS;
  236. if (loginServerThread != null) {
  237. Entity entity = new Entity();
  238. entity.userType = 0;
  239. loginServerThread.sendPacket(new MsgServerPacket(entity));
  240. logger.d("login#send packet ok");
  241. }
  242. }
  243. public void onRepMsgServerAddrs(DataBuffer buffer) {
  244. logger.i("login#onRepMsgServerAddrs");
  245. MsgServerPacket packet = new MsgServerPacket();
  246. packet.decode(buffer);
  247. MsgServerPacket.PacketResponse resp = (MsgServerPacket.PacketResponse) packet.getResponse();
  248. if (resp == null) {
  249. logger.e("login#decode MsgServerResponse failed");
  250. onLoginFailed(ErrorCode.E_REQ_MSG_SERVER_ADDRS_FAILED);
  251. return;
  252. }
  253. if (msgServerAddrs == null) {
  254. msgServerAddrs = new ArrayList<String>();
  255. }
  256. msgServerAddrs.add(resp.entity.ip1);
  257. msgServerAddrs.add(resp.entity.ip2);
  258. msgServerPort = resp.entity.port;
  259. logger.i("login#msgserver ip1:%s, login ip2:%s, port:%d", resp.entity.ip1, resp.entity.ip2, resp.entity.port);
  260. connectMsgServer();
  261. }
  262. private String pickLoginServerIp() {
  263. // todo eric
  264. // pick the second one right now
  265. return msgServerAddrs.get(1);
  266. }
  267. private void disconnectLoginServer() {
  268. logger.i("login#disconnectLoginServer");
  269. if (loginServerThread != null) {
  270. loginServerThread.close();
  271. logger.i("login#do real disconnectLoginServer ok");
  272. // todo eric
  273. // loginServerThread = null;
  274. }
  275. }
  276. private void disconnectMsgServer() {
  277. // logger.i("login#disconnectMsgServer, callstack:%s", Log.getStackTraceString(new Throwable()));
  278. logger.i("login#disconnectMsgServer");
  279. if (msgServerThread != null) {
  280. msgServerThread.close();
  281. logger.i("login#do real disconnectMsgServer ok");
  282. // msgServerThread = null;
  283. }
  284. }
  285. private void connectMsgServer() {
  286. currentStatus = STATUS_CONNECT_MSG_SERVER;
  287. disconnectLoginServer();
  288. String ip = pickLoginServerIp();
  289. logger.i("login#connectMsgServer -> (%s:%d)", ip, msgServerPort);
  290. if (msgServerThread != null) {
  291. msgServerThread.close();
  292. msgServerThread = null;
  293. }
  294. msgServerThread = new SocketThread(ip, msgServerPort,
  295. new MsgServerHandler());
  296. msgServerThread.start();
  297. }
  298. public void onMessageServerUnconnected() {
  299. logger.i("login#onMessageServerUnconnected");
  300. onLoginFailed(ErrorCode.E_CONNECT_MSG_SERVER_FAILED);
  301. }
  302. public void onMsgServerConnected() {
  303. logger.i("login#onMsgServerConnected");
  304. reqLoginMsgServer();
  305. }
  306. private void broadcastDisconnectWithServer() {
  307. logger.i("login#broadcastDisconnectWithServer");
  308. if (ctx != null) {
  309. ctx.sendBroadcast(new Intent(IMActions.ACTION_SERVER_DISCONNECTED));
  310. }
  311. }
  312. public void onMsgServerDisconnected() {
  313. logger.w("login#onMsgServerDisconnected");
  314. if (currentStatus < STATUS_LOGIN_OK) {
  315. onLoginFailed(ErrorCode.E_LOGIN_MSG_SERVER_FAILED);
  316. } else {
  317. broadcastDisconnectWithServer();
  318. }
  319. currentStatus = STATUS_MSG_SERVER_DISCONNECTED;
  320. loggined = false;
  321. // only 2 threads(ui thread, network thread) would request sending
  322. // packet
  323. // let the ui thread to close the connection
  324. // so if the ui thread has a sending task, no synchronization issue
  325. handler.sendEmptyMessage(MSG_SERVER_DISCONNECTED_EVENT);
  326. }
  327. private void reqLoginMsgServer() {
  328. logger.i("login#reqLoginMsgServer");
  329. currentStatus = STATUS_LOGINING_MSG_SERVER;
  330. if (msgServerThread != null) {
  331. com.mogujie.tt.imlib.proto.LoginPacket.PacketRequest.Entity entity = new com.mogujie.tt.imlib.proto.LoginPacket.PacketRequest.Entity();
  332. entity.name = loginUserName;
  333. entity.pass = loginPwd;
  334. entity.onlineStatus = ProtocolConstant.ON_LINE;
  335. entity.clientType = ProtocolConstant.CLIENT_TYPE;
  336. entity.clientVersion = ProtocolConstant.CLIENT_VERSION;
  337. msgServerThread.sendPacket(new LoginPacket(entity));
  338. }
  339. }
  340. public void onRepMsgServerLogin(DataBuffer buffer) {
  341. logger.i("login#onRepMsgServerLogin");
  342. LoginPacket packet = new LoginPacket();
  343. packet.decode(buffer);
  344. LoginPacket.PacketResponse resp = (LoginPacket.PacketResponse) packet.getResponse();
  345. if (resp == null) {
  346. logger.e("login#decode LoginResponse failed");
  347. onLoginFailed(ErrorCode.E_LOGIN_MSG_SERVER_FAILED);
  348. return;
  349. }
  350. int loginResult = resp.entity.result;
  351. this.msgServerErrorCode = loginResult;
  352. logger.d("login#loginResult:%d", loginResult);
  353. if (loginResult == 0) {
  354. loginUser = resp.getUser();
  355. loginUser.setUserId(resp.entity.userId);
  356. setLoginId(resp.entity.userId);
  357. onLoginOk();
  358. } else {
  359. logger.e("login#login msg server failed, result:%d", loginResult);
  360. // todo eric right now, no detail failed reason
  361. onLoginFailed(ErrorCode.E_MSG_SERVER_ERROR_CODE);
  362. if (loginResult == LOGIN_ERROR_TOKEN_EXPIRED) {
  363. logger.e("login#error:token expired");
  364. reloginFromStart();
  365. }
  366. }
  367. }
  368. public SocketThread getMsgServerChannel() {
  369. return msgServerThread;
  370. }
  371. public void disconnect() {
  372. logger.d("login#disconnect");
  373. disconnectLoginServer();
  374. disconnectMsgServer();
  375. }
  376. @Override
  377. public void reset() {
  378. // TODO Auto-generated method stub
  379. }
  380. }