This commit is contained in:
世界 2020-04-24 20:10:35 +08:00
parent 3d973f3ef1
commit 1f6f647ad1
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
15 changed files with 381 additions and 55 deletions

View File

@ -9,7 +9,7 @@ jobs:
canaryBuild:
name: Canary Build
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[S]') && !contains(github.event.head_commit.message, '[RELEASE]') && !contains(github.event.head_commit.message, '[FOSS]')"
if: "!contains(github.event.head_commit.message, '[S]') && !contains(github.event.head_commit.message, '[RELEASE]') && !contains(github.event.head_commit.message, '[N]')"
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v1

View File

@ -9,7 +9,7 @@ jobs:
fossBuild:
name: Foss Build
runs-on: ubuntu-latest
if: "contains(github.event.head_commit.message, '[RELEASE]') || contains(github.event.head_commit.message, '[FOSS]')"
if: "contains(github.event.head_commit.message, '[RELEASE]') || contains(github.event.head_commit.message, '[N]')"
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v1

View File

@ -150,10 +150,10 @@ void bindRequestToGuid(JNIEnv *env, jclass c, jint instanceNum, jint requestToke
return ConnectionsManager::getInstance(instanceNum).bindRequestToGuid(requestToken, guid);
}
void applyDatacenterAddress(JNIEnv *env, jclass c, jint instanceNum, jint datacenterId, jstring ipAddress, jint port) {
void applyDatacenterAddress(JNIEnv *env, jclass c, jint instanceNum, jint datacenterId, jstring ipAddress, jint port,jint flag) {
const char *valueStr = env->GetStringUTFChars(ipAddress, 0);
ConnectionsManager::getInstance(instanceNum).applyDatacenterAddress((uint32_t) datacenterId, std::string(valueStr), (uint32_t) port);
ConnectionsManager::getInstance(instanceNum).applyDatacenterAddress((uint32_t) datacenterId, std::string(valueStr), (uint32_t) port,(uint32_t) flag);
if (valueStr != 0) {
env->ReleaseStringUTFChars(ipAddress, valueStr);
@ -427,7 +427,7 @@ static JNINativeMethod ConnectionsManagerMethods[] = {
{"native_cleanUp", "(IZ)V", (void *) cleanUp},
{"native_cancelRequestsForGuid", "(II)V", (void *) cancelRequestsForGuid},
{"native_bindRequestToGuid", "(III)V", (void *) bindRequestToGuid},
{"native_applyDatacenterAddress", "(IILjava/lang/String;I)V", (void *) applyDatacenterAddress},
{"native_applyDatacenterAddress", "(IILjava/lang/String;II)V", (void *) applyDatacenterAddress},
{"native_setProxySettings", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void *) setProxySettings},
{"native_getConnectionState", "(I)I", (void *) getConnectionState},
{"native_setUserId", "(II)V", (void *) setUserId},

View File

@ -3041,14 +3041,14 @@ void ConnectionsManager::authorizedOnMovingDatacenter() {
});
}
void ConnectionsManager::applyDatacenterAddress(uint32_t datacenterId, std::string ipAddress, uint32_t port) {
void ConnectionsManager::applyDatacenterAddress(uint32_t datacenterId, std::string ipAddress, uint32_t port,uint32_t flag) {
scheduleTask([&, datacenterId, ipAddress, port] {
Datacenter *datacenter = getDatacenterWithId(datacenterId);
if (datacenter != nullptr) {
std::vector<TcpAddress> addresses;
addresses.push_back(TcpAddress(ipAddress, port, 0, ""));
addresses.push_back(TcpAddress(ipAddress, port, flag, ""));
datacenter->suspendConnections(true);
datacenter->replaceAddresses(addresses, 0);
datacenter->replaceAddresses(addresses, flag);
datacenter->resetAddressAndPortNum();
saveConfig();
if (datacenter->isHandshakingAny()) {

View File

@ -54,7 +54,7 @@ public:
void cleanUp(bool resetKeys);
void cancelRequestsForGuid(int32_t guid);
void bindRequestToGuid(int32_t requestToken, int32_t guid);
void applyDatacenterAddress(uint32_t datacenterId, std::string ipAddress, uint32_t port);
void applyDatacenterAddress(uint32_t datacenterId, std::string ipAddress, uint32_t port,uint32_t flag);
void setDelegate(ConnectiosManagerDelegate *connectiosManagerDelegate);
ConnectionState getConnectionState();
void setUserId(int32_t userId);

View File

@ -434,6 +434,19 @@ void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
"PGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6MAQIDAQAB\n"
"-----END RSA PUBLIC KEY-----");
serverPublicKeysFingerprints.push_back(0x5a181b2235057d98LL);
serverPublicKeys.push_back("-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAvKLEOWTzt9Hn3/9Kdp/RdHcEhzmd8xXeLSpHIIzaXTLJDw8BhJy1\n"
"jR/iqeG8Je5yrtVabqMSkA6ltIpgylH///FojMsX1BHu4EPYOXQgB0qOi6kr08iX\n"
"ZIH9/iOPQOWDsL+Lt8gDG0xBy+sPe/2ZHdzKMjX6O9B4sOsxjFrk5qDoWDrioJor\n"
"AJ7eFAfPpOBf2w73ohXudSrJE0lbQ8pCWNpMY8cB9i8r+WBitcvouLDAvmtnTX7a\n"
"khoDzmKgpJBYliAY4qA73v7u5UIepE8QgV0jCOhxJCPubP8dg+/PlLLVKyxU5Cdi\n"
"QtZj2EMy4s9xlNKzX8XezE0MHEa6bQpnFwIDAQAB\n"
"-----END RSA PUBLIC KEY-----");
serverPublicKeysFingerprints.push_back(0xa9e071c1771060cdLL);
}
size_t count2 = serverPublicKeysFingerprints.size();
@ -441,7 +454,7 @@ void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
for (uint32_t b = 0; b < count2; b++) {
if ((uint64_t) result->server_public_key_fingerprints[a] == serverPublicKeysFingerprints[b]) {
keyFingerprint = result->server_public_key_fingerprints[a];
key = serverPublicKeys[a];
key = serverPublicKeys[b];
break;
}
}

Binary file not shown.

View File

@ -115,6 +115,7 @@ object Utils {
return (isIpv4Address(value) || isIpv6Address(value))
}
@JvmStatic
fun isIpv4Address(value: String): Boolean {
val regV4 = Regex("^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$")
return regV4.matches(value)

View File

@ -175,7 +175,7 @@ public class GcmPushListenerService extends FirebaseMessagingService {
}
String ip = parts[0];
int port = Integer.parseInt(parts[1]);
ConnectionsManager.getInstance(currentAccount).applyDatacenterAddress(dc, ip, port);
ConnectionsManager.getInstance(currentAccount).applyDatacenterAddress(dc, ip, port, 0);
ConnectionsManager.getInstance(currentAccount).resumeNetworkMaybe();
countDownLatch.countDown();
return;

View File

@ -52,6 +52,7 @@ import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import tw.nekomimi.nekogram.DataCenter;
import tw.nekomimi.nekogram.ExternalGcm;
import tw.nekomimi.nekogram.InternalFilters;
import tw.nekomimi.nekogram.NekoConfig;
@ -7951,7 +7952,9 @@ public class MessagesController extends BaseController implements NotificationCe
getMessagesStorage().cleanup(false);
cleanup();
getContactsController().deleteUnknownAppAccounts();
if (ConnectionsManager.native_isTestBackend(currentAccount) != 0) {
if (MessagesController.getMainSettings(currentAccount).getBoolean("custom_dc",false)) {
DataCenter.applyOfficalDataCanter(currentAccount);
} else if (ConnectionsManager.native_isTestBackend(currentAccount) != 0) {
ConnectionsManager.native_switchBackend(currentAccount);
}
}

View File

@ -310,8 +310,8 @@ public class ConnectionsManager extends BaseController {
native_bindRequestToGuid(currentAccount, requestToken, guid);
}
public void applyDatacenterAddress(int datacenterId, String ipAddress, int port) {
native_applyDatacenterAddress(currentAccount, datacenterId, ipAddress, port);
public void applyDatacenterAddress(int datacenterId, String ipAddress, int port, int flag) {
native_applyDatacenterAddress(currentAccount, datacenterId, ipAddress, port, flag);
}
public int getConnectionState() {
@ -326,7 +326,16 @@ public class ConnectionsManager extends BaseController {
}
public void checkConnection() {
native_setUseIpv6(currentAccount, useIpv6Address());
boolean useIpv6;
int networkType = MessagesController.getMainSettings(currentAccount).getInt("network",0);
if (networkType == 4) {
useIpv6 = false;
} else if (networkType == 6) {
useIpv6 = true;
} else {
useIpv6 = useIpv6Address();
}
native_setUseIpv6(currentAccount, useIpv6);
native_setNetworkAvailable(currentAccount, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), ApplicationLoader.isConnectionSlow());
}
@ -527,6 +536,11 @@ public class ConnectionsManager extends BaseController {
}
return;
}
if (MessagesController.getMainSettings(currentAccount).getBoolean("custom_dc",false)) {
return;
}
lastDnsRequestTime = System.currentTimeMillis();
if (BuildVars.LOGS_ENABLED) {
@ -648,7 +662,7 @@ public class ConnectionsManager extends BaseController {
public static native void native_bindRequestToGuid(int currentAccount, int requestToken, int guid);
public static native void native_applyDatacenterAddress(int currentAccount, int datacenterId, String ipAddress, int port);
public static native void native_applyDatacenterAddress(int currentAccount, int datacenterId, String ipAddress, int port, int flag);
public static native int native_getConnectionState(int currentAccount);
@ -694,7 +708,7 @@ public class ConnectionsManager extends BaseController {
@SuppressLint("NewApi")
public static boolean useIpv6Address() {
if (Build.VERSION.SDK_INT < 19 || !(SharedConfig.proxyEnabled && SharedConfig.currentProxy != null && !SharedConfig.currentProxy.secret.isEmpty())) {
if (Build.VERSION.SDK_INT < 19) {
return false;
}
if (BuildVars.LOGS_ENABLED) {

View File

@ -67,6 +67,8 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.v2ray.ang.util.Utils;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
@ -125,6 +127,7 @@ import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import kotlin.Unit;
import tw.nekomimi.nekogram.BottomBuilder;
import tw.nekomimi.nekogram.DataCenter;
import tw.nekomimi.nekogram.EditTextAutoFill;
import tw.nekomimi.nekogram.NekoXConfig;
@ -267,6 +270,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
private int menu_other = 5;
private int menu_custom_api = 6;
private int menu_custom_dc = 7;
@Override
public View createView(Context context) {
@ -425,7 +429,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
});
builder.addRadioItem(LocaleController.getString("CustomApiInput", R.string.CustomApiInput), NekoXConfig.customApi > 2, (cell) -> {
targetApi.set(3);
@ -527,6 +530,209 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
builder.show();
} else if (id == menu_custom_dc) {
AtomicInteger targetDc = new AtomicInteger(-1);
BottomBuilder builder = new BottomBuilder(getParentActivity());
EditText[] inputs = new EditText[3];
builder.addTitle("TEST TITLE",
true,
"TEST NOTICE");
int dcType;
if (MessagesController.getMainSettings(currentAccount).getBoolean("custom_dc", false)) {
dcType = 2;
} else if (ConnectionsManager.native_isTestBackend(currentAccount) != 0) {
dcType = 1;
} else {
dcType = 0;
}
builder.addRadioItem("OFFICAL", dcType == 0, (cell) -> {
targetDc.set(0);
builder.doRadioCheck(cell);
for (EditText input : inputs) input.setVisibility(View.GONE);
return Unit.INSTANCE;
});
builder.addRadioItem("TEST DC", dcType == 1, (cell) -> {
targetDc.set(1);
builder.doRadioCheck(cell);
for (EditText input : inputs) input.setVisibility(View.GONE);
return Unit.INSTANCE;
});
builder.addRadioItem(LocaleController.getString("CustomApiInput", R.string.CustomApiInput), dcType == 2, (cell) -> {
targetDc.set(2);
builder.doRadioCheck(cell);
for (EditText input : inputs) input.setVisibility(View.VISIBLE);
return Unit.INSTANCE;
});
inputs[0] = builder.addEditText("Ipv4 Address");
inputs[0].setFilters(new InputFilter[]{new InputFilter.LengthFilter(15)});
if (StrUtil.isNotBlank(NekoXConfig.customDcIpv4)) {
inputs[0].setText(NekoXConfig.customDcIpv4);
}
inputs[0].addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (StrUtil.isBlank(s) || Utils.isIpv4Address(s.toString())) {
inputs[0].setError(null);
NekoXConfig.customDcIpv4 = s.toString();
} else {
inputs[0].setError("Invalid Ipv4 Address");
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
inputs[1] = builder.addEditText("Ipv6 Address");
if (StrUtil.isNotBlank(NekoXConfig.customDcIpv6)) {
inputs[1].setText(NekoXConfig.customDcIpv6);
}
inputs[1].addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (StrUtil.isBlank(s) || Utils.isIpv6Address(s.toString())) {
inputs[1].setError(null);
NekoXConfig.customDcIpv6 = s.toString();
} else {
inputs[1].setError("Invalid Ipv6 Address");
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
inputs[2] = builder.addEditText("Port");
inputs[2].setInputType(InputType.TYPE_CLASS_NUMBER);
inputs[2].setText(NekoXConfig.customDcPort + "");
inputs[2].setFilters(new InputFilter[]{new InputFilter.LengthFilter(5)});
inputs[2].addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (StrUtil.isBlank(s.toString())) {
NekoXConfig.customDcPort = 12345;
} else {
NekoXConfig.customDcPort = NumberUtil.parseInt(s.toString());
if (NekoXConfig.customDcPort <= 0 || NekoXConfig.customDcPort > 65535) {
NekoXConfig.customDcPort = 12345;
inputs[2].setError("Invalid Port");
} else {
inputs[2].setError(null);
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
if (dcType < 2) {
for (EditText input : inputs) input.setVisibility(View.GONE);
}
builder.addCancelButton();
builder.addButton(LocaleController.getString("Set", R.string.Set), (it) -> {
int target = targetDc.get();
if (target >= 2) {
if (inputs[0].getError() != null) {
inputs[0].requestFocus();
AndroidUtilities.showKeyboard(inputs[0]);
return Unit.INSTANCE;
} else if (inputs[1].getError() != null) {
inputs[1].requestFocus();
AndroidUtilities.showKeyboard(inputs[1]);
return Unit.INSTANCE;
} else if (StrUtil.isBlank(NekoXConfig.customDcIpv4) && StrUtil.isBlank(NekoXConfig.customDcIpv6)) {
inputs[0].requestFocus();
AndroidUtilities.showKeyboard(inputs[0]);
return Unit.INSTANCE;
}
}
if (target == dcType) {
// do nothing
} else if (target == 0) {
DataCenter.applyOfficalDataCanter(currentAccount);
} else if (target == 1) {
DataCenter.applyTestDataCenter(currentAccount);
} else {
DataCenter.applyCustomDataCenter(currentAccount,NekoXConfig.customDcIpv4,NekoXConfig.customDcIpv6,NekoXConfig.customDcPort);
NekoXConfig.saveCustomDc();
}
builder.dismiss();
return Unit.INSTANCE;
});
builder.show();
}
}
@ -555,6 +761,12 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
otherItem.addSubItem(menu_custom_api, R.drawable.baseline_vpn_key_24, LocaleController.getString("CustomApi", R.string.CustomApi));
if(NekoXConfig.developerMode) {
otherItem.addSubItem(menu_custom_dc, R.drawable.baseline_sync_24, "Test Option");
}
actionBar.setAllowOverlayTitle(true);
doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
doneProgressView = new ContextProgressView(context, 1);
@ -1481,7 +1693,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
private TextView textView2;
private CheckBoxCell checkBoxCell;
private CheckBoxCell allowFlashCallCell;
private CheckBoxCell testBackendCell;
private int countryState = 0;
@ -1818,41 +2029,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
cell.setChecked(allowFlashCall = !allowFlashCall, true);
});
if (NekoXConfig.developerMode) {
testBackendCell = new CheckBoxCell(context, 2);
testBackendCell.setText(LocaleController.getString("TestBackend", R.string.TestBackend), "", ConnectionsManager.native_isTestBackend(currentAccount) != 0, false);
addView(testBackendCell, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
testBackendCell.setOnClickListener(new OnClickListener() {
private Toast visibleToast;
@Override
public void onClick(View v) {
if (getParentActivity() == null) {
return;
}
CheckBoxCell cell = (CheckBoxCell) v;
ConnectionsManager.native_switchBackend(currentAccount);
boolean isTestBackend = ConnectionsManager.native_isTestBackend(currentAccount) != 0;
cell.setChecked(isTestBackend, true);
try {
if (visibleToast != null) {
visibleToast.cancel();
}
} catch (Exception e) {
FileLog.e(e);
}
if (isTestBackend) {
visibleToast = Toast.makeText(getParentActivity(), LocaleController.getString("TestBackendOn", R.string.TestBackendOn), Toast.LENGTH_SHORT);
visibleToast.show();
} else {
visibleToast = Toast.makeText(getParentActivity(), LocaleController.getString("TestBackendOff", R.string.TestBackendOff), Toast.LENGTH_SHORT);
visibleToast.show();
}
}
});
}
HashMap<String, String> languageMap = new HashMap<>();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().getAssets().open("countries.txt")));

View File

@ -0,0 +1,99 @@
package tw.nekomimi.nekogram
import com.v2ray.ang.util.Utils
import org.telegram.messenger.MessagesController
import org.telegram.tgnet.ConnectionsManager
object DataCenter {
@JvmStatic
fun applyOfficalDataCanter(account: Int) {
MessagesController.getMainSettings(account).edit().putInt("network", 0).apply()
MessagesController.getMainSettings(account).edit().putBoolean("custom_dc", false).apply()
if (ConnectionsManager.native_isTestBackend(account) != 0) {
ConnectionsManager.getInstance(account).switchBackend()
}
applyDataCanter(account, 1, "149.154.175.50")
applyDataCanter(account, 1, "2001:b28:f23d:f001:0000:0000:0000:000a")
applyDataCanter(account, 2, "149.154.167.51")
applyDataCanter(account, 2, "2001:67c:4e8:f002:0000:0000:0000:000a")
applyDataCanter(account, 3, "149.154.175.100")
applyDataCanter(account, 3, "2001:b28:f23d:f003:0000:0000:0000:000a")
applyDataCanter(account, 4, "149.154.167.91")
applyDataCanter(account, 4, "2001:67c:4e8:f004:0000:0000:0000:000a")
applyDataCanter(account, 5, "149.154.171.5")
applyDataCanter(account, 5, "2001:67c:4e8:f005:0000:0000:0000:000a")
}
@JvmStatic
fun applyTestDataCenter(account: Int) {
MessagesController.getMainSettings(account).edit().putInt("network", 0).apply()
MessagesController.getMainSettings(account).edit().putBoolean("custom_dc", false).apply()
if (ConnectionsManager.native_isTestBackend(account) == 0) {
ConnectionsManager.getInstance(account).switchBackend()
}
}
@JvmStatic
fun applyCustomDataCenter(account: Int, ipv4Address: String = "", ipv6Address: String = "", port: Int) {
MessagesController.getMainSettings(account).edit().putBoolean("custom_dc", true).apply()
if (ConnectionsManager.native_isTestBackend(account) != 0) {
ConnectionsManager.getInstance(account).switchBackend()
}
var networkType = 0
if (ipv4Address.isNotBlank()) {
for (dc in 1..5) applyDataCanter(account, dc, ipv4Address, port)
if (ipv6Address.isBlank()) {
networkType = 4
}
}
if (ipv6Address.isNotBlank()) {
for (dc in 1..5) applyDataCanter(account, dc, ipv6Address, port)
if (ipv4Address.isBlank()) {
networkType = 6
}
}
MessagesController.getMainSettings(account).edit().putInt("network", networkType).apply()
}
private fun applyDataCanter(account: Int, dataCenter: Int, address: String, port: Int = 443) {
ConnectionsManager.getInstance(account).applyDatacenterAddress(dataCenter, address, port, if (Utils.isIpv6Address(address)) 1 else 0)
}
}

View File

@ -574,7 +574,13 @@ public class NekoSettingsActivity extends BaseFragment {
rowCount = 0;
connectionRow = rowCount++;
ipv6Row = rowCount++;
if (MessagesController.getMainSettings(currentAccount).getInt("network", 0) == 0) {
ipv6Row = rowCount++;
}
disableProxyWhenVpnEnabledRow = rowCount++;
connection2Row = rowCount++;

View File

@ -85,4 +85,18 @@ public class NekoXConfig {
}
public static String customDcIpv4 = preferences.getString("custom_dc_v4", "");
public static String customDcIpv6 = preferences.getString("custom_dc_v6", "");
public static int customDcPort = preferences.getInt("custom_dc_port", 12345);
public static void saveCustomDc() {
preferences.edit()
.putString("custom_dc_v4", customDcIpv4)
.putString("custom_dc_v6", customDcIpv6)
.putInt("custom_dc_port",customDcPort)
.apply();
}
}