mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Refactor OpenVPNPacketFlowAdapter
This commit is contained in:
@@ -35,10 +35,8 @@
|
|||||||
return CFSocketGetNative(_openVPNClientSocket);
|
return CFSocketGetNative(_openVPNClientSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
|
static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *adapter) {
|
||||||
if (type == kCFSocketDataCallBack) {
|
[(__bridge OpenVPNPacketFlowAdapter *)adapter writeDataToPacketFlow:(__bridge NSData *)data];
|
||||||
[(__bridge OpenVPNPacketFlowAdapter *)info writeDataToPacketFlow:(__bridge NSData *)data];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)configureSockets {
|
- (BOOL)configureSockets {
|
||||||
@@ -53,12 +51,12 @@ static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBack
|
|||||||
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack, PacketFlowSocketCallback, &socketCtxt);
|
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack, PacketFlowSocketCallback, &socketCtxt);
|
||||||
_openVPNClientSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
|
_openVPNClientSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
|
||||||
|
|
||||||
if (!_packetFlowSocket || !_openVPNClientSocket) {
|
if (!(_packetFlowSocket && _openVPNClientSocket)) {
|
||||||
NSLog(@"Failed to create core foundation sockets from native sockets");
|
NSLog(@"Failed to create core foundation sockets from native sockets");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (![self configureOptionsForSocket:_packetFlowSocket] || ![self configureOptionsForSocket:_openVPNClientSocket]) {
|
if (!([self configureOptionsForSocket:_packetFlowSocket] && [self configureOptionsForSocket:_openVPNClientSocket])) {
|
||||||
NSLog(@"Failed to configure buffer size of the sockets");
|
NSLog(@"Failed to configure buffer size of the sockets");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@@ -88,7 +86,7 @@ static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBack
|
|||||||
|
|
||||||
CFOptionFlags sockopt = CFSocketGetSocketFlags(socket);
|
CFOptionFlags sockopt = CFSocketGetSocketFlags(socket);
|
||||||
|
|
||||||
sockopt |= kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack;
|
sockopt |= kCFSocketCloseOnInvalidate;
|
||||||
CFSocketSetSocketFlags(socket, sockopt);
|
CFSocketSetSocketFlags(socket, sockopt);
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@@ -96,71 +94,72 @@ static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBack
|
|||||||
|
|
||||||
- (void)readPacketFlowPackets {
|
- (void)readPacketFlowPackets {
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
[self.packetFlow readPacketsWithCompletionHandler:^(NSArray<NSData *> * _Nonnull packets, NSArray<NSNumber *> * _Nonnull protocols) {
|
[self.packetFlow readPacketObjectsWithCompletionHandler:^(NSArray<NEPacket *> * _Nonnull packets) {
|
||||||
typeof(self) strongSelf = weakSelf;
|
typeof(self) strongSelf = weakSelf;
|
||||||
[strongSelf writeVPNPackets:packets protocols:protocols];
|
[strongSelf writeVPNPacketObjects:packets];
|
||||||
[strongSelf readPacketFlowPackets];
|
[strongSelf readPacketFlowPackets];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)writeVPNPackets:(NSArray<NSData *> *)packets protocols:(NSArray<NSNumber *> *)protocols {
|
- (void)writeVPNPacketObjects:(NSArray<NEPacket *> *)packets {
|
||||||
[packets enumerateObjectsUsingBlock:^(NSData *data, NSUInteger idx, BOOL *stop) {
|
for (NEPacket *packet in packets) {
|
||||||
// Prepare data for sending
|
CFSocketSendData(_packetFlowSocket, NULL, (CFDataRef)[self dataFromPacket:packet], 0.05);
|
||||||
NSData *packet = [self prepareVPNPacket:data protocol:protocols[idx]];
|
}
|
||||||
|
|
||||||
// Send data to the VPN server
|
|
||||||
CFSocketSendData(_packetFlowSocket, NULL, (CFDataRef)packet, 0.05);
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)prepareVPNPacket:(NSData *)packet protocol:(NSNumber *)protocol {
|
- (NSData *)dataFromPacket:(NEPacket *)packet {
|
||||||
NSMutableData *data = [NSMutableData new];
|
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network protocol.
|
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network protocol.
|
||||||
uint32_t prefix = CFSwapInt32HostToBig((uint32_t)[protocol unsignedIntegerValue]);
|
uint32_t prefix = CFSwapInt32HostToBig((uint32_t)packet.protocolFamily);
|
||||||
|
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeof(prefix) + packet.data.length];
|
||||||
[data appendBytes:&prefix length:sizeof(prefix)];
|
[data appendBytes:&prefix length:sizeof(prefix)];
|
||||||
|
[data appendData:packet.data];
|
||||||
|
return data;
|
||||||
|
#else
|
||||||
|
return packet.data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[data appendData:packet];
|
|
||||||
|
|
||||||
return [data copy];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)writeDataToPacketFlow:(NSData *)packet {
|
- (NEPacket *)packetFromData:(NSData *)data {
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
// Get network protocol from prefix
|
// Get network protocol from prefix
|
||||||
NSUInteger prefixSize = sizeof(uint32_t);
|
NSUInteger prefixSize = sizeof(uint32_t);
|
||||||
|
|
||||||
if (packet.length < prefixSize) {
|
if (data.length < prefixSize) {
|
||||||
NSLog(@"Incorrect OpenVPN packet size");
|
return nil;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t protocol = PF_UNSPEC;
|
uint32_t protocol = PF_UNSPEC;
|
||||||
[packet getBytes:&protocol length:prefixSize];
|
[data getBytes:&protocol length:prefixSize];
|
||||||
protocol = CFSwapInt32BigToHost(protocol);
|
protocol = CFSwapInt32BigToHost(protocol);
|
||||||
|
|
||||||
NSRange range = NSMakeRange(prefixSize, packet.length - prefixSize);
|
NSRange range = NSMakeRange(prefixSize, data.length - prefixSize);
|
||||||
NSData *data = [packet subdataWithRange:range];
|
NSData *packetData = [data subdataWithRange:range];
|
||||||
#else
|
#else
|
||||||
// Get network protocol from header
|
// Get network protocol from header
|
||||||
uint8_t header = 0;
|
uint8_t header = 0;
|
||||||
[packet getBytes:&header length:1];
|
[data getBytes:&header length:1];
|
||||||
|
|
||||||
uint32_t version = openvpn::IPHeader::version(header);
|
uint32_t version = openvpn::IPHeader::version(header);
|
||||||
uint8_t protocol = [self protocolFamilyForVersion:version];
|
sa_family_t protocol = [self protocolFamilyForVersion:version];
|
||||||
|
|
||||||
NSData *data = packet;
|
NSData *packetData = data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Send the packet to the TUN interface
|
return [[NEPacket alloc] initWithData:packetData protocolFamily:protocol];
|
||||||
if (![self.packetFlow writePackets:@[data] withProtocols:@[@(protocol)]]) {
|
|
||||||
NSLog(@"Failed to send OpenVPN packet to the TUN interface");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (uint8_t)protocolFamilyForVersion:(uint32_t)version {
|
- (void)writeDataToPacketFlow:(NSData *)data {
|
||||||
|
NEPacket *packet = [self packetFromData:data];
|
||||||
|
|
||||||
|
if (!packet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.packetFlow writePacketObjects:@[packet]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (sa_family_t)protocolFamilyForVersion:(uint32_t)version {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 4: return PF_INET;
|
case 4: return PF_INET;
|
||||||
case 6: return PF_INET6;
|
case 6: return PF_INET6;
|
||||||
|
|||||||
Reference in New Issue
Block a user