Skip to content

Commit 4748a80

Browse files
committed
ping add
1 parent d46c5cd commit 4748a80

File tree

6 files changed

+185
-840
lines changed

6 files changed

+185
-840
lines changed

NetDiag.xcodeproj/project.pbxproj

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
/* Begin PBXBuildFile section */
1010
A6296E24683C84AC5548DB39 /* libPods-NetDiagTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F50835689CBA65323B9B2AA7 /* libPods-NetDiagTests.a */; };
1111
DF2B76EC1C33702D00643678 /* QNNPing.m in Sources */ = {isa = PBXBuildFile; fileRef = DF2B76EB1C33702D00643678 /* QNNPing.m */; };
12-
DF2B76F11C3B9DA100643678 /* QNNSimplePing.m in Sources */ = {isa = PBXBuildFile; fileRef = DF2B76F01C3B9DA100643678 /* QNNSimplePing.m */; };
1312
DF8DFFC51C60951D00174DA9 /* QNNNslookup.m in Sources */ = {isa = PBXBuildFile; fileRef = DF8DFFC41C60951D00174DA9 /* QNNNslookup.m */; };
1413
DF8DFFD21C61DA1B00174DA9 /* TcpPingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DF8DFFD11C61DA1B00174DA9 /* TcpPingTest.m */; };
1514
DF8DFFD41C61DA1B00174DA9 /* libNetDiag.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DFCEC6451C2EC01D0058EE65 /* libNetDiag.a */; };
@@ -55,8 +54,6 @@
5554
DF2B76EA1C33702D00643678 /* QNNPing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QNNPing.h; sourceTree = "<group>"; };
5655
DF2B76EB1C33702D00643678 /* QNNPing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QNNPing.m; sourceTree = "<group>"; };
5756
DF2B76ED1C33706900643678 /* QNNProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QNNProtocols.h; sourceTree = "<group>"; };
58-
DF2B76EF1C3B9DA100643678 /* QNNSimplePing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QNNSimplePing.h; sourceTree = "<group>"; };
59-
DF2B76F01C3B9DA100643678 /* QNNSimplePing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QNNSimplePing.m; sourceTree = "<group>"; };
6057
DF8DFFC31C60951D00174DA9 /* QNNNslookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QNNNslookup.h; sourceTree = "<group>"; };
6158
DF8DFFC41C60951D00174DA9 /* QNNNslookup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QNNNslookup.m; sourceTree = "<group>"; };
6259
DF8DFFCF1C61DA1B00174DA9 /* NetDiagTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NetDiagTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -166,8 +163,6 @@
166163
DF2B76EA1C33702D00643678 /* QNNPing.h */,
167164
DF2B76EB1C33702D00643678 /* QNNPing.m */,
168165
DF2B76ED1C33706900643678 /* QNNProtocols.h */,
169-
DF2B76EF1C3B9DA100643678 /* QNNSimplePing.h */,
170-
DF2B76F01C3B9DA100643678 /* QNNSimplePing.m */,
171166
DF9D41F81C57787500486F87 /* QNNTcpPing.h */,
172167
DF9D41F91C57787500486F87 /* QNNTcpPing.m */,
173168
DF9D41FB1C57789B00486F87 /* QNNUtil.h */,
@@ -340,7 +335,6 @@
340335
DF8DFFC51C60951D00174DA9 /* QNNNslookup.m in Sources */,
341336
DF2B76EC1C33702D00643678 /* QNNPing.m in Sources */,
342337
DF9D41FA1C57787500486F87 /* QNNTcpPing.m in Sources */,
343-
DF2B76F11C3B9DA100643678 /* QNNSimplePing.m in Sources */,
344338
DF9D42091C57BEFD00486F87 /* QNNExternalIp.m in Sources */,
345339
DF9D42001C5778B600486F87 /* QNNRtmp.m in Sources */,
346340
DF9D41FD1C57789B00486F87 /* QNNUtil.m in Sources */,

NetDiag/QNNPing.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
@interface QNNPingResult : NSObject
1313

1414
@property (readonly) NSInteger code;
15-
@property (readonly) NSInteger maxRtt;
16-
@property (readonly) NSInteger minRtt;
17-
@property (readonly) NSInteger avgRtt;
15+
@property (readonly) NSTimeInterval maxRtt;
16+
@property (readonly) NSTimeInterval minRtt;
17+
@property (readonly) NSTimeInterval avgRtt;
1818
@property (readonly) double lossRate;
1919
@property (readonly) NSInteger count;
2020
@property (readonly) NSInteger interval;

NetDiag/QNNPing.m

Lines changed: 181 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,112 @@
66
// Copyright © 2015年 Qiniu Cloud Storage. All rights reserved.
77
//
88

