Authored by 钱兢安

socket加密验证 review by 盖建秋

@@ -16,5 +16,7 @@ @@ -16,5 +16,7 @@
16 #import "UIViewAdditions.h" 16 #import "UIViewAdditions.h"
17 #import "YHAssistant.h" 17 #import "YHAssistant.h"
18 #import "UtilsMacros.h" 18 #import "UtilsMacros.h"
  19 +#import "M16Model.h"
  20 +#import "APIStringMacros.h"
19 21
20 #endif 22 #endif
@@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
5 // Created by Arthur on 16/6/14. 5 // Created by Arthur on 16/6/14.
6 // Copyright © 2016年 YOHO. All rights reserved. 6 // Copyright © 2016年 YOHO. All rights reserved.
7 // 7 //
  8 +#define kIphonePrivate @"a85bb0674e08986c6b115d5e3a4884fa"
  9 +#define SOCKET_LIVE_TIMEOUT 10
8 10
9 #import "GCDAsyncSocket+SocketHandler.h" 11 #import "GCDAsyncSocket+SocketHandler.h"
10 12
@@ -13,16 +15,17 @@ @@ -13,16 +15,17 @@
13 - (BOOL)writeDataWithParams:(NSDictionary *)params tag:(long)tag 15 - (BOOL)writeDataWithParams:(NSDictionary *)params tag:(long)tag
14 { 16 {
15 NSError *error; 17 NSError *error;
16 - NSData *data = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:&error]; 18 + NSMutableDictionary *dic = [self encodeParams:params];//md5加密
  19 + NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error];
17 NSMutableData *mutaData = [NSMutableData dataWithData:data]; 20 NSMutableData *mutaData = [NSMutableData dataWithData:data];
18 [mutaData appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 21 [mutaData appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
19 // DLog(@"发送:%@",[[NSString alloc] initWithData:mutaData encoding:NSUTF8StringEncoding]); 22 // DLog(@"发送:%@",[[NSString alloc] initWithData:mutaData encoding:NSUTF8StringEncoding]);
20 if (mutaData) { 23 if (mutaData) {
21 - [self writeData:mutaData withTimeout:10 tag:tag]; 24 + [self writeData:mutaData withTimeout:SOCKET_LIVE_TIMEOUT tag:tag];
22 [self readDataWithTimeout:-1 tag:tag]; 25 [self readDataWithTimeout:-1 tag:tag];
23 return YES; 26 return YES;
24 } else { 27 } else {
25 -// DLog(@"请求序列化错误:%@", error); 28 + DLog(@"请求序列化错误:%@", error);
26 return NO; 29 return NO;
27 } 30 }
28 } 31 }
@@ -56,8 +59,35 @@ @@ -56,8 +59,35 @@
56 } 59 }
57 } 60 }
58 } 61 }
59 -// DLog(@"服务器返回数据序列化错误:%@", error); 62 + DLog(@"服务器返回数据序列化错误:%@", error);
60 } 63 }
61 } 64 }
  65 +// md5加密
  66 +- (NSMutableDictionary *)encodeParams:(NSDictionary *)parameters
  67 +{
  68 + NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithDictionary:parameters];
  69 + [params setObject:kIphonePrivate forKey:@"private_key"];
  70 + NSArray *allKeys = [params allKeys];
  71 + NSArray *sortedArray = [allKeys sortedArrayUsingSelector:@selector(compare:)];
  72 +
  73 + NSMutableArray *strings = [NSMutableArray array];
  74 + for (NSString *key in sortedArray) {
  75 + id value = [params objectForKey:key];
  76 + if ([value isKindOfClass:[NSString class]]) {
  77 + value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  78 + value = [value stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  79 + value = [value stringByReplacingOccurrencesOfString:@"\t" withString:@""];
  80 + value = [value stringByReplacingOccurrencesOfString:@"\r" withString:@""];
  81 + }
  82 + [params setObject:value forKey:key];
  83 + [strings addObject:[NSString stringWithFormat:@"%@=%@", key, value]];
  84 + }
  85 + NSString *source = [strings componentsJoinedByString:@"&"];
  86 + NSString *secret = [[source md5String] lowercaseString];
  87 + [params removeObjectForKey:@"private_key"];
  88 +
  89 + [params setObject:secret forKey:@"secret"];
  90 + return params;
  91 +}
