2018-05-02 17:29:58 +02:00
|
|
|
/*
|
|
|
|
* Copyright © 2018 Samuel Holland <samuel@sholland.org>
|
2018-05-02 21:40:01 +02:00
|
|
|
* Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
2018-07-06 04:09:48 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2018-05-02 17:29:58 +02:00
|
|
|
*/
|
|
|
|
|
2017-07-29 13:08:54 +02:00
|
|
|
package com.wireguard.config;
|
|
|
|
|
2017-08-01 04:13:01 +02:00
|
|
|
import android.databinding.BaseObservable;
|
2018-04-28 04:45:17 +02:00
|
|
|
import android.databinding.Bindable;
|
2017-07-30 00:30:33 +02:00
|
|
|
import android.databinding.ObservableArrayList;
|
|
|
|
import android.databinding.ObservableList;
|
2017-08-24 06:47:44 +02:00
|
|
|
import android.os.Parcel;
|
|
|
|
import android.os.Parcelable;
|
2017-08-01 04:13:01 +02:00
|
|
|
|
2018-04-30 18:39:12 +02:00
|
|
|
import com.android.databinding.library.baseAdapters.BR;
|
|
|
|
|
2017-07-29 13:08:54 +02:00
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
2017-07-30 00:30:33 +02:00
|
|
|
import java.nio.charset.StandardCharsets;
|
2018-04-28 04:45:17 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2017-07-29 13:08:54 +02:00
|
|
|
|
|
|
|
/**
|
2017-08-13 14:24:03 +02:00
|
|
|
* Represents a wg-quick configuration file, its name, and its connection state.
|
2017-07-29 13:08:54 +02:00
|
|
|
*/
|
|
|
|
|
2018-04-30 05:00:51 +02:00
|
|
|
public class Config {
|
|
|
|
private final Interface interfaceSection = new Interface();
|
|
|
|
private List<Peer> peers = new ArrayList<>();
|
|
|
|
|
2018-04-28 18:35:12 +02:00
|
|
|
public static Config from(final InputStream stream) throws IOException {
|
|
|
|
return from(new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Config from(final BufferedReader reader) throws IOException {
|
2018-01-01 09:06:37 +01:00
|
|
|
final Config config = new Config();
|
2018-04-28 18:35:12 +02:00
|
|
|
Peer currentPeer = null;
|
|
|
|
String line;
|
|
|
|
boolean inInterfaceSection = false;
|
|
|
|
while ((line = reader.readLine()) != null) {
|
2018-05-03 15:41:44 +02:00
|
|
|
final int commentIndex = line.indexOf('#');
|
|
|
|
if (commentIndex != -1)
|
|
|
|
line = line.substring(0, commentIndex);
|
|
|
|
line = line.trim();
|
|
|
|
if (line.isEmpty())
|
2018-04-28 18:35:12 +02:00
|
|
|
continue;
|
2018-05-03 15:41:44 +02:00
|
|
|
if ("[Interface]".toLowerCase().equals(line.toLowerCase())) {
|
2018-04-28 18:35:12 +02:00
|
|
|
currentPeer = null;
|
|
|
|
inInterfaceSection = true;
|
2018-05-03 15:41:44 +02:00
|
|
|
} else if ("[Peer]".toLowerCase().equals(line.toLowerCase())) {
|
2018-04-28 18:35:12 +02:00
|
|
|
currentPeer = new Peer();
|
|
|
|
config.peers.add(currentPeer);
|
|
|
|
inInterfaceSection = false;
|
|
|
|
} else if (inInterfaceSection) {
|
|
|
|
config.interfaceSection.parse(line);
|
|
|
|
} else if (currentPeer != null) {
|
|
|
|
currentPeer.parse(line);
|
|
|
|
} else {
|
|
|
|
throw new IllegalArgumentException("Invalid configuration line: " + line);
|
2017-11-26 23:45:41 +01:00
|
|
|
}
|
2017-07-30 00:30:33 +02:00
|
|
|
}
|
2018-04-28 18:35:12 +02:00
|
|
|
if (!inInterfaceSection && currentPeer == null) {
|
|
|
|
throw new IllegalArgumentException("Could not find any config information");
|
|
|
|
}
|
2018-01-01 09:06:37 +01:00
|
|
|
return config;
|
2017-07-29 13:08:54 +02:00
|
|
|
}
|
|
|
|
|
2018-01-01 09:06:37 +01:00
|
|
|
public Interface getInterface() {
|
|
|
|
return interfaceSection;
|
2017-08-16 11:26:45 +02:00
|
|
|
}
|
|
|
|
|
2018-04-28 04:45:17 +02:00
|
|
|
public List<Peer> getPeers() {
|
2018-01-01 09:06:37 +01:00
|
|
|
return peers;
|
2017-08-08 12:54:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-29 13:08:54 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
2018-01-01 09:06:37 +01:00
|
|
|
final StringBuilder sb = new StringBuilder().append(interfaceSection);
|
2017-08-13 14:24:03 +02:00
|
|
|
for (final Peer peer : peers)
|
|
|
|
sb.append('\n').append(peer);
|
2017-07-30 00:30:33 +02:00
|
|
|
return sb.toString();
|
2017-07-29 13:08:54 +02:00
|
|
|
}
|
2018-04-30 18:39:12 +02:00
|
|
|
|
|
|
|
public static class Observable extends BaseObservable implements Parcelable {
|
|
|
|
public static final Creator<Observable> CREATOR = new Creator<Observable>() {
|
|
|
|
@Override
|
|
|
|
public Observable createFromParcel(final Parcel in) {
|
|
|
|
return new Observable(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Observable[] newArray(final int size) {
|
|
|
|
return new Observable[size];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
private String name;
|
|
|
|
private Interface.Observable observableInterface;
|
|
|
|
private ObservableList<Peer.Observable> observablePeers;
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
public Observable(final Config parent, final String name) {
|
2018-04-30 18:39:12 +02:00
|
|
|
this.name = name;
|
|
|
|
loadData(parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Observable(final Parcel in) {
|
|
|
|
name = in.readString();
|
|
|
|
observableInterface = in.readParcelable(Interface.Observable.class.getClassLoader());
|
|
|
|
observablePeers = new ObservableArrayList<>();
|
|
|
|
in.readTypedList(observablePeers, Peer.Observable.CREATOR);
|
|
|
|
}
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
public void commitData(final Config parent) {
|
|
|
|
observableInterface.commitData(parent.interfaceSection);
|
|
|
|
final List<Peer> newPeers = new ArrayList<>(observablePeers.size());
|
|
|
|
for (final Peer.Observable observablePeer : observablePeers) {
|
|
|
|
final Peer peer = new Peer();
|
2018-04-30 18:39:12 +02:00
|
|
|
observablePeer.commitData(peer);
|
|
|
|
newPeers.add(peer);
|
|
|
|
}
|
|
|
|
parent.peers = newPeers;
|
|
|
|
notifyChange();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Bindable
|
|
|
|
public Interface.Observable getInterfaceSection() {
|
|
|
|
return observableInterface;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Bindable
|
|
|
|
public String getName() {
|
|
|
|
return name == null ? "" : name;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Bindable
|
|
|
|
public ObservableList<Peer.Observable> getPeers() {
|
|
|
|
return observablePeers;
|
|
|
|
}
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
protected void loadData(final Config parent) {
|
|
|
|
observableInterface = new Interface.Observable(parent == null ? null : parent.interfaceSection);
|
|
|
|
observablePeers = new ObservableArrayList<>();
|
2018-04-30 18:39:12 +02:00
|
|
|
if (parent != null) {
|
2018-04-30 18:37:52 +02:00
|
|
|
for (final Peer peer : parent.getPeers())
|
|
|
|
observablePeers.add(new Peer.Observable(peer));
|
2018-04-30 18:39:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
public void setName(final String name) {
|
2018-04-30 18:39:12 +02:00
|
|
|
this.name = name;
|
|
|
|
notifyPropertyChanged(BR.name);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void writeToParcel(final Parcel dest, final int flags) {
|
|
|
|
dest.writeString(name);
|
|
|
|
dest.writeParcelable(observableInterface, flags);
|
|
|
|
dest.writeTypedList(observablePeers);
|
|
|
|
}
|
|
|
|
}
|
2017-07-29 13:08:54 +02:00
|
|
|
}
|