Skip to content

Commit

Permalink
1-调整目录结构。2-增加protobuf对应的编解码器(不完整)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhuruhong committed May 26, 2016
1 parent 95eb694 commit 0ae7d22
Show file tree
Hide file tree
Showing 39 changed files with 423 additions and 170 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

21 changes: 21 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHProtobufVarint32LengthDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// RHProtobufVarint32LengthDecoder.h
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "RHSocketCodecProtocol.h"

@interface RHProtobufVarint32LengthDecoder : NSObject <RHSocketDecoderProtocol>

/**
* 应用协议中允许发送的最大数据块大小,默认为65536
*/
@property (nonatomic, assign) NSUInteger maxFrameSize;

@property (nonatomic, strong) id<RHSocketDecoderProtocol> nextDecoder;

@end
78 changes: 78 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHProtobufVarint32LengthDecoder.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// RHProtobufVarint32LengthDecoder.m
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import "RHProtobufVarint32LengthDecoder.h"
#import "RHSocketException.h"
#import "RHSocketUtils+Protobuf.h"
#import "RHSocketPacketContext.h"

@implementation RHProtobufVarint32LengthDecoder

- (instancetype)init
{
if (self = [super init]) {
_maxFrameSize = NSIntegerMax;
}
return self;
}

- (NSInteger)decode:(id<RHDownstreamPacket>)downstreamPacket output:(id<RHSocketDecoderOutputProtocol>)output
{
id object = [downstreamPacket object];
if (![object isKindOfClass:[NSData class]]) {
[RHSocketException raiseWithReason:@"[Decode] object should be NSData ..."];
return -1;
}

NSData *downstreamData = object;
NSUInteger headIndex = 0;

//先读区2个字节的协议长度 (前2个字节为数据包的长度)
while (downstreamData && downstreamData.length - headIndex > 1) {

NSRange remainRange = NSMakeRange(headIndex, downstreamData.length - headIndex);
NSData *remainData = [downstreamData subdataWithRange:remainRange];

NSInteger countOfLengthByte = [RHSocketUtils computeCountOfLengthByte:remainData];
if (countOfLengthByte <= 0) {
break;
}

NSData *lenData = [downstreamData subdataWithRange:NSMakeRange(headIndex, countOfLengthByte)];
//长度字节数据,可能存在高低位互换,通过数值转换工具处理
NSUInteger frameLen = (NSUInteger)[RHSocketUtils valueWithVarint32Data:lenData];
if (frameLen >= _maxFrameSize - countOfLengthByte) {
[RHSocketException raiseWithReason:@"[Decode] Too Long Frame ..."];
return -1;
}//

//剩余数据,不是完整的数据包,则break继续读取等待
if (downstreamData.length - headIndex < countOfLengthByte + frameLen) {
break;
}
//数据包(长度+内容)
NSData *frameData = [downstreamData subdataWithRange:NSMakeRange(headIndex, countOfLengthByte + frameLen)];

//去除数据长度后的数据内容
RHSocketPacketResponse *ctx = [[RHSocketPacketResponse alloc] init];
ctx.object = [frameData subdataWithRange:NSMakeRange(countOfLengthByte, frameLen)];

//责任链模式,丢给下一个处理器
if (_nextDecoder) {
[_nextDecoder decode:ctx output:output];
} else {
[output didDecode:ctx];
}

//调整已经解码数据
headIndex += frameData.length;
}//while
return headIndex;
}

@end
19 changes: 19 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHProtobufVarint32LengthEncoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// RHProtobufVarint32LengthEncoder.h
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "RHSocketCodecProtocol.h"

@interface RHProtobufVarint32LengthEncoder : NSObject <RHSocketEncoderProtocol>

/**
* 应用协议中允许发送的最大数据块大小,默认为65536
*/
@property (nonatomic, assign) NSUInteger maxFrameSize;

@end
55 changes: 55 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHProtobufVarint32LengthEncoder.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// RHProtobufVarint32LengthEncoder.m
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import "RHProtobufVarint32LengthEncoder.h"
#import "RHSocketException.h"
#import "RHSocketUtils+Protobuf.h"

@implementation RHProtobufVarint32LengthEncoder

- (instancetype)init
{
if (self = [super init]) {
_maxFrameSize = NSIntegerMax;
}
return self;
}