9+
#import <sys/socket.h>
10+
#import <netinet/in.h>
11+
#import <arpa/inet.h>
12+
#import <unistd.h>
13+
#import <netdb.h>
14+
15+
#import <netinet/tcp.h>
16+
#import <netinet/in.h>
17+
18+
#include <AssertMacros.h>
19+
920
#import "QNNPing.h"
1021

11-
typedef struct PingPacket{
22+
@interface QNNPingResult()
23+
24+
-(instancetype)init:(NSInteger)code
25+
max:(NSTimeInterval)maxRtt
26+
min:(NSTimeInterval)minRtt
27+
avg:(NSTimeInterval)avgRtt
28+
loss:(double)lossRate
29+
interval:(NSInteger)interval
30+
count:(NSInteger)count;
31+
@end
32+
33+
@implementation QNNPingResult
34+
35+
-(NSString*) description{
36+
if (_code == 0) {
37+
return [NSString stringWithFormat:@"ping %d times, min/avg/max = %f/%f/%fms loss %f", _count, _minRtt, _avgRtt, _maxRtt, _lossRate];
38+
}
39+
return [NSString stringWithFormat:@"ping failed %d", _code];
40+
}
41+
42+
-(instancetype)init:(NSInteger)code
43+
max:(NSTimeInterval)maxRtt
44+
min:(NSTimeInterval)minRtt
45+
avg:(NSTimeInterval)avgRtt
46+
loss:(double)lossRate
47+
interval:(NSInteger)interval
48+
count:(NSInteger)count{
49+
if (self = [super init]) {
50+
_code = code;
51+
_minRtt = minRtt;
52+
_avgRtt = avgRtt;
53+
_maxRtt = maxRtt;
54+
_lossRate = lossRate;
55+
_interval = interval;
56+
_count = count;
57+
}
58+
return self;
59+
}
60+
61+
@end
62+
63+
// IP header structure:
64+
65+
struct IPHeader {
66+
uint8_t versionAndHeaderLength;
67+
uint8_t differentiatedServices;
68+
uint16_t totalLength;
69+
uint16_t identification;
70+
uint16_t flagsAndFragmentOffset;
71+
uint8_t timeToLive;
72+
uint8_t protocol;
73+
uint16_t headerChecksum;
74+
uint8_t sourceAddress[4];
75+
uint8_t destinationAddress[4];
76+
// options...
77+
// data...
78+
};
79+
typedef struct IPHeader IPHeader;
80+
81+
check_compile_time(sizeof(IPHeader) == 20);
82+
check_compile_time(offsetof(IPHeader, versionAndHeaderLength) == 0);
83+
check_compile_time(offsetof(IPHeader, differentiatedServices) == 1);
84+
check_compile_time(offsetof(IPHeader, totalLength) == 2);
85+
check_compile_time(offsetof(IPHeader, identification) == 4);
86+
check_compile_time(offsetof(IPHeader, flagsAndFragmentOffset) == 6);
87+
check_compile_time(offsetof(IPHeader, timeToLive) == 8);
88+
check_compile_time(offsetof(IPHeader, protocol) == 9);
89+
check_compile_time(offsetof(IPHeader, headerChecksum) == 10);
90+
check_compile_time(offsetof(IPHeader, sourceAddress) == 12);
91+
check_compile_time(offsetof(IPHeader, destinationAddress) == 16);
92+
93+
typedef struct ICMPPacket{
1294
uint8_t type;
1395
uint8_t code;
1496
uint16_t checksum;
1597
uint16_t identifier;
1698
uint16_t sequenceNumber;
17-
uint8_t payload[1]; // data, variable length
18-
}PingPacket;
99+
uint8_t payload[0]; // data, variable length
100+
}ICMPPacket;
101+
102+
enum {
103+
kQNNICMPTypeEchoReply = 0, // code is always 0
104+
kQNNICMPTypeEchoRequest = 8 // code is always 0
105+
};
106+
107+
check_compile_time(sizeof(ICMPPacket) == 8);
108+
check_compile_time(offsetof(ICMPPacket, type) == 0);
109+
check_compile_time(offsetof(ICMPPacket, code) == 1);
110+
check_compile_time(offsetof(ICMPPacket, checksum) == 2);
111+
check_compile_time(offsetof(ICMPPacket, identifier) == 4);
112+
check_compile_time(offsetof(ICMPPacket, sequenceNumber) == 6);
113+
114+
const int kQNNPacketSize = sizeof(ICMPPacket) + 100;
19115

20116
static uint16_t in_cksum(const void *buffer, size_t bufferLen)
21117
// This is the standard BSD checksum code, modified to use modern types.
@@ -59,17 +155,95 @@ static uint16_t in_cksum(const void *buffer, size_t bufferLen)
59155
return answer;
60156
}
61157