62 92
63 @end 93 @end
@@ -237,32 +237,28 @@ @@ -237,32 +237,28 @@
237 } 237 }
238 238
239 #pragma mark --sockerserviceDelegate 239 #pragma mark --sockerserviceDelegate
240 -- (void)userPraised:(NSString *)currentTotalNum isSelfPraise:(BOOL)isSelf 240 +- (NSString *)formatNumer:(NSString *)number
241 { 241 {
242 - NSInteger num = currentTotalNum.integerValue; 242 + NSInteger num = number.integerValue;
243 NSInteger a = 0; 243 NSInteger a = 0;
244 NSInteger b = 0; 244 NSInteger b = 0;
245 if (num >9999) { 245 if (num >9999) {
246 a = ceilf(num /10000); 246 a = ceilf(num /10000);
247 b = ceilf((num - a * 10000)/ 1000); 247 b = ceilf((num - a * 10000)/ 1000);
248 - self.emojiCountLabel.text =[NSString stringWithFormat:@"%ld.%ld万",(long)a,(long)b]; 248 + return [NSString stringWithFormat:@"%ld.%ld万",(long)a,(long)b];
249 }else{ 249 }else{
250 - self.emojiCountLabel.text =[NSString stringWithFormat:@"%@",currentTotalNum]; 250 + return [NSString stringWithFormat:@"%@",number];
251 } 251 }
252 } 252 }
253 253
  254 +- (void)userPraised:(NSString *)currentTotalNum isSelfPraise:(BOOL)isSelf
  255 +{
  256 + self.emojiCountLabel.text =[self formatNumer:currentTotalNum];
  257 +}
  258 +
254 - (void)currentPeopleNumber:(NSString *)peopleNumber 259 - (void)currentPeopleNumber:(NSString *)peopleNumber
255 { 260 {
256 - NSInteger num = peopleNumber.integerValue;  
257 - NSInteger a = 0;  
258 - NSInteger b = 0;  
259 - if (num >9999) {  
260 - a = ceilf(num /10000);  
261 - b = ceilf((num - a * 10000)/ 1000);  
262 - self.onlineCountLabel.text =[NSString stringWithFormat:@"%ld.%ld万人在线",(long)a,(long)b];  
263 - }else{  
264 - self.onlineCountLabel.text =[NSString stringWithFormat:@"%@人在线",peopleNumber];  
265 - } 261 + self.onlineCountLabel.text =[NSString stringWithFormat:@"%@人在线",[self formatNumer:peopleNumber]];
266 } 262 }
267 263
268 - (void)livePalyEnd:(NSString *)audienceNums likeNums:(NSString *)likeNums videoLen:(NSString *)videoLen 264 - (void)livePalyEnd:(NSString *)audienceNums likeNums:(NSString *)likeNums videoLen:(NSString *)videoLen
@@ -270,7 +266,11 @@ @@ -270,7 +266,11 @@
270 266
271 } 267 }
272 268
273 - 269 +- (void)liveOnlineNums:(NSString *)onlineNums likes:(NSString *)likes
  270 +{
  271 + self.emojiCountLabel.text =[self formatNumer:likes];
  272 + self.onlineCountLabel.text =[NSString stringWithFormat:@"%@人在线",[self formatNumer:onlineNums]];
  273 +}