- (void)encode:(id<RHUpstreamPacket>)upstreamPacket output:(id<RHSocketEncoderOutputProtocol>)output
{
id object = [upstreamPacket object];
if (![object isKindOfClass:[NSData class]]) {
[RHSocketException raiseWithReason:@"[Encode] object should be NSData ..."];
return;
}

NSData *data = object;
if (data.length == 0) {
return;
}//

if (data.length >= _maxFrameSize - 4) {
[RHSocketException raiseWithReason:@"[Encode] Too Long Frame ..."];
return;
}//

//可变长度编码,数据块的前两个字节为后续完整数据块的长度
NSUInteger dataLen = data.length;
NSMutableData *sendData = [[NSMutableData alloc] init];

//将数据长度转换为长度字节,写入到数据块中。这里根据head占的字节个数转换data长度,长度不定[1~5]
NSData *headData = [RHSocketUtils dataWithRawVarint32:dataLen];
[sendData appendData:headData];
[sendData appendData:data];
NSTimeInterval timeout = [upstreamPacket timeout];

RHSocketLog(@"timeout: %f, sendData: %@", timeout, sendData);
[output didEncode:sendData timeout:timeout];
}

@end
25 changes: 25 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHSocketUtils+Protobuf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RHSocketUtils+Protobuf.h
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import "RHSocketUtils.h"

@interface RHSocketUtils (Protobuf)

/**
* 计算出一帧数据的长度字节个数 (1~5)
*
* @param frameData 带解码字节
*
* @return 返回一帧数据的长度字节个数, varint32, 返回值为1~5有效,-1为计算失败
*/
+ (NSInteger)computeCountOfLengthByte:(NSData *)frameData;

+ (int64_t)valueWithVarint32Data:(NSData *)data;
+ (NSData *)dataWithRawVarint32:(int64_t)value;

@end
80 changes: 80 additions & 0 deletions RHSocketKit/Core/Codec/Protobuf/RHSocketUtils+Protobuf.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// RHSocketUtils+Protobuf.m
// RHSocketKitDemo
//
// Created by zhuruhong on 16/5/26.
// Copyright © 2016年 zhuruhong. All rights reserved.
//

#import "RHSocketUtils+Protobuf.h"

@implementation RHSocketUtils (Protobuf)

/**
* 计算出一帧数据的长度字节个数 (1~5)
*
* @param frameData 带解码字节
*
* @return 返回一帧数据的长度字节个数, varint32, 返回值为1~5有效,-1为计算失败
*/
+ (NSInteger)computeCountOfLengthByte:(NSData *)frameData
{
//默认长度字节个数为-1
NSInteger countOfLengthByte = -1;
//最大尝试读区个数为4个字节,超过则认为是大数据5个字节
NSInteger maxCountOfLengthByte = MIN(frameData.length, 4);
//从第1个字节开始尝试读取计算
NSInteger testIndex = 0;

while (testIndex < maxCountOfLengthByte) {
NSRange lengthRange = NSMakeRange(testIndex, 1);
NSData *oneByte = [frameData subdataWithRange:lengthRange];
int8_t oneValue = [RHSocketUtils int8FromBytes:oneByte];

if ((oneValue & 0x80) == 0) {
countOfLengthByte = testIndex + 1;
break;
}
testIndex++;//增加长度字节个数
}//while

//超过4个字节,则认为是大数据5个字节
if (testIndex >= 4) {
countOfLengthByte = 5;
}
return countOfLengthByte;
}

+ (int64_t)valueWithVarint32Data:(NSData *)data
{
NSUInteger dataLen = data.length;
int64_t value = 0;
int offset = 0;

while (offset < dataLen) {
int32_t tempVal = 0;
[data getBytes:&tempVal range:NSMakeRange(offset, 1)];
value += (tempVal << (7 * offset));
offset++;
}//while

return value;
}

+ (NSData *)dataWithRawVarint32:(int64_t)value
{
NSMutableData *valData = [[NSMutableData alloc] init];
while (true) {
if ((value & ~0x7F) == 0) {//如果最高位是0,只要一个字节表示
[valData appendBytes:&value length:1];
break;
} else {
int valChar = (value & 0x7F) | 0x80;//先写入低7位,最高位置1
[valData appendBytes:&valChar length:1];
value = value >> 7;//再写高7位
}
}
return valData;
}

@end
2 changes: 1 addition & 1 deletion RHSocketKit/Core/Utils/RHSocketUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ + (int64_t)valueFromBytes:(NSData *)data
int offset = 0;

while (offset < dataLen) {
uint32_t tempVal = 0;
int32_t tempVal = 0;
[data getBytes:&tempVal range:NSMakeRange(offset, 1)];
value += (tempVal << (8 * offset));
offset++;
Expand Down
Loading

0 comments on commit 0ae7d22

Please sign in to comment.