62-
static PingPacket* build_packet(int seq){
63-
return NULL;
158+
static ICMPPacket* build_packet(uint16_t seq, uint16_t identifier){
159+
ICMPPacket* packet = (ICMPPacket*)calloc(kQNNPacketSize, 1);
160+
161+
packet->type = kQNNICMPTypeEchoRequest;
162+
packet->code = 0;
163+
packet->checksum = 0;
164+
packet->identifier = OSSwapHostToBigInt16(identifier);
165+
packet->sequenceNumber = OSSwapHostToBigInt16(seq);
166+
snprintf((char*)packet->payload, kQNNPacketSize - sizeof(ICMPPacket), "qiniu ping test %d", (int)seq);
167+
packet->checksum = in_cksum(packet, kQNNPacketSize);
168+
return packet;
64169
}
65170

66171
@interface QNNPing ()
172+
@property (readonly) NSString* host;
67173
@property (nonatomic, strong) id<QNNOutputDelegate> output;
68-
@property NSInteger sequenceNumber;
174+
@property (readonly) QNNPingCompleteHandler complete;
175+
176+
@property (readonly) NSInteger interval;
177+
@property (readonly) NSInteger count;
178+
@property (atomic) BOOL stopped;
69179
@end
70180

71181
@implementation QNNPing
72182

183+
-(NSInteger)sendPacket:(ICMPPacket*)packet
184+
sock:(int)sock
185+
target:(struct sockaddr *)addr{
186+
int sent = sendto(sock, packet, (size_t)kQNNPacketSize, 0, addr, (socklen_t)sizeof(struct sockaddr));
187+
if (sent < 0) {
188+
return errno;
189+
}
190+
return 0;
191+
}
192+
193+
-(void)run{
194+
struct sockaddr_in addr;
195+
memset(&addr, 0, sizeof(addr));
196+
addr.sin_len = sizeof(addr);
197+
addr.sin_family = AF_INET;
198+
addr.sin_addr.s_addr = inet_addr([_host UTF8String]);
199+
if (addr.sin_addr.s_addr == INADDR_NONE) {
200+
struct hostent *host = gethostbyname([_host UTF8String]);
201+
if (host == NULL || host->h_addr == NULL) {
202+
[self.output write:@"Problem accessing the DNS"];
203+
if (_complete != nil) {
204+
dispatch_async(dispatch_get_main_queue(), ^(void) {
205+
QNNPingResult* result = [[QNNPingResult alloc] init:-1006 max:0 min:0 avg:0 loss:0 interval:0 count:0];
206+
_complete(result);
207+
});
208+
}
209+
return;
210+
}
211+
addr.sin_addr = *(struct in_addr *)host->h_addr;
212+
[self.output write:[NSString stringWithFormat:@"ping to ip %s ...\n", inet_ntoa(addr.sin_addr)]];
213+
}
214+
215+
NSTimeInterval* durations = (NSTimeInterval*)malloc(sizeof(NSTimeInterval)*_count);
216+
NSInteger index = 0;
217+
int r = 0;
218+
do {
219+
NSDate* t1 = [NSDate date];
220+
r = [self connect:&addr];
221+
NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:t1];
222+
intervals[index] = duration;
223+
if (r == 0) {
224+
[self.output write:[NSString stringWithFormat:@"connected to %s:%d, %f ms\n", inet_ntoa(addr.sin_addr), _port, duration*1000]];
225+
}else{
226+
[self.output write:[NSString stringWithFormat:@"connect failed to %s:%d, %f ms, error %d\n", inet_ntoa(addr.sin_addr), _port, duration*1000, r]];
227+
}
228+
229+
if (index < _count && !_stopped && r == 0) {
230+
[NSThread sleepForTimeInterval:0.1];
231+
}
232+
} while (++index < _count && !_stopped && r == 0);
233+
234+
if (_complete) {
235+
NSInteger code = r;
236+
if(_stopped){
237+
code = kQNNRequestStoped;
238+
}
239+
dispatch_async(dispatch_get_main_queue(), ^(void) {
240+
QNNPingResult result =
241+
_complete([self buildResult:code durations:intervals count:index]);
242+
});
243+
}
244+
free(durations);
245+
}
246+
73247
+(instancetype) start:(NSString*)host
74248
output:(id<QNNOutputDelegate>)output
75249
complete:(QNNPingCompleteHandler)complete{
@@ -85,6 +259,7 @@ +(instancetype) start:(NSString*)host
85259
}
86260

87261
-(void)stop{
262+
_stopped = YES;
88263
return;
89264
}
90265

0 commit comments

Comments
 (0)