WFCCNetworkService.mm 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. //
  2. // WFCCNetworkService.mm
  3. // WFChatClient
  4. //
  5. // Created by heavyrain on 2017/11/5.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #include "WFCCNetworkService.h"
  9. #import <UIKit/UIKit.h>
  10. #import <SystemConfiguration/SCNetworkReachability.h>
  11. #import <sys/xattr.h>
  12. #import <CommonCrypto/CommonDigest.h>
  13. #import "app_callback.h"
  14. #include <mars/baseevent/base_logic.h>
  15. #include <mars/xlog/xlogger.h>
  16. #include <mars/xlog/xloggerbase.h>
  17. #include <mars/xlog/appender.h>
  18. #include <mars/proto/proto.h>
  19. #include <mars/stn/stn_logic.h>
  20. #include <list>
  21. #import "WFCCIMService.h"
  22. #import "WFCCNetworkStatus.h"
  23. #import "WFCCRecallMessageContent.h"
  24. const NSString *SDKVERSION = @"0.1";
  25. extern NSMutableArray* convertProtoMessageList(const std::list<mars::stn::TMessage> &messageList, BOOL reverse);
  26. extern NSMutableArray* convertProtoDeliveryList(const std::map<std::string, int64_t> &userReceived);
  27. extern NSMutableArray* convertProtoReadedList(const std::list<mars::stn::TReadEntry> &userReceived);
  28. NSString *kGroupInfoUpdated = @"kGroupInfoUpdated";
  29. NSString *kGroupMemberUpdated = @"kGroupMemberUpdated";
  30. NSString *kUserInfoUpdated = @"kUserInfoUpdated";
  31. NSString *kFriendListUpdated = @"kFriendListUpdated";
  32. NSString *kFriendRequestUpdated = @"kFriendRequestUpdated";
  33. NSString *kSettingUpdated = @"kSettingUpdated";
  34. NSString *kChannelInfoUpdated = @"kChannelInfoUpdated";
  35. @protocol RefreshGroupInfoDelegate <NSObject>
  36. - (void)onGroupInfoUpdated:(NSArray<WFCCGroupInfo *> *)updatedGroupInfo;
  37. @end
  38. @protocol RefreshGroupMemberDelegate <NSObject>
  39. - (void)onGroupMemberUpdated:(NSString *)groupId members:(NSArray<WFCCGroupMember *> *)updatedGroupMember;
  40. @end
  41. @protocol RefreshChannelInfoDelegate <NSObject>
  42. - (void)onChannelInfoUpdated:(NSArray<WFCCChannelInfo *> *)updatedChannelInfo;
  43. @end
  44. @protocol RefreshUserInfoDelegate <NSObject>
  45. - (void)onUserInfoUpdated:(NSArray<WFCCUserInfo *> *)updatedUserInfo;
  46. @end
  47. @protocol RefreshFriendListDelegate <NSObject>
  48. - (void)onFriendListUpdated;
  49. @end
  50. @protocol RefreshFriendRequestDelegate <NSObject>
  51. - (void)onFriendRequestUpdated;
  52. @end
  53. @protocol RefreshSettingDelegate <NSObject>
  54. - (void)onSettingUpdated;
  55. @end
  56. class CSCB : public mars::stn::ConnectionStatusCallback {
  57. public:
  58. CSCB(id<ConnectionStatusDelegate> delegate) : m_delegate(delegate) {
  59. }
  60. void onConnectionStatusChanged(mars::stn::ConnectionStatus connectionStatus) {
  61. if (m_delegate) {
  62. [m_delegate onConnectionStatusChanged:(ConnectionStatus)connectionStatus];
  63. }
  64. }
  65. id<ConnectionStatusDelegate> m_delegate;
  66. };
  67. class RPCB : public mars::stn::ReceiveMessageCallback {
  68. public:
  69. RPCB(id<ReceiveMessageDelegate> delegate) : m_delegate(delegate) {}
  70. void onReceiveMessage(const std::list<mars::stn::TMessage> &messageList, bool hasMore) {
  71. if (m_delegate && !messageList.empty()) {
  72. NSMutableArray *messages = convertProtoMessageList(messageList, NO);
  73. [m_delegate onReceiveMessage:messages hasMore:hasMore];
  74. }
  75. }
  76. void onRecallMessage(const std::string &operatorId, long long messageUid) {
  77. if (m_delegate) {
  78. [m_delegate onRecallMessage:messageUid];
  79. }
  80. }
  81. void onDeleteMessage(long long messageUid) {
  82. if (m_delegate) {
  83. [m_delegate onDeleteMessage:messageUid];
  84. }
  85. }
  86. void onUserReceivedMessage(const std::map<std::string, int64_t> &userReceived) {
  87. if (m_delegate && !userReceived.empty()) {
  88. NSMutableArray *ds = convertProtoDeliveryList(userReceived);
  89. [m_delegate onMessageDelivered:ds];
  90. }
  91. }
  92. void onUserReadedMessage(const std::list<mars::stn::TReadEntry> &userReceived) {
  93. if (m_delegate && !userReceived.empty()) {
  94. NSMutableArray *ds = convertProtoReadedList(userReceived);
  95. [m_delegate onMessageReaded:ds];
  96. }
  97. }
  98. id<ReceiveMessageDelegate> m_delegate;
  99. };
  100. WFCCUserInfo* convertUserInfo(const mars::stn::TUserInfo &tui) {
  101. WFCCUserInfo *userInfo = [[WFCCUserInfo alloc] init];
  102. userInfo.userId = [NSString stringWithUTF8String:tui.uid.c_str()];
  103. userInfo.name = [NSString stringWithUTF8String:tui.name.c_str()];
  104. userInfo.portrait = [NSString stringWithUTF8String:tui.portrait.c_str()];
  105. userInfo.deleted = tui.deleted;
  106. if (tui.deleted) {
  107. userInfo.displayName = @"已删除用户";
  108. } else {
  109. userInfo.displayName = [NSString stringWithUTF8String:tui.displayName.c_str()];
  110. userInfo.gender = tui.gender;
  111. userInfo.social = [NSString stringWithUTF8String:tui.social.c_str()];
  112. userInfo.mobile = [NSString stringWithUTF8String:tui.mobile.c_str()];
  113. userInfo.email = [NSString stringWithUTF8String:tui.email.c_str()];
  114. userInfo.address = [NSString stringWithUTF8String:tui.address.c_str()];
  115. userInfo.company = [NSString stringWithUTF8String:tui.company.c_str()];
  116. userInfo.social = [NSString stringWithUTF8String:tui.social.c_str()];
  117. }
  118. userInfo.friendAlias = [NSString stringWithUTF8String:tui.friendAlias.c_str()];
  119. userInfo.groupAlias = [NSString stringWithUTF8String:tui.groupAlias.c_str()];
  120. userInfo.extra = [NSString stringWithUTF8String:tui.extra.c_str()];
  121. userInfo.updateDt = tui.updateDt;
  122. userInfo.type = tui.type;
  123. return userInfo;
  124. }
  125. NSArray<WFCCUserInfo *>* converUserInfos(const std::list<mars::stn::TUserInfo> &userInfoList) {
  126. NSMutableArray *out = [[NSMutableArray alloc] init];
  127. for (std::list<mars::stn::TUserInfo>::const_iterator it = userInfoList.begin(); it != userInfoList.end(); it++) {
  128. [out addObject:convertUserInfo(*it)];
  129. }
  130. return out;
  131. }
  132. WFCCGroupInfo* convertGroupInfo(const mars::stn::TGroupInfo &tgi) {
  133. WFCCGroupInfo *groupInfo = [[WFCCGroupInfo alloc] init];
  134. groupInfo.type = (WFCCGroupType)tgi.type;
  135. groupInfo.target = [NSString stringWithUTF8String:tgi.target.c_str()];
  136. groupInfo.name = [NSString stringWithUTF8String:tgi.name.c_str()];
  137. groupInfo.extra = [NSString stringWithUTF8String:tgi.extra.c_str()];;
  138. groupInfo.portrait = [NSString stringWithUTF8String:tgi.portrait.c_str()];
  139. groupInfo.owner = [NSString stringWithUTF8String:tgi.owner.c_str()];
  140. groupInfo.memberCount = tgi.memberCount;
  141. groupInfo.mute = tgi.mute;
  142. groupInfo.joinType = tgi.joinType;
  143. groupInfo.privateChat = tgi.privateChat;
  144. groupInfo.searchable = tgi.searchable;
  145. groupInfo.historyMessage = tgi.historyMessage;
  146. groupInfo.maxMemberCount = tgi.maxMemberCount;
  147. groupInfo.updateTimestamp = tgi.updateDt;
  148. return groupInfo;
  149. }
  150. extern WFCCChannelInfo *convertProtoChannelInfo(const mars::stn::TChannelInfo &tci);
  151. NSArray<WFCCGroupInfo *>* convertGroupInfos(const std::list<mars::stn::TGroupInfo> &groupInfoList) {
  152. NSMutableArray *out = [[NSMutableArray alloc] init];
  153. for (std::list<mars::stn::TGroupInfo>::const_iterator it = groupInfoList.begin(); it != groupInfoList.end(); it++) {
  154. [out addObject:convertGroupInfo(*it)];
  155. }
  156. return out;
  157. }
  158. NSArray<WFCCChannelInfo *>* convertChannelInfos(const std::list<mars::stn::TChannelInfo> &channelInfoList) {
  159. NSMutableArray *out = [[NSMutableArray alloc] init];
  160. for (std::list<mars::stn::TChannelInfo>::const_iterator it = channelInfoList.begin(); it != channelInfoList.end(); it++) {
  161. [out addObject:convertProtoChannelInfo(*it)];
  162. }
  163. return out;
  164. }
  165. class GUCB : public mars::stn::GetUserInfoCallback {
  166. public:
  167. GUCB(id<RefreshUserInfoDelegate> delegate) : m_delegate(delegate) {}
  168. void onSuccess(const std::list<mars::stn::TUserInfo> &userInfoList) {
  169. if(m_delegate) {
  170. [m_delegate onUserInfoUpdated:converUserInfos(userInfoList)];
  171. }
  172. }
  173. void onFalure(int errorCode) {
  174. }
  175. id<RefreshUserInfoDelegate> m_delegate;
  176. };
  177. class GGCB : public mars::stn::GetGroupInfoCallback {
  178. public:
  179. GGCB(id<RefreshGroupInfoDelegate> delegate) : m_delegate(delegate) {}
  180. void onSuccess(const std::list<mars::stn::TGroupInfo> &groupInfoList) {
  181. if(m_delegate && !groupInfoList.empty()) {
  182. [m_delegate onGroupInfoUpdated:convertGroupInfos(groupInfoList)];
  183. }
  184. }
  185. void onFalure(int errorCode) {
  186. }
  187. id<RefreshGroupInfoDelegate> m_delegate;
  188. };
  189. class GGMCB : public mars::stn::GetGroupMembersCallback {
  190. public:
  191. GGMCB(id<RefreshGroupMemberDelegate> delegate) : m_delegate(delegate) {}
  192. void onSuccess(const std::string &groupId, const std::list<mars::stn::TGroupMember> &groupMemberList) {
  193. if(m_delegate && !groupMemberList.empty()) {
  194. [m_delegate onGroupMemberUpdated:[NSString stringWithUTF8String:groupId.c_str()] members:nil];
  195. }
  196. }
  197. void onFalure(int errorCode) {
  198. }
  199. id<RefreshGroupMemberDelegate> m_delegate;
  200. };
  201. class GCHCB : public mars::stn::GetChannelInfoCallback {
  202. public:
  203. GCHCB(id<RefreshChannelInfoDelegate> delegate) : m_delegate(delegate) {}
  204. void onSuccess(const std::list<mars::stn::TChannelInfo> &channelInfoList) {
  205. if(m_delegate && !channelInfoList.empty()) {
  206. [m_delegate onChannelInfoUpdated:convertChannelInfos(channelInfoList)];
  207. }
  208. }
  209. void onFalure(int errorCode) {
  210. }
  211. id<RefreshChannelInfoDelegate> m_delegate;
  212. };
  213. class GFLCB : public mars::stn::GetMyFriendsCallback {
  214. public:
  215. GFLCB(id<RefreshFriendListDelegate> delegate) : m_delegate(delegate) {}
  216. void onSuccess(std::list<std::string> friendIdList) {
  217. if(m_delegate) {
  218. [m_delegate onFriendListUpdated];
  219. }
  220. }
  221. void onFalure(int errorCode) {
  222. }
  223. id<RefreshFriendListDelegate> m_delegate;
  224. };
  225. class GFRCB : public mars::stn::GetFriendRequestCallback {
  226. public:
  227. GFRCB(id<RefreshFriendRequestDelegate> delegate) : m_delegate(delegate) {}
  228. void onSuccess(bool hasNewRequest) {
  229. if(m_delegate && hasNewRequest) {
  230. [m_delegate onFriendRequestUpdated];
  231. }
  232. }
  233. void onFalure(int errorCode) {
  234. }
  235. id<RefreshFriendRequestDelegate> m_delegate;
  236. };
  237. class GSCB : public mars::stn::GetSettingCallback {
  238. public:
  239. GSCB(id<RefreshSettingDelegate> delegate) : m_delegate(delegate) {}
  240. void onSuccess(bool hasNewRequest) {
  241. if(m_delegate && hasNewRequest) {
  242. [m_delegate onSettingUpdated];
  243. }
  244. }
  245. void onFalure(int errorCode) {
  246. }
  247. id<RefreshSettingDelegate> m_delegate;
  248. };
  249. @interface WFCCNetworkService () <ConnectionStatusDelegate, ReceiveMessageDelegate, RefreshUserInfoDelegate, RefreshGroupInfoDelegate, WFCCNetworkStatusDelegate, RefreshFriendListDelegate, RefreshFriendRequestDelegate, RefreshSettingDelegate, RefreshChannelInfoDelegate, RefreshGroupMemberDelegate>
  250. @property(nonatomic, assign)ConnectionStatus currentConnectionStatus;
  251. @property (nonatomic, strong)NSString *userId;
  252. @property (nonatomic, strong)NSString *passwd;
  253. @property(nonatomic, strong)NSString *serverHost;
  254. @property(nonatomic, assign)UIBackgroundTaskIdentifier bgTaskId;
  255. @property(nonatomic, strong)NSTimer *forceConnectTimer;
  256. @property(nonatomic, strong)NSTimer *suspendTimer;
  257. @property(nonatomic, strong)NSTimer *endBgTaskTimer;
  258. @property(nonatomic, strong)NSString *backupDeviceToken;
  259. @property(nonatomic, strong)NSString *backupVoipDeviceToken;
  260. @property(nonatomic, assign)BOOL requestProxying;
  261. @property(nonatomic, strong) NSMutableArray *messageFilterList;
  262. - (void)reportEvent_OnForeground:(BOOL)isForeground;
  263. @property(nonatomic, assign)NSUInteger backgroudRunTime;
  264. @end
  265. @implementation WFCCNetworkService
  266. static WFCCNetworkService * sharedSingleton = nil;
  267. + (void)startLog {
  268. NSString* logPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/log"];
  269. // set do not backup for logpath
  270. const char* attrName = "com.apple.MobileBackup";
  271. u_int8_t attrValue = 1;
  272. setxattr([logPath UTF8String], attrName, &attrValue, sizeof(attrValue), 0, 0);
  273. // init xlog
  274. #if DEBUG
  275. xlogger_SetLevel(kLevelVerbose);
  276. appender_set_console_log(true);
  277. #else
  278. xlogger_SetLevel(kLevelInfo);
  279. appender_set_console_log(false);
  280. #endif
  281. appender_open(kAppednerAsync, [logPath UTF8String], "Test", NULL);
  282. }
  283. + (void)stopLog {
  284. appender_close();
  285. }
  286. + (NSArray<NSString *> *)getLogFilesPath {
  287. NSString* logPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/log"];
  288. NSFileManager *myFileManager = [NSFileManager defaultManager];
  289. NSDirectoryEnumerator *myDirectoryEnumerator = [myFileManager enumeratorAtPath:logPath];
  290. BOOL isDir = NO;
  291. BOOL isExist = NO;
  292. NSMutableArray *output = [[NSMutableArray alloc] init];
  293. for (NSString *path in myDirectoryEnumerator.allObjects) {
  294. isExist = [myFileManager fileExistsAtPath:[NSString stringWithFormat:@"%@/%@", logPath, path] isDirectory:&isDir];
  295. if (!isDir) {
  296. if ([path containsString:@"Test_"]) {
  297. [output addObject:[NSString stringWithFormat:@"%@/%@", logPath, path]];
  298. }
  299. }
  300. }
  301. return output;
  302. }
  303. - (void)onRecallMessage:(long long)messageUid {
  304. dispatch_async(dispatch_get_main_queue(), ^{
  305. [[NSNotificationCenter defaultCenter] postNotificationName:kRecallMessages object:@(messageUid)];
  306. if ([self.receiveMessageDelegate respondsToSelector:@selector(onRecallMessage:)]) {
  307. [self.receiveMessageDelegate onRecallMessage:messageUid];
  308. }
  309. });
  310. }
  311. - (void)onDeleteMessage:(long long)messageUid {
  312. dispatch_async(dispatch_get_main_queue(), ^{
  313. [[NSNotificationCenter defaultCenter] postNotificationName:kDeleteMessages object:@(messageUid)];
  314. if ([self.receiveMessageDelegate respondsToSelector:@selector(onDeleteMessage:)]) {
  315. [self.receiveMessageDelegate onDeleteMessage:messageUid];
  316. }
  317. });
  318. }
  319. - (void)onReceiveMessage:(NSArray<WFCCMessage *> *)messages hasMore:(BOOL)hasMore {
  320. dispatch_async(dispatch_get_main_queue(), ^{
  321. NSMutableArray *messageList = [messages mutableCopy];
  322. for (WFCCMessage *message in messages) {
  323. for (id<ReceiveMessageFilter> filter in self.messageFilterList) {
  324. @try {
  325. if ([filter onReceiveMessage:message]) {
  326. [messageList removeObject:message];
  327. break;
  328. }
  329. } @catch (NSException *exception) {
  330. NSLog(@"%@", exception);
  331. break;
  332. }
  333. }
  334. }
  335. [[NSNotificationCenter defaultCenter] postNotificationName:kReceiveMessages object:messageList];
  336. [self.receiveMessageDelegate onReceiveMessage:messageList hasMore:hasMore];
  337. });
  338. }
  339. - (void)onMessageReaded:(NSArray<WFCCReadReport *> *)readeds {
  340. dispatch_async(dispatch_get_main_queue(), ^{
  341. [[NSNotificationCenter defaultCenter] postNotificationName:kMessageReaded object:readeds];
  342. if ([self.receiveMessageDelegate respondsToSelector:@selector(onMessageReaded:)]) {
  343. [self.receiveMessageDelegate onMessageReaded:readeds];
  344. }
  345. });
  346. }
  347. - (void)onMessageDelivered:(NSArray<WFCCDeliveryReport *> *)delivereds {
  348. dispatch_async(dispatch_get_main_queue(), ^{
  349. [[NSNotificationCenter defaultCenter] postNotificationName:kMessageDelivered object:delivereds];
  350. if ([self.receiveMessageDelegate respondsToSelector:@selector(onMessageDelivered:)]) {
  351. [self.receiveMessageDelegate onMessageDelivered:delivereds];
  352. }
  353. });
  354. }
  355. - (void)addReceiveMessageFilter:(id<ReceiveMessageFilter>)filter {
  356. [self.messageFilterList addObject:filter];
  357. }
  358. - (void)removeReceiveMessageFilter:(id<ReceiveMessageFilter>)filter {
  359. [self.messageFilterList removeObject:filter];
  360. }
  361. - (void)onDisconnected {
  362. mars::baseevent::OnDestroy();
  363. }
  364. - (void)setCurrentConnectionStatus:(ConnectionStatus)currentConnectionStatus {
  365. NSLog(@"Connection status changed to (%ld)", (long)currentConnectionStatus);
  366. if (_currentConnectionStatus != currentConnectionStatus) {
  367. _currentConnectionStatus = currentConnectionStatus;
  368. [[NSNotificationCenter defaultCenter] postNotificationName:kConnectionStatusChanged object:@(_currentConnectionStatus)];
  369. if (_connectionStatusDelegate) {
  370. [_connectionStatusDelegate onConnectionStatusChanged:currentConnectionStatus];
  371. }
  372. }
  373. }
  374. - (void)onConnectionStatusChanged:(ConnectionStatus)status {
  375. if (!_logined || kConnectionStatusRejected == status) {
  376. dispatch_async(dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT), ^{
  377. [self disconnect:YES clearSession:YES];
  378. });
  379. return;
  380. }
  381. if((int)status == (int)mars::stn::kConnectionStatusServerDown) {
  382. status = kConnectionStatusUnconnected;
  383. }
  384. dispatch_async(dispatch_get_main_queue(), ^{
  385. self.currentConnectionStatus = status;
  386. if (status == kConnectionStatusConnected) {
  387. if (self.backupDeviceToken.length) {
  388. [self setDeviceToken:self.backupDeviceToken];
  389. }
  390. if (self.backupVoipDeviceToken.length) {
  391. [self setVoipDeviceToken:self.backupVoipDeviceToken];
  392. }
  393. }
  394. });
  395. }
  396. + (WFCCNetworkService *)sharedInstance {
  397. if (sharedSingleton == nil) {
  398. @synchronized (self) {
  399. if (sharedSingleton == nil) {
  400. sharedSingleton = [[WFCCNetworkService alloc] init];
  401. }
  402. }
  403. }
  404. return sharedSingleton;
  405. }
  406. - (instancetype)init {
  407. self = [super init];
  408. if (self) {
  409. _currentConnectionStatus = kConnectionStatusLogout;
  410. _messageFilterList = [[NSMutableArray alloc] init];
  411. [[NSNotificationCenter defaultCenter] addObserver:self
  412. selector:@selector(onAppSuspend)
  413. name:UIApplicationDidEnterBackgroundNotification
  414. object:nil];
  415. [[NSNotificationCenter defaultCenter] addObserver:self
  416. selector:@selector(onAppResume)
  417. name:UIApplicationWillEnterForegroundNotification
  418. object:nil];
  419. [[NSNotificationCenter defaultCenter] addObserver:self
  420. selector:@selector(onAppTerminate)
  421. name:UIApplicationWillTerminateNotification
  422. object:nil];
  423. }
  424. return self;
  425. }
  426. - (void)startBackgroundTask {
  427. if (!_logined) {
  428. return;
  429. }
  430. if (_bgTaskId != UIBackgroundTaskInvalid) {
  431. [[UIApplication sharedApplication] endBackgroundTask:_bgTaskId];
  432. }
  433. __weak typeof(self) ws = self;
  434. _bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
  435. if (ws.suspendTimer) {
  436. [ws.suspendTimer invalidate];
  437. ws.suspendTimer = nil;
  438. }
  439. if(ws.endBgTaskTimer) {
  440. [ws.endBgTaskTimer invalidate];
  441. ws.endBgTaskTimer = nil;
  442. }
  443. if(ws.forceConnectTimer) {
  444. [ws.forceConnectTimer invalidate];
  445. ws.forceConnectTimer = nil;
  446. }
  447. ws.bgTaskId = UIBackgroundTaskInvalid;
  448. }];
  449. }
  450. - (void)onAppSuspend {
  451. if (!_logined) {
  452. return;
  453. }
  454. [self reportEvent_OnForeground:NO];
  455. self.backgroudRunTime = 0;
  456. [self startBackgroundTask];
  457. [self checkBackGroundTask];
  458. }
  459. - (void)checkBackGroundTask {
  460. if(_suspendTimer) {
  461. [_suspendTimer invalidate];
  462. }
  463. if(_endBgTaskTimer) {
  464. [_endBgTaskTimer invalidate];
  465. _endBgTaskTimer = nil;
  466. }
  467. NSTimeInterval timeInterval = 3;
  468. _suspendTimer = [NSTimer scheduledTimerWithTimeInterval:timeInterval
  469. target:self
  470. selector:@selector(suspend)
  471. userInfo:nil
  472. repeats:NO];
  473. }
  474. - (void)suspend {
  475. if(_bgTaskId != UIBackgroundTaskInvalid) {
  476. self.backgroudRunTime += 3;
  477. BOOL inCall = NO;
  478. Class cls = NSClassFromString(@"WFAVEngineKit");
  479. if (cls && [cls respondsToSelector:@selector(isCallActive)] && [cls performSelector:@selector(isCallActive)]) {
  480. inCall = YES;
  481. }
  482. if ((mars::stn::GetTaskCount() > 0 && self.backgroudRunTime < 60) || (inCall && self.backgroudRunTime < 1800)) {
  483. [self checkBackGroundTask];
  484. } else {
  485. mars::stn::Reset();
  486. _endBgTaskTimer = [NSTimer scheduledTimerWithTimeInterval:1
  487. target:self
  488. selector:@selector(endBgTask)
  489. userInfo:nil
  490. repeats:NO];
  491. }
  492. }
  493. }
  494. - (void)endBgTask {
  495. if(_bgTaskId != UIBackgroundTaskInvalid) {
  496. [[UIApplication sharedApplication] endBackgroundTask:_bgTaskId];
  497. _bgTaskId = UIBackgroundTaskInvalid;
  498. }
  499. if (_suspendTimer) {
  500. [_suspendTimer invalidate];
  501. _suspendTimer = nil;
  502. }
  503. if(_endBgTaskTimer) {
  504. [_endBgTaskTimer invalidate];
  505. _endBgTaskTimer = nil;
  506. }
  507. if (_forceConnectTimer) {
  508. [_forceConnectTimer invalidate];
  509. _forceConnectTimer = nil;
  510. }
  511. self.backgroudRunTime = 0;
  512. }
  513. - (void)onAppResume {
  514. if (!_logined) {
  515. return;
  516. }
  517. [self reportEvent_OnForeground:YES];
  518. mars::stn::MakesureLonglinkConnected();
  519. [self endBgTask];
  520. }
  521. - (void)onAppTerminate {
  522. mars::stn::AppWillTerminate();
  523. }
  524. - (void)dealloc {
  525. }
  526. - (void) createMars {
  527. mars::app::SetCallback(mars::app::AppCallBack::Instance());
  528. mars::stn::setConnectionStatusCallback(new CSCB(self));
  529. mars::stn::setReceiveMessageCallback(new RPCB(self));
  530. mars::stn::setRefreshUserInfoCallback(new GUCB(self));
  531. mars::stn::setRefreshGroupInfoCallback(new GGCB(self));
  532. mars::stn::setRefreshGroupMemberCallback(new GGMCB(self));
  533. mars::stn::setRefreshChannelInfoCallback(new GCHCB(self));
  534. mars::stn::setRefreshFriendListCallback(new GFLCB(self));
  535. mars::stn::setRefreshFriendRequestCallback(new GFRCB(self));
  536. mars::stn::setRefreshSettingCallback(new GSCB(self));
  537. mars::baseevent::OnCreate();
  538. }
  539. - (BOOL)connect:(NSString *)host {
  540. bool newDB = mars::stn::Connect([host UTF8String]);
  541. dispatch_async(dispatch_get_main_queue(), ^{
  542. if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
  543. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  544. if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
  545. [self onAppSuspend];
  546. }
  547. });
  548. }
  549. });
  550. if (newDB) {
  551. return YES;
  552. }
  553. return NO;
  554. }
  555. - (void)forceConnectTimeOut {
  556. if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
  557. [self onAppSuspend];
  558. }
  559. }
  560. - (void)forceConnect:(NSUInteger)second {
  561. __weak typeof(self)ws = self;
  562. dispatch_async(dispatch_get_main_queue(), ^{
  563. if (ws.logined &&[UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
  564. [self onAppResume];
  565. [self startBackgroundTask];
  566. ws.forceConnectTimer = [NSTimer scheduledTimerWithTimeInterval:second
  567. target:self
  568. selector:@selector(forceConnectTimeOut)
  569. userInfo:nil
  570. repeats:NO];
  571. }
  572. });
  573. }
  574. - (void)cancelForceConnect {
  575. __weak typeof(self)ws = self;
  576. dispatch_async(dispatch_get_main_queue(), ^{
  577. if (ws.forceConnectTimer) {
  578. [ws.forceConnectTimer invalidate];
  579. ws.forceConnectTimer = nil;
  580. }
  581. if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
  582. [self onAppSuspend];
  583. }
  584. });
  585. }
  586. - (long long)serverDeltaTime {
  587. return mars::stn::getServerDeltaTime();
  588. }
  589. - (NSString *)getClientId {
  590. return [UIDevice currentDevice].identifierForVendor.UUIDString;
  591. }
  592. - (BOOL)connect:(NSString *)userId token:(NSString *)token {
  593. if (_logined) {
  594. for (int i = 0; i < 10; i++) {
  595. xerror2(TSF"Error: 使用错误,已经connect过了,不能再次connect。如果切换用户请先disconnect,再connect。请修正改错误");
  596. }
  597. #if DEBUG
  598. exit(-1);
  599. #endif
  600. return NO;
  601. }
  602. _logined = YES;
  603. mars::app::AppCallBack::Instance()->SetAccountUserName([userId UTF8String]);
  604. [self createMars];
  605. self.userId = userId;
  606. self.passwd = token;
  607. if(!mars::stn::setAuthInfo([userId cStringUsingEncoding:NSUTF8StringEncoding], [token cStringUsingEncoding:NSUTF8StringEncoding])) {
  608. return NO;
  609. }
  610. self.currentConnectionStatus = kConnectionStatusConnecting;
  611. [[WFCCNetworkStatus sharedInstance] Start:[WFCCNetworkService sharedInstance]];
  612. return [self connect:self.serverHost];
  613. }
  614. - (void)disconnect:(BOOL)disablePush clearSession:(BOOL)clearSession {
  615. _logined = NO;
  616. self.userId = nil;
  617. dispatch_async(dispatch_get_main_queue(), ^{
  618. self.currentConnectionStatus = kConnectionStatusLogout;
  619. });
  620. [[WFCCNetworkStatus sharedInstance] Stop];
  621. int flag = 0;
  622. if (clearSession) {
  623. flag = 8;
  624. } else if(disablePush) {
  625. flag = 1;
  626. }
  627. if (mars::stn::getConnectionStatus() != mars::stn::kConnectionStatusConnected && mars::stn::getConnectionStatus() != mars::stn::kConnectionStatusReceiving) {
  628. mars::stn::Disconnect(flag);
  629. [self destroyMars];
  630. } else {
  631. mars::stn::Disconnect(flag);
  632. }
  633. }
  634. - (void)setServerAddress:(NSString *)host {
  635. self.serverHost = host;
  636. }
  637. - (NSString *)getHost {
  638. return [NSString stringWithUTF8String:mars::stn::GetHost().c_str()];
  639. }
  640. - (void)destroyMars {
  641. [[WFCCNetworkStatus sharedInstance] Stop];
  642. mars::baseevent::OnDestroy();
  643. }
  644. // event reporting
  645. - (void)reportEvent_OnForeground:(BOOL)isForeground {
  646. mars::baseevent::OnForeground(isForeground);
  647. }
  648. - (void)setDeviceToken:(NSString *)token {
  649. if (token.length == 0) {
  650. return;
  651. }
  652. if (!self.isLogined || self.currentConnectionStatus != kConnectionStatusConnected) {
  653. self.backupDeviceToken = token;
  654. return;
  655. }
  656. NSString *appName =
  657. [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
  658. mars::stn::setDeviceToken([appName UTF8String], [token UTF8String], mars::app::AppCallBack::Instance()->GetPushType());
  659. }
  660. - (void)setVoipDeviceToken:(NSString *)token {
  661. if (token.length == 0) {
  662. return;
  663. }
  664. if (!self.isLogined || self.currentConnectionStatus != kConnectionStatusConnected) {
  665. self.backupVoipDeviceToken = token;
  666. return;
  667. }
  668. NSString *appName =
  669. [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
  670. mars::stn::setDeviceToken([appName UTF8String], [token UTF8String], 2);
  671. }
  672. - (NSString *)encodedCid {
  673. return [NSString stringWithUTF8String:mars::stn::GetEncodedCid().c_str()];
  674. }
  675. - (void)onGroupInfoUpdated:(NSArray<WFCCGroupInfo *> *)updatedGroupInfo {
  676. dispatch_async(dispatch_get_main_queue(), ^{
  677. for (WFCCGroupInfo *groupInfo in updatedGroupInfo) {
  678. [[NSNotificationCenter defaultCenter] postNotificationName:kGroupInfoUpdated object:groupInfo.target userInfo:@{@"groupInfo":groupInfo}];
  679. }
  680. });
  681. }
  682. - (void)onGroupMemberUpdated:(NSString *)groupId members:(NSArray<WFCCGroupMember *> *)updatedGroupMember {
  683. dispatch_async(dispatch_get_main_queue(), ^{
  684. [[NSNotificationCenter defaultCenter] postNotificationName:kGroupMemberUpdated object:groupId];
  685. });
  686. }
  687. - (void)onChannelInfoUpdated:(NSArray<WFCCChannelInfo *> *)updatedChannelInfo {
  688. dispatch_async(dispatch_get_main_queue(), ^{
  689. for (WFCCChannelInfo *channelInfo in updatedChannelInfo) {
  690. [[NSNotificationCenter defaultCenter] postNotificationName:kChannelInfoUpdated object:channelInfo.channelId userInfo:@{@"channelInfo":channelInfo}];
  691. }
  692. });
  693. }
  694. - (void)onUserInfoUpdated:(NSArray<WFCCUserInfo *> *)updatedUserInfo {
  695. dispatch_async(dispatch_get_main_queue(), ^{
  696. for (WFCCUserInfo *userInfo in updatedUserInfo) {
  697. [[NSNotificationCenter defaultCenter] postNotificationName:kUserInfoUpdated object:userInfo.userId userInfo:@{@"userInfo":userInfo}];
  698. }
  699. });
  700. }
  701. - (void)onFriendListUpdated {
  702. dispatch_async(dispatch_get_main_queue(), ^{
  703. [[NSNotificationCenter defaultCenter] postNotificationName:kFriendListUpdated object:nil];
  704. });
  705. }
  706. - (void)onFriendRequestUpdated {
  707. dispatch_async(dispatch_get_main_queue(), ^{
  708. [[NSNotificationCenter defaultCenter] postNotificationName:kFriendRequestUpdated object:nil];
  709. });
  710. }
  711. - (NSData *)encodeData:(NSData *)data {
  712. std::string encodeData = mars::stn::GetEncodeDataEx(std::string((char *)data.bytes, data.length));
  713. return [[NSData alloc] initWithBytes:encodeData.c_str() length:encodeData.length()];
  714. }
  715. - (void)onSettingUpdated {
  716. dispatch_async(dispatch_get_main_queue(), ^{
  717. [[NSNotificationCenter defaultCenter] postNotificationName:kSettingUpdated object:nil];
  718. });
  719. }
  720. - (NSData *)decodeData:(NSData *)data {
  721. std::string encodeData = mars::stn::GetDecodeData(std::string((char *)data.bytes, data.length));
  722. return [[NSData alloc] initWithBytes:encodeData.c_str() length:encodeData.length()];
  723. }
  724. #pragma mark WFCCNetworkStatusDelegate
  725. -(void) ReachabilityChange:(UInt32)uiFlags {
  726. if ((uiFlags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) {
  727. mars::baseevent::OnNetworkChange();
  728. }
  729. }
  730. @end