274 274
275 #pragma mark - Publisher delegate methods... 275 #pragma mark - Publisher delegate methods...
276 276
@@ -9,9 +9,6 @@ @@ -9,9 +9,6 @@
9 #import <Foundation/Foundation.h> 9 #import <Foundation/Foundation.h>
10 #import "YH_BarrageViewController.h" 10 #import "YH_BarrageViewController.h"
11 #import "M16Service.h" 11 #import "M16Service.h"
12 -#import "M16Model.h"  
13 -#import "Macros.h"  
14 -#import "YHAssistant.h"  
15 12
16 typedef NS_ENUM(NSInteger, SOCKET_TAG) { 13 typedef NS_ENUM(NSInteger, SOCKET_TAG) {
17 SOCKET_TAG_EOR = -1, 14 SOCKET_TAG_EOR = -1,
@@ -26,6 +23,7 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) { @@ -26,6 +23,7 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) {
26 SOCKET_TAG_NotifyPeopleNumber = 10, //服务器通知当前在线人数 23 SOCKET_TAG_NotifyPeopleNumber = 10, //服务器通知当前在线人数
27 SOCKET_TAG_EndPlay = 11, //结束播放 24 SOCKET_TAG_EndPlay = 11, //结束播放
28 SOCKET_TAG_NotifyEndPlay = 12, //服务器通知结束播放 25 SOCKET_TAG_NotifyEndPlay = 12, //服务器通知结束播放
  26 + SOCKET_TAG_NotifyOnlineAndLikes = 13, //服务器通知点赞数和在线人数
29 }; 27 };
30 28
31 @protocol YH_SocketServiceDelegate <NSObject> 29 @protocol YH_SocketServiceDelegate <NSObject>
@@ -33,7 +31,7 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) { @@ -33,7 +31,7 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) {
33 - (void)userPraised:(NSString *)currentTotalNum isSelfPraise:(BOOL)isSelf; 31 - (void)userPraised:(NSString *)currentTotalNum isSelfPraise:(BOOL)isSelf;
34 - (void)currentPeopleNumber:(NSString *)peopleNumber; 32 - (void)currentPeopleNumber:(NSString *)peopleNumber;
35 - (void)livePalyEnd:(NSString *)audienceNums likeNums:(NSString *)likeNums videoLen:(NSString *)videoLen; 33 - (void)livePalyEnd:(NSString *)audienceNums likeNums:(NSString *)likeNums videoLen:(NSString *)videoLen;
36 - 34 +- (void)liveOnlineNums:(NSString *)onlineNums likes:(NSString *)likes;
37 @end 35 @end
38 36
39 @interface YH_SocketService : NSObject 37 @interface YH_SocketService : NSObject
@@ -70,6 +68,6 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) { @@ -70,6 +68,6 @@ typedef NS_ENUM(NSInteger, SOCKET_TAG) {
70 -(void)logout; 68 -(void)logout;
71 69
72 //手动释放timer 70 //手动释放timer
73 -- (void)reset; 71 +//- (void)reset;
74 72
75 @end 73 @end
@@ -9,17 +9,17 @@ @@ -9,17 +9,17 @@
9 #import "YH_SocketService.h" 9 #import "YH_SocketService.h"
10 #import "GCDAsyncSocket+SocketHandler.h" 10 #import "GCDAsyncSocket+SocketHandler.h"
11 11
12 -  
13 #define TimeIntervalForHeartBeat 59 12 #define TimeIntervalForHeartBeat 59
14 #define SOCKET_COMMAND @"cmd" 13 #define SOCKET_COMMAND @"cmd"
15 #define SOCKET_CONNECT_MAX_COUNT 9 14 #define SOCKET_CONNECT_MAX_COUNT 9
16 15
17 @interface YH_SocketService ()<GCDAsyncSocketDelegate> 16 @interface YH_SocketService ()<GCDAsyncSocketDelegate>
18 { 17 {
19 - GCDAsyncSocket *_socket;  
20 - NSTimer *_heartBeatTimer; // ❤️ 18 + BOOL _hasLoginWithNameSuccessed;
21 } 19 }
22 @property (nonatomic, strong) NSTimer *connectTimer; 20 @property (nonatomic, strong) NSTimer *connectTimer;
  21 +@property (nonatomic, strong) NSTimer *heartBeatTimer; // ❤️
  22 +@property (nonatomic, strong) GCDAsyncSocket *socket;
23 23
24 @end 24 @end
25 25
@@ -30,24 +30,69 @@ @@ -30,24 +30,69 @@
30 { 30 {
31 self = [super init]; 31 self = [super init];
32 if (self) { 32 if (self) {
33 - _socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];  
34 - _heartBeatTimer = [NSTimer scheduledTimerWithTimeInterval:TimeIntervalForHeartBeat target:self selector:@selector(_heartbeat) userInfo:nil repeats:YES]; 33 + self.socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
  34 + self.heartBeatTimer = [NSTimer scheduledTimerWithTimeInterval:TimeIntervalForHeartBeat target:self selector:@selector(_heartbeat) userInfo:nil repeats:YES];
  35 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkReachabilityDidChange:) name:AFNetworkingReachabilityDidChangeNotification object:nil];
  36 +
35 } 37 }
36 38
37 return self; 39 return self;
38 } 40 }
39 41
40 -- (void)reset 42 +- (NSString *)getProperIPWithAddress:(NSString *)ipAddr port:(UInt32)port
41 { 43 {
42 - DLog(@"socket service reset!!");  
43 - if (_heartBeatTimer) {  
44 - [_heartBeatTimer invalidate];  
45 - _heartBeatTimer = nil; 44 + NSError *addresseError = nil;
  45 + NSArray *addresseArray = [GCDAsyncSocket lookupHost:ipAddr
  46 + port:port
  47 + error:&addresseError];
  48 + if (addresseError) {
  49 + NSLog(@"");
  50 + }
  51 +
  52 + NSString *ipv6Addr = @"";
  53 + for (NSData *addrData in addresseArray) {
  54 + if ([GCDAsyncSocket isIPv6Address:addrData]) {
  55 + ipv6Addr = [GCDAsyncSocket hostFromAddress:addrData];
  56 + }
  57 + }
  58 +
  59 + if (ipv6Addr.length == 0) {
  60 + ipv6Addr = ipAddr;
46 } 61 }
47 62
  63 + return ipv6Addr;
  64 +}
  65 +
  66 +//网络发生变化时重连
  67 +- (void)networkReachabilityDidChange:(NSNotification *)notification
  68 +{
  69 + [self reConnect];
  70 +}
  71 +
  72 +- (void)reConnect
  73 +{
48 [_socket disconnect]; 74 [_socket disconnect];
  75 + self.socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
  76 + [self connectToHostRepeat];
49 } 77 }
50 78
  79 +- (void)dealloc
  80 +{
  81 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  82 +}
  83 +
  84 +
  85 +//- (void)reset
  86 +//{
  87 +// DLog(@"socket service reset!!");
  88 +// if (_heartBeatTimer) {
  89 +// [_heartBeatTimer invalidate];
  90 +// _heartBeatTimer = nil;
  91 +// }
  92 +//
  93 +// [_socket disconnect];
  94 +//}
  95 +
