2
0

WFCCNetworkService.mm 30 KB

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