mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-01-07 08:28:28 +01:00
Implement GetCurrentIpConfigInfo
Needed for almost every LAN game
This commit is contained in:
parent
635f06bf50
commit
54041ceba1
@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<uses-feature
|
||||
|
@ -64,7 +64,8 @@ namespace skyline {
|
||||
closeKeyboardId{environ->GetMethodID(instanceClass, "closeKeyboard", "(Lemu/skyline/applet/swkbd/SoftwareKeyboardDialog;)V")},
|
||||
showValidationResultId{environ->GetMethodID(instanceClass, "showValidationResult", "(Lemu/skyline/applet/swkbd/SoftwareKeyboardDialog;ILjava/lang/String;)I")},
|
||||
getVersionCodeId{environ->GetMethodID(instanceClass, "getVersionCode", "()I")},
|
||||
getIntegerValueId{environ->GetMethodID(environ->FindClass("java/lang/Integer"), "intValue", "()I")} {
|
||||
getIntegerValueId{environ->GetMethodID(environ->FindClass("java/lang/Integer"), "intValue", "()I")},
|
||||
getDhcpInfoId{environ->GetMethodID(instanceClass, "getDhcpInfo", "()Landroid/net/DhcpInfo;")} {
|
||||
env.Initialize(environ);
|
||||
}
|
||||
|
||||
@ -132,6 +133,23 @@ namespace skyline {
|
||||
return {static_cast<KeyboardCloseResult>(env->CallIntMethod(buttonInteger, getIntegerValueId)), input};
|
||||
}
|
||||
|
||||
DhcpInfo JvmManager::GetDhcpInfo() {
|
||||
jobject dhcpInfo{env->CallObjectMethod(instance, getDhcpInfoId)};
|
||||
jclass dhcpInfoClass{env->GetObjectClass(dhcpInfo)};
|
||||
jfieldID ipAddressFieldId{env->GetFieldID(dhcpInfoClass, "ipAddress", "I")};
|
||||
jfieldID subnetFieldId{env->GetFieldID(dhcpInfoClass, "netmask", "I")};
|
||||
jfieldID gatewayFieldId{env->GetFieldID(dhcpInfoClass, "gateway", "I")};
|
||||
jfieldID dns1FieldId{env->GetFieldID(dhcpInfoClass, "dns1", "I")};
|
||||
jfieldID dns2FieldId{env->GetFieldID(dhcpInfoClass, "dns2", "I")};
|
||||
|
||||
jint ipAddress{env->GetIntField(dhcpInfo, ipAddressFieldId)};
|
||||
jint subnet{env->GetIntField(dhcpInfo, subnetFieldId)};
|
||||
jint gateway{env->GetIntField(dhcpInfo, gatewayFieldId)};
|
||||
jint dns1{env->GetIntField(dhcpInfo, dns1FieldId)};
|
||||
jint dns2{env->GetIntField(dhcpInfo, dns2FieldId)};
|
||||
return DhcpInfo{ipAddress, subnet, gateway, dns1, dns2};
|
||||
}
|
||||
|
||||
void JvmManager::CloseKeyboard(jobject dialog) {
|
||||
env->CallVoidMethod(instance, closeKeyboardId, dialog);
|
||||
env->DeleteGlobalRef(dialog);
|
||||
|
@ -7,6 +7,14 @@
|
||||
#include <jni.h>
|
||||
|
||||
namespace skyline {
|
||||
struct DhcpInfo {
|
||||
i32 ipAddress;
|
||||
i32 subnet;
|
||||
i32 gateway;
|
||||
i32 dns1;
|
||||
i32 dns2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper over std::string that supports construction using a JNI jstring
|
||||
*/
|
||||
@ -182,6 +190,11 @@ namespace skyline {
|
||||
*/
|
||||
i32 GetVersionCode();
|
||||
|
||||
/**
|
||||
* @brief A call to EmulationActivity.getDhcpInfo in Kotlin
|
||||
*/
|
||||
DhcpInfo GetDhcpInfo();
|
||||
|
||||
private:
|
||||
jmethodID initializeControllersId;
|
||||
jmethodID vibrateDeviceId;
|
||||
@ -191,6 +204,7 @@ namespace skyline {
|
||||
jmethodID closeKeyboardId;
|
||||
jmethodID showValidationResultId;
|
||||
jmethodID getVersionCodeId;
|
||||
jmethodID getDhcpInfoId;
|
||||
|
||||
jmethodID getIntegerValueId;
|
||||
};
|
||||
|
@ -4,8 +4,22 @@
|
||||
#include "IScanRequest.h"
|
||||
#include "IRequest.h"
|
||||
#include "IGeneralService.h"
|
||||
#include <common/settings.h>
|
||||
#include <jvm.h>
|
||||
|
||||
namespace skyline::service::nifm {
|
||||
/**
|
||||
* @brief Converts integer value to an array of bytes ordered in little-endian format
|
||||
*/
|
||||
static std::array<u8, 4> ConvertIntToByteArray(i32 value) {
|
||||
std::array<u8, 4> result{};
|
||||
result[0] = value & 0xFF;
|
||||
result[1] = (value >> 8) & 0xFF;
|
||||
result[2] = (value >> 16) & 0xFF;
|
||||
result[3] = (value >> 24) & 0xFF;
|
||||
return result;
|
||||
}
|
||||
|
||||
IGeneralService::IGeneralService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {}
|
||||
|
||||
Result IGeneralService::CreateScanRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
@ -18,13 +32,89 @@ namespace skyline::service::nifm {
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IGeneralService::GetCurrentNetworkProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
if (!(*state.settings->isInternetEnabled))
|
||||
return result::NoInternetConnection;
|
||||
|
||||
const UUID uuid{static_cast<u128>(0xdeadbeef) << 64};
|
||||
auto dhcpInfo{state.jvm->GetDhcpInfo()};
|
||||
|
||||
SfNetworkProfileData networkProfileData{
|
||||
.ipSettingData{
|
||||
.ipAddressSetting{
|
||||
true,
|
||||
.currentAddress{ConvertIntToByteArray(dhcpInfo.ipAddress)},
|
||||
.subnetMask{ConvertIntToByteArray(dhcpInfo.subnet)},
|
||||
.gateway{ConvertIntToByteArray(dhcpInfo.gateway)},
|
||||
},
|
||||
.dnsSetting{
|
||||
true,
|
||||
.primaryDns{ConvertIntToByteArray(dhcpInfo.dns1)},
|
||||
.secondaryDns{ConvertIntToByteArray(dhcpInfo.dns2)},
|
||||
},
|
||||
.proxySetting{
|
||||
false,
|
||||
.port{},
|
||||
.proxyServer{},
|
||||
.automaticAuthEnabled{},
|
||||
.user{},
|
||||
.password{},
|
||||
},
|
||||
1500,
|
||||
},
|
||||
.uuid{uuid},
|
||||
.networkName{"Skyline Network"},
|
||||
.wirelessSettingData{
|
||||
12,
|
||||
.ssid{"Skyline Network"},
|
||||
.passphrase{"skylinepassword"},
|
||||
},
|
||||
};
|
||||
|
||||
request.outputBuf.at(0).as<SfNetworkProfileData>() = networkProfileData;
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IGeneralService::GetCurrentIpAddress(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
return result::NoInternetConnection;
|
||||
if (!(*state.settings->isInternetEnabled))
|
||||
return result::NoInternetConnection;
|
||||
|
||||
auto dhcpInfo{state.jvm->GetDhcpInfo()};
|
||||
response.Push(ConvertIntToByteArray(dhcpInfo.ipAddress));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IGeneralService::GetCurrentIpConfigInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
if (!(*state.settings->isInternetEnabled))
|
||||
return result::NoInternetConnection;
|
||||
|
||||
auto dhcpInfo{state.jvm->GetDhcpInfo()};
|
||||
|
||||
struct IpConfigInfo {
|
||||
IpAddressSetting ipAddressSetting;
|
||||
DnsSetting dnsSetting;
|
||||
};
|
||||
|
||||
IpConfigInfo ipConfigInfo{
|
||||
.ipAddressSetting{
|
||||
true,
|
||||
.currentAddress{ConvertIntToByteArray(dhcpInfo.ipAddress)},
|
||||
.subnetMask{ConvertIntToByteArray(dhcpInfo.subnet)},
|
||||
.gateway{ConvertIntToByteArray(dhcpInfo.gateway)},
|
||||
},
|
||||
.dnsSetting{
|
||||
true,
|
||||
.primaryDns{ConvertIntToByteArray(dhcpInfo.dns1)},
|
||||
.secondaryDns{ConvertIntToByteArray(dhcpInfo.dns2)},
|
||||
},
|
||||
};
|
||||
|
||||
response.Push(ipConfigInfo);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IGeneralService::IsAnyInternetRequestAccepted(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
// We don't emulate networking so always return false
|
||||
response.Push(false);
|
||||
response.Push<u8>(*state.settings->isInternetEnabled);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,90 @@
|
||||
#pragma once
|
||||
|
||||
#include <services/serviceman.h>
|
||||
#include "common/uuid.h"
|
||||
|
||||
namespace skyline::service::nifm {
|
||||
namespace result {
|
||||
constexpr Result NoInternetConnection{110, 300};
|
||||
}
|
||||
|
||||
struct IpAddressSetting {
|
||||
bool isAutomatic{};
|
||||
std::array<u8, 4> currentAddress{};
|
||||
std::array<u8, 4> subnetMask{};
|
||||
std::array<u8, 4> gateway{};
|
||||
};
|
||||
static_assert(sizeof(IpAddressSetting) == 0xD);
|
||||
|
||||
struct DnsSetting {
|
||||
bool isAutomatic{};
|
||||
std::array<u8, 4> primaryDns{};
|
||||
std::array<u8, 4> secondaryDns{};
|
||||
};
|
||||
static_assert(sizeof(DnsSetting) == 0x9);
|
||||
|
||||
struct ProxySetting {
|
||||
bool enabled{};
|
||||
u8 _pad0_[0x1];
|
||||
u16 port{};
|
||||
std::array<char, 0x64> proxyServer{};
|
||||
bool automaticAuthEnabled{};
|
||||
std::array<char, 0x20> user{};
|
||||
std::array<char, 0x20> password{};
|
||||
u8 _pad1_[0x1];
|
||||
};
|
||||
static_assert(sizeof(ProxySetting) == 0xAA);
|
||||
|
||||
struct IpSettingData {
|
||||
IpAddressSetting ipAddressSetting{};
|
||||
DnsSetting dnsSetting{};
|
||||
ProxySetting proxySetting{};
|
||||
u16 mtu{};
|
||||
};
|
||||
static_assert(sizeof(IpSettingData) == 0xC2);
|
||||
|
||||
struct SfWirelessSettingData {
|
||||
u8 ssidLength{};
|
||||
std::array<char, 0x20> ssid{};
|
||||
u8 _unk0_[0x3];
|
||||
std::array<char, 0x41> passphrase{};
|
||||
};
|
||||
static_assert(sizeof(SfWirelessSettingData) == 0x65);
|
||||
|
||||
struct NifmWirelessSettingData {
|
||||
u8 ssidLength{};
|
||||
std::array<char, 0x21> ssid{};
|
||||
u8 _unk0_[0x1];
|
||||
u8 _pad0_[0x1];
|
||||
u32 _unk1_[0x2];
|
||||
std::array<char, 0x41> passphrase{};
|
||||
u8 _pad1_[0x3];
|
||||
};
|
||||
static_assert(sizeof(NifmWirelessSettingData) == 0x70);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct SfNetworkProfileData {
|
||||
IpSettingData ipSettingData{};
|
||||
UUID uuid{};
|
||||
std::array<char, 0x40> networkName{};
|
||||
u8 _unk0_[0x4];
|
||||
SfWirelessSettingData wirelessSettingData{};
|
||||
u8 _pad0_[0x1];
|
||||
};
|
||||
static_assert(sizeof(SfNetworkProfileData) == 0x17C);
|
||||
|
||||
struct NifmNetworkProfileData {
|
||||
UUID uuid{};
|
||||
std::array<char, 0x40> networkName{};
|
||||
u32 _unk0_[0x2];
|
||||
u8 _unk1_[0x2];
|
||||
u8 _pad0_[0x2];
|
||||
NifmWirelessSettingData wirelessSettingData{};
|
||||
IpSettingData ipSettingData{};
|
||||
};
|
||||
static_assert(sizeof(NifmNetworkProfileData) == 0x18E);
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* @brief IGeneralService is used by applications to control the network connection
|
||||
* @url https://switchbrew.org/wiki/Network_Interface_services#IGeneralService
|
||||
@ -27,11 +106,21 @@ namespace skyline::service::nifm {
|
||||
*/
|
||||
Result CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Network_Interface_services#GetCurrentNetworkProfile
|
||||
*/
|
||||
Result GetCurrentNetworkProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Network_Interface_services#GetCurrentIpAddress
|
||||
*/
|
||||
Result GetCurrentIpAddress(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Network_Interface_services#GetCurrentIpConfigInfo
|
||||
*/
|
||||
Result GetCurrentIpConfigInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Network_Interface_services#IsAnyInternetRequestAccepted
|
||||
*/
|
||||
@ -40,7 +129,9 @@ namespace skyline::service::nifm {
|
||||
SERVICE_DECL(
|
||||
SFUNC(0x1, IGeneralService, CreateScanRequest),
|
||||
SFUNC(0x4, IGeneralService, CreateRequest),
|
||||
SFUNC(0x5, IGeneralService, GetCurrentNetworkProfile),
|
||||
SFUNC(0xC, IGeneralService, GetCurrentIpAddress),
|
||||
SFUNC(0xF, IGeneralService, GetCurrentIpConfigInfo),
|
||||
SFUNC(0x15, IGeneralService, IsAnyInternetRequestAccepted)
|
||||
)
|
||||
};
|
||||
|
@ -18,6 +18,8 @@ import android.content.res.Configuration
|
||||
import android.graphics.PointF
|
||||
import android.graphics.drawable.Icon
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.net.DhcpInfo
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.*
|
||||
import android.util.Log
|
||||
import android.util.Rational
|
||||
@ -626,6 +628,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
return dialog.waitForSubmitOrCancel().let { arrayOf(if (it.cancelled) 1 else 0, it.text) }
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun getDhcpInfo() : DhcpInfo {
|
||||
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
return wifiManager.dhcpInfo
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun closeKeyboard(dialog : SoftwareKeyboardDialog) {
|
||||
runOnUiThread { dialog.dismiss() }
|
||||
|
Loading…
Reference in New Issue
Block a user