51 #pragma mark - Private Methods 96 #pragma mark - Private Methods
52 - (void)_heartbeat{ 97 - (void)_heartbeat{
53 98
@@ -61,13 +106,17 @@ @@ -61,13 +106,17 @@
61 106
62 107
63 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_HEARTBEAT), 108 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_HEARTBEAT),
64 - @"msg":@"heartbeat", 109 + @"msg":@"heart_ios",
65 @"room":MakeStringNotNil(self.room), 110 @"room":MakeStringNotNil(self.room),
66 }; 111 };
67 [_socket writeDataWithParams:params tag:SOCKET_TAG_SEND_MSG]; 112 [_socket writeDataWithParams:params tag:SOCKET_TAG_SEND_MSG];
68 113
69 - [_socket readDataWithTimeout:1.0 tag:1];  
70 - 114 +// [self loginToServer];
  115 +// [self listenData];
  116 + //心跳并判断是否已经断掉
  117 + if (![_socket isConnected]) {
  118 + [self reConnect];
  119 + }
71 } 120 }
72 121
73 #pragma mark - Service 122 #pragma mark - Service
@@ -81,7 +130,6 @@ @@ -81,7 +130,6 @@
81 [[NSRunLoop mainRunLoop] addTimer:self.connectTimer forMode:NSRunLoopCommonModes]; 130 [[NSRunLoop mainRunLoop] addTimer:self.connectTimer forMode:NSRunLoopCommonModes];
82 } else { 131 } else {
83 NSLog(@"connent success!"); 132 NSLog(@"connent success!");
84 - [self loginToServer];  
85 } 133 }
86 } else { 134 } else {
87 NSLog(@"get addressList failed!"); 135 NSLog(@"get addressList failed!");
@@ -133,11 +181,13 @@ @@ -133,11 +181,13 @@
133 181
134 - (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port 182 - (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port
135 { 183 {
  184 + NSString *hostProper = [self getProperIPWithAddress:host port:port];
  185 +
136 NSError *socketConnectError = nil; 186 NSError *socketConnectError = nil;
137 187
138 NSAssert(_socket, @"You must init YH_SocketService first!"); 188 NSAssert(_socket, @"You must init YH_SocketService first!");
139 189
140 - [_socket connectToHost:host onPort:port error:&socketConnectError]; 190 + [_socket connectToHost:hostProper onPort:port error:&socketConnectError];
141 191
142 if (socketConnectError) { 192 if (socketConnectError) {
143 DLog(@"connect host error: %@", [socketConnectError localizedDescription]); 193 DLog(@"connect host error: %@", [socketConnectError localizedDescription]);
@@ -159,6 +209,7 @@ @@ -159,6 +209,7 @@
159 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port 209 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
160 { 210 {
161 DLog(@"socket connect success!"); 211 DLog(@"socket connect success!");
  212 + [self loginToServer];
162 [self listenData]; 213 [self listenData];
163 } 214 }
164 215
@@ -181,7 +232,7 @@ @@ -181,7 +232,7 @@
181 switch (tag) { 232 switch (tag) {
182 case SOCKET_TAG_LOGIN: 233 case SOCKET_TAG_LOGIN:
183 { 234 {
184 - [self _heartbeat]; 235 +// [self _heartbeat];
185 } 236 }
186 break; 237 break;
187 238
@@ -225,6 +276,9 @@ @@ -225,6 +276,9 @@
225 case SOCKET_TAG_RESIVE_MSG: 276 case SOCKET_TAG_RESIVE_MSG:
226 case SOCKET_TAG_USER_JOIN: 277 case SOCKET_TAG_USER_JOIN:
227 { 278 {
  279 + if (resDic && [resDic.allKeys containsObject:@"uid"] && [resDic[@"uid"] isEqualToString:self.uid] && [self.uid notNilOrEmpty]) {
  280 + _hasLoginWithNameSuccessed = YES;
  281 + }
228 [self.barrageViewController insertItem:resDic]; 282 [self.barrageViewController insertItem:resDic];
229 } 283 }
230 break; 284 break;
@@ -232,8 +286,8 @@ @@ -232,8 +286,8 @@
232 { 286 {
233 if ([self.delegate respondsToSelector:@selector(userPraised:isSelfPraise:)] && [resDic.allKeys containsObject:@"msg"]) { 287 if ([self.delegate respondsToSelector:@selector(userPraised:isSelfPraise:)] && [resDic.allKeys containsObject:@"msg"]) {
234 yh_dispatch_execute_in_main_queue(^{ 288 yh_dispatch_execute_in_main_queue(^{
235 -  
236 - [self.delegate userPraised:resDic[@"msg"] isSelfPraise:([resDic[@"uid"] isEqualToString:self.uid])]; 289 +// BOOL isSelfPraise =(resDic[@"deviceToken"] && [resDic[@"deviceToken"] isEqualToString:[GVUserDefaults standardUserDefaults].deviceTokenString]);
  290 + [self.delegate userPraised:resDic[@"msg"] isSelfPraise:NO];
237 }); 291 });
238 } 292 }
239 } 293 }
@@ -242,7 +296,7 @@ @@ -242,7 +296,7 @@
242 { 296 {
243 if ([self.delegate respondsToSelector:@selector(currentPeopleNumber:)] && [resDic.allKeys containsObject:@"msg"]) { 297 if ([self.delegate respondsToSelector:@selector(currentPeopleNumber:)] && [resDic.allKeys containsObject:@"msg"]) {
244 yh_dispatch_execute_in_main_queue(^{ 298 yh_dispatch_execute_in_main_queue(^{
245 - [self.delegate currentPeopleNumber:resDic[@"msg"]]; 299 + [self.delegate currentPeopleNumber:resDic[@"onlineNums"]];
246 }); 300 });
247 } 301 }
248 } 302 }
@@ -256,6 +310,15 @@ @@ -256,6 +310,15 @@
256 } 310 }
257 } 311 }
258 break; 312 break;
  313 + case SOCKET_TAG_NotifyOnlineAndLikes:
  314 + {
  315 + if ([self.delegate respondsToSelector:@selector(liveOnlineNums:likes:)]) {
  316 + yh_dispatch_execute_in_main_queue(^{
  317 + [self.delegate liveOnlineNums:resDic[@"onlineNums"] likes:resDic[@"likeNums"]];
  318 + });
  319 + }
  320 + }
  321 + break;
259 default: 322 default:
260 break; 323 break;
261 } 324 }
@@ -288,10 +351,10 @@ @@ -288,10 +351,10 @@
288 - (void)loginToServer 351 - (void)loginToServer
289 { 352 {
290 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_LOGIN), 353 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_LOGIN),
291 - @"uid":MakeStringNotNil(self.uid), 354 + @"uid":(_hasLoginWithNameSuccessed?@"":MakeStringNotNil(self.uid)),
292 @"room":MakeStringNotNil(self.room), 355 @"room":MakeStringNotNil(self.room),
293 - @"name":MakeStringNotNil(self.userName),  
294 - @"avatar":MakeStringNotNil(self.avartar) 356 + @"name":(_hasLoginWithNameSuccessed?@"":MakeStringNotNil(self.userName)),
  357 + @"avatar":(_hasLoginWithNameSuccessed?@"":MakeStringNotNil(self.avartar)),
295 }; 358 };
296 359
297 [_socket writeDataWithParams:params tag:SOCKET_TAG_LOGIN]; 360 [_socket writeDataWithParams:params tag:SOCKET_TAG_LOGIN];
@@ -317,7 +380,8 @@ @@ -317,7 +380,8 @@
317 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_PRAISE), 380 NSDictionary *params = @{@"cmd":@(SOCKET_TAG_PRAISE),
318 @"uid":MakeStringNotNil(self.uid), 381 @"uid":MakeStringNotNil(self.uid),
319 @"msg":@"", 382 @"msg":@"",
320 - @"room":MakeStringNotNil(self.room) 383 + @"room":MakeStringNotNil(self.room),
  384 + @"deviceToken":@"",
321 }; 385 };
322 [_socket writeDataWithParams:params tag:SOCKET_TAG_SEND_MSG]; 386 [_socket writeDataWithParams:params tag:SOCKET_TAG_SEND_MSG];
323 } 387 }