Skip to content

Commit 8d50d03

Browse files
committed
✨ feat: 支持字符串形式的 .ovpn 配置
1 parent f8a98fc commit 8d50d03

File tree

5 files changed

+58
-27
lines changed

5 files changed

+58
-27
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export default App;
144144
```ts
145145
interface VpnOptions {
146146
remoteAddress?: string;
147+
ovpnString?: string;
147148
ovpnFileName?: string;
148149
assetsPath?: string;
149150
providerBundleIdentifier: string;
@@ -155,6 +156,12 @@ interface VpnOptions {
155156

156157
VPN server address, the format is `<ip> <port>`, use the address in the configuration file of `xxx.ovpn` when it is not passed in
157158

159+
#### ovpnString
160+
161+
The string format of the content of the OpenVPN configuration file. When it is not passed in or an empty string `''` is passed, the module will look for the `xxx.ovpn` configuration file string format
162+
163+
String format reference [example.ovpn](example/android/app/src/main/assets/Japan.ovpn)
164+
158165
#### ovpnFileName
159166

160167
The name of the OpenVPN configuration file, without extensions, using the default name `client` if not passed in
@@ -188,7 +195,7 @@ interface VpnEventParams {
188195

189196
### `xxx.ovpn` configuration file
190197

191-
Don't forget to add the configuration file to your project
198+
If you don’t use [ovpnString](#ovpnstring), don’t forget to add the configuration file to your project
192199

193200
- The Android path is `android/app/src/main/assets/`,create a new `assets` folder if you don't have one
194201
- The iOS path is the main bundle, just drag and drop the file into the project
@@ -227,7 +234,7 @@ The following items were used in this project
227234

228235
## License
229236

230-
react-native-simple-openvpn is available under the GPLv2 license. See the [LICENSE](LICENSE) file for more information
237+
[GPLv2](LICENSE) © Nor Cod
231238

232239
<!-- badge url -->
233240

README.zh-CN.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export default App;
144144
```ts
145145
interface VpnOptions {
146146
remoteAddress?: string;
147+
ovpnString?: string;
147148
ovpnFileName?: string;
148149
assetsPath?: string;
149150
providerBundleIdentifier: string;
@@ -155,6 +156,12 @@ interface VpnOptions {
155156

156157
VPN 服务端地址,格式为 `<ip> <port>`,未传入时使用 `xxx.ovpn` 配置文件中的地址
157158

159+
#### ovpnString
160+
161+
OpenVPN 配置文件内容的字符串形式,未传入时或传递空字符串 `''`,模块将寻找 `xxx.ovpn` 配置文件
162+
163+
字符串格式参考 [example.ovpn](example/android/app/src/main/assets/Japan.ovpn)
164+
158165
#### ovpnFileName
159166

160167
OpenVPN 配置文件的名称,不含扩展名,未传入时使用默认名称 `client`
@@ -188,7 +195,7 @@ interface VpnEventParams {
188195

189196
### `xxx.ovpn` 配置文件
190197

191-
不要忘记将配置文件添加你的项目中
198+
如果你不使用 [ovpnString](#ovpnstring)不要忘记将配置文件添加你的项目中
192199

193200
- Android 路径 `android/app/src/main/assets/`,没有 `assets` 文件夹就新建一个
194201
- iOS 路径为 main bundle,将文件拖拽到工程下即可
@@ -222,7 +229,7 @@ remote <IP address> <port>
222229

223230
## License
224231

225-
react-native-simple-openvpn 是在 GPLv2 许可证下提供的。参见 [LICENSE](LICENSE) 文件以了解更多信息
232+
[GPLv2](LICENSE) © Nor Cod
226233

227234
<!-- badge url -->
228235

android/src/main/java/com/norcod/rnovpn/RNSimpleOpenvpnModule.java

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,22 +164,9 @@ private void startVpn(Promise promise) {
164164

165165
try {
166166
String remoteAddress = ovpnOptions.getOrDefault("remoteAddress", "").toString();
167-
String assetsPath = ovpnOptions.getOrDefault("assetsPath", "").toString();
168-
String ovpnFileName = ovpnOptions.getOrDefault("ovpnFileName", "client").toString();
169-
String ovpnFilePath = assetsPath + ovpnFileName + ".ovpn";
170-
171-
InputStream conf = reactContext.getAssets().open(ovpnFilePath);
172-
InputStreamReader isr = new InputStreamReader(conf);
173-
BufferedReader br = new BufferedReader(isr);
174-
String line;
175-
176-
while (true) {
177-
line = br.readLine();
178-
if (line == null) {
179-
break;
180-
}
181-
config += line + "\n";
182-
}
167+
String ovpnString = ovpnOptions.getOrDefault("ovpnString", "").toString();
168+
169+
config = ovpnString.isEmpty() ? getOvpnFileContent() : ovpnString;
183170

184171
if (config.isEmpty()) {
185172
throw new Exception("ovpn config is empty");
@@ -215,6 +202,28 @@ private void startVpn(Promise promise) {
215202
promise = null;
216203
}
217204

205+
private String getOvpnFileContent() throws Exception {
206+
String content = "";
207+
String assetsPath = ovpnOptions.getOrDefault("assetsPath", "").toString();
208+
String ovpnFileName = ovpnOptions.getOrDefault("ovpnFileName", "client").toString();
209+
String ovpnFilePath = assetsPath + ovpnFileName + ".ovpn";
210+
211+
InputStream conf = reactContext.getAssets().open(ovpnFilePath);
212+
InputStreamReader isr = new InputStreamReader(conf);
213+
BufferedReader br = new BufferedReader(isr);
214+
String line;
215+
216+
while (true) {
217+
line = br.readLine();
218+
if (line == null) {
219+
break;
220+
}
221+
content += line + "\n";
222+
}
223+
224+
return content;
225+
}
226+
218227
private String getModifiedOvpnConfig(String ovpnConfig, String remoteAddress) {
219228
final String regex =
220229
"^remote\\s(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\s((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$";

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
interface VpnOptions {
2121
remoteAddress?: string;
22+
ovpnString?: string;
2223
ovpnFileName?: string;
2324
assetsPath?: string;
2425
providerBundleIdentifier: string;

ios/RNSimpleOpenvpn.m

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ - (void)prepareVpn:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlo
8181
}
8282

8383
- (void)startVpn:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
84-
NSString *const ovpnFileName = self.ovpnOptions[@"ovpnFileName"] ? self.ovpnOptions[@"ovpnFileName"] : @"client";
8584
NSString *const providerBundleIdentifier = self.ovpnOptions[@"providerBundleIdentifier"];
8685
NSString *const localizedDescription =
8786
self.ovpnOptions[@"localizedDescription"] ? self.ovpnOptions[@"localizedDescription"] : RN_OPEN_VPN;
@@ -91,14 +90,22 @@ - (void)startVpn:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock
9190
return;
9291
}
9392

94-
NSURL *url = [[NSBundle mainBundle] URLForResource:ovpnFileName withExtension:@"ovpn"];
93+
NSString *const ovpnString = self.ovpnOptions[@"ovpnString"] ? self.ovpnOptions[@"ovpnString"] : @"";
94+
NSData *data;
9595

96-
if (url == nil) {
97-
reject(@"E_NO_OVPN_FILE_ERROR", @"There are no ovpn file", nil);
98-
return;
99-
}
96+
if ([ovpnString length] != 0) {
97+
data = [ovpnString dataUsingEncoding:NSUTF8StringEncoding];
98+
} else {
99+
NSString *const ovpnFileName = self.ovpnOptions[@"ovpnFileName"] ? self.ovpnOptions[@"ovpnFileName"] : @"client";
100+
NSURL *url = [[NSBundle mainBundle] URLForResource:ovpnFileName withExtension:@"ovpn"];
101+
102+
if (url == nil) {
103+
reject(@"E_NO_OVPN_FILE_ERROR", @"There are no ovpn file", nil);
104+
return;
105+
}
100106

101-
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
107+
data = [[NSData alloc] initWithContentsOfURL:url];
108+
}
102109

103110
NETunnelProviderProtocol *tunel = [NETunnelProviderProtocol new];
104111
tunel.providerConfiguration = @{@"ovpn" : data};

0 commit comments

Comments
 (0)