Make wii-network async.
* accept still needs to be made async.
This commit is contained in:
parent
d0d162e6ad
commit
124fe24f4c
|
@ -335,6 +335,7 @@
|
|||
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb.cpp" />
|
||||
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb_kbd.cpp" />
|
||||
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_WiiMote.cpp" />
|
||||
<ClCompile Include="Src\IPC_HLE\WII_Socket.cpp" />
|
||||
<ClCompile Include="Src\x64MemTools.cpp" />
|
||||
<ClCompile Include="Src\Movie.cpp" />
|
||||
<ClCompile Include="Src\NetPlay.cpp" />
|
||||
|
@ -546,6 +547,7 @@
|
|||
<ClInclude Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb.h" />
|
||||
<ClInclude Include="Src\IPC_HLE\WII_IPC_HLE_Device_usb_kbd.h" />
|
||||
<ClInclude Include="Src\IPC_HLE\WII_IPC_HLE_WiiMote.h" />
|
||||
<ClInclude Include="Src\IPC_HLE\WII_Socket.h" />
|
||||
<ClInclude Include="Src\MemTools.h" />
|
||||
<ClInclude Include="Src\Movie.h" />
|
||||
<ClInclude Include="Src\NetPlay.h" />
|
||||
|
|
|
@ -574,6 +574,9 @@
|
|||
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\ec_wii.cpp" />
|
||||
<ClCompile Include="Src\IPC_HLE\WII_Socket.cpp">
|
||||
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\ConfigManager.h" />
|
||||
|
@ -1069,6 +1072,9 @@
|
|||
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\ec_wii.h" />
|
||||
<ClInclude Include="Src\IPC_HLE\WII_Socket.h">
|
||||
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
|
|
@ -525,14 +525,15 @@ void ExecuteCommand(u32 _Address)
|
|||
}
|
||||
}
|
||||
|
||||
// It seems that the original hardware overwrites the command after it has been
|
||||
// executed. We write 8 which is not any valid command, and what IOS does
|
||||
Memory::Write_U32(8, _Address);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(Command, _Address + 8);
|
||||
|
||||
if (CmdSuccess)
|
||||
{
|
||||
// It seems that the original hardware overwrites the command after it has been
|
||||
// executed. We write 8 which is not any valid command, and what IOS does
|
||||
Memory::Write_U32(8, _Address);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(Command, _Address + 8);
|
||||
|
||||
// Ensure replies happen in order, fairly ugly
|
||||
// Without this, tons of games fail now that DI commands have different reply delays
|
||||
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
|
||||
|
|
|
@ -36,6 +36,61 @@
|
|||
//#define FS_EFATAL (u32)-119 // Fatal error not used by IOS as fatal ERROR
|
||||
#define FS_EESEXHAUSTED (u32)-1016 // Max of 2 ES handles at a time
|
||||
|
||||
// A struct for IOS ioctlv calls
|
||||
struct SIOCtlVBuffer
|
||||
{
|
||||
SIOCtlVBuffer(u32 _Address) : m_Address(_Address)
|
||||
{
|
||||
// These are the Ioctlv parameters in the IOS communication. The BufferVector
|
||||
// is a memory address offset at where the in and out buffer addresses are
|
||||
// stored.
|
||||
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
|
||||
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
|
||||
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
|
||||
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
|
||||
|
||||
// The start of the out buffer
|
||||
u32 BufferVectorOffset = BufferVector;
|
||||
|
||||
// Write the address and size for all in messages
|
||||
for (u32 i = 0; i < NumberInBuffer; i++)
|
||||
{
|
||||
SBuffer Buffer;
|
||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
InBuffer.push_back(Buffer);
|
||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x",
|
||||
i, Buffer.m_Address, Buffer.m_Size);
|
||||
}
|
||||
|
||||
// Write the address and size for all out or in-out messages
|
||||
for (u32 i = 0; i < NumberPayloadBuffer; i++)
|
||||
{
|
||||
SBuffer Buffer;
|
||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
PayloadBuffer.push_back(Buffer);
|
||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x",
|
||||
i, Buffer.m_Address, Buffer.m_Size);
|
||||
}
|
||||
}
|
||||
|
||||
const u32 m_Address;
|
||||
|
||||
u32 Parameter;
|
||||
u32 NumberInBuffer;
|
||||
u32 NumberPayloadBuffer;
|
||||
u32 BufferVector;
|
||||
|
||||
struct SBuffer { u32 m_Address, m_Size; };
|
||||
std::vector<SBuffer> InBuffer;
|
||||
std::vector<SBuffer> PayloadBuffer;
|
||||
};
|
||||
|
||||
class IWII_IPC_HLE_Device
|
||||
{
|
||||
public:
|
||||
|
@ -104,61 +159,6 @@ protected:
|
|||
bool m_Hardware;
|
||||
bool m_Active;
|
||||
|
||||
// A struct for IOS ioctlv calls
|
||||
struct SIOCtlVBuffer
|
||||
{
|
||||
SIOCtlVBuffer(u32 _Address) : m_Address(_Address)
|
||||
{
|
||||
// These are the Ioctlv parameters in the IOS communication. The BufferVector
|
||||
// is a memory address offset at where the in and out buffer addresses are
|
||||
// stored.
|
||||
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
|
||||
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
|
||||
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
|
||||
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
|
||||
|
||||
// The start of the out buffer
|
||||
u32 BufferVectorOffset = BufferVector;
|
||||
|
||||
// Write the address and size for all in messages
|
||||
for (u32 i = 0; i < NumberInBuffer; i++)
|
||||
{
|
||||
SBuffer Buffer;
|
||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
InBuffer.push_back(Buffer);
|
||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x",
|
||||
i, Buffer.m_Address, Buffer.m_Size);
|
||||
}
|
||||
|
||||
// Write the address and size for all out or in-out messages
|
||||
for (u32 i = 0; i < NumberPayloadBuffer; i++)
|
||||
{
|
||||
SBuffer Buffer;
|
||||
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
|
||||
BufferVectorOffset += 4;
|
||||
PayloadBuffer.push_back(Buffer);
|
||||
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x",
|
||||
i, Buffer.m_Address, Buffer.m_Size);
|
||||
}
|
||||
}
|
||||
|
||||
const u32 m_Address;
|
||||
|
||||
u32 Parameter;
|
||||
u32 NumberInBuffer;
|
||||
u32 NumberPayloadBuffer;
|
||||
u32 BufferVector;
|
||||
|
||||
struct SBuffer { u32 m_Address, m_Size; };
|
||||
std::vector<SBuffer> InBuffer;
|
||||
std::vector<SBuffer> PayloadBuffer;
|
||||
};
|
||||
|
||||
// Write out the IPC struct from _CommandAddress to _NumberOfCommands numbers
|
||||
// of 4 byte commands.
|
||||
void DumpCommands(u32 _CommandAddress, size_t _NumberOfCommands = 8,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -135,7 +135,7 @@ struct nwc24_config_t
|
|||
NWC24_IDCS_GENERATED = 1,
|
||||
NWC24_IDCS_REGISTERED = 2
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
URL_COUNT = 0x05,
|
||||
|
@ -143,7 +143,7 @@ struct nwc24_config_t
|
|||
MAX_EMAIL_LENGTH = 0x40,
|
||||
MAX_PASSWORD_LENGTH = 0x20,
|
||||
};
|
||||
|
||||
|
||||
u32 magic; /* 'WcCf' 0x57634366 */
|
||||
u32 _unk_04; /* must be 8 */
|
||||
u64 nwc24_id;
|
||||
|
@ -167,21 +167,21 @@ class NWC24Config
|
|||
private:
|
||||
std::string path;
|
||||
nwc24_config_t config;
|
||||
|
||||
|
||||
public:
|
||||
NWC24Config()
|
||||
{
|
||||
path = File::GetUserPath(D_WIIWC24_IDX) + "nwc24msg.cfg";
|
||||
ReadConfig();
|
||||
}
|
||||
|
||||
|
||||
void ResetConfig()
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if (File::Exists(path))
|
||||
File::Delete(path);
|
||||
|
||||
|
||||
const char* urls[5] = {
|
||||
"https://amw.wc24.wii.com/cgi-bin/account.cgi",
|
||||
"http://rcw.wc24.wii.com/cgi-bin/check.cgi",
|
||||
|
@ -189,25 +189,25 @@ public:
|
|||
"http://mtw.wc24.wii.com/cgi-bin/delete.cgi",
|
||||
"http://mtw.wc24.wii.com/cgi-bin/send.cgi",
|
||||
};
|
||||
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
|
||||
SetMagic(0x57634366);
|
||||
SetUnk(8);
|
||||
SetCreationStage(nwc24_config_t::NWC24_IDCS_INITIAL);
|
||||
SetEnableBooting(0);
|
||||
SetEmail("@wii.com");
|
||||
|
||||
|
||||
for(i=0; i<nwc24_config_t::URL_COUNT; i++)
|
||||
{
|
||||
strncpy(config.http_urls[i], urls[i], nwc24_config_t::MAX_URL_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
SetChecksum(CalculateNwc24ConfigChecksum());
|
||||
|
||||
|
||||
WriteConfig();
|
||||
}
|
||||
|
||||
|
||||
void WriteConfig()
|
||||
{
|
||||
if (!File::Exists(path))
|
||||
|
@ -217,11 +217,11 @@ public:
|
|||
ERROR_LOG(WII_IPC_WC24, "Failed to create directory for WC24");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File::IOFile(path, "wb").WriteBytes((void*)&config, sizeof(config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ReadConfig()
|
||||
{
|
||||
if (File::Exists(path))
|
||||
|
@ -240,7 +240,7 @@ public:
|
|||
ResetConfig();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u32 CalculateNwc24ConfigChecksum(void)
|
||||
{
|
||||
u32* ptr = (u32*)&config;
|
||||
|
@ -252,7 +252,7 @@ public:
|
|||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
s32 CheckNwc24Config(void)
|
||||
{
|
||||
if (Magic() != 0x57634366) /* 'WcCf' magic */
|
||||
|
@ -274,16 +274,16 @@ public:
|
|||
}
|
||||
if (Unk() != 8)
|
||||
return -27;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 Magic(){return Common::swap32(config.magic);}
|
||||
void SetMagic(u32 magic){config.magic = Common::swap32(magic);}
|
||||
|
||||
|
||||
u32 Unk(){return Common::swap32(config._unk_04);}
|
||||
void SetUnk(u32 _unk_04){config._unk_04 = Common::swap32(_unk_04);}
|
||||
|
||||
|
||||
u32 IdGen(){return Common::swap32(config.id_generation);}
|
||||
void SetIdGen(u32 id_generation){config.id_generation = Common::swap32(id_generation);}
|
||||
void IncrementIdGen(){
|
||||
|
@ -292,26 +292,26 @@ public:
|
|||
id_ctr &= 0x1F;
|
||||
SetIdGen(id_ctr);
|
||||
}
|
||||
|
||||
|
||||
u32 Checksum(){return Common::swap32(config.checksum);}
|
||||
void SetChecksum(u32 checksum){config.checksum = Common::swap32(checksum);}
|
||||
|
||||
|
||||
u32 CreationStage(){return Common::swap32(config.creation_stage);}
|
||||
void SetCreationStage(u32 creation_stage){config.creation_stage = Common::swap32(creation_stage);}
|
||||
|
||||
|
||||
u32 EnableBooting(){return Common::swap32(config.enable_booting);}
|
||||
void SetEnableBooting(u32 enable_booting){config.enable_booting = Common::swap32(enable_booting);}
|
||||
|
||||
|
||||
u64 Id(){return Common::swap64(config.nwc24_id);}
|
||||
void SetId(u64 nwc24_id){config.nwc24_id = Common::swap64(nwc24_id);}
|
||||
|
||||
|
||||
const char * Email(){return config.email;}
|
||||
void SetEmail(const char * email)
|
||||
{
|
||||
strncpy(config.email, email, nwc24_config_t::MAX_EMAIL_LENGTH);
|
||||
config.email[nwc24_config_t::MAX_EMAIL_LENGTH-1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class WiiNetConfig
|
||||
|
@ -390,7 +390,7 @@ public:
|
|||
class CWII_IPC_HLE_Device_net_kd_request : public IWII_IPC_HLE_Device
|
||||
{
|
||||
public:
|
||||
CWII_IPC_HLE_Device_net_kd_request(u32 _DeviceID, const std::string& _rDeviceName);
|
||||
CWII_IPC_HLE_Device_net_kd_request(u32 _DeviceID, const std::string& _rDeviceName);
|
||||
|
||||
virtual ~CWII_IPC_HLE_Device_net_kd_request();
|
||||
|
||||
|
@ -399,32 +399,32 @@ public:
|
|||
virtual bool IOCtl(u32 _CommandAddress);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
IOCTL_NWC24_SUSPEND_SCHEDULAR = 0x01,
|
||||
IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR = 0x02,
|
||||
IOCTL_NWC24_EXEC_RESUME_SCHEDULAR = 0x03,
|
||||
IOCTL_NWC24_KD_GET_TIME_TRIGGERS = 0x04,
|
||||
IOCTL_NWC24_SET_SCHEDULE_SPAN = 0x05,
|
||||
IOCTL_NWC24_STARTUP_SOCKET = 0x06,
|
||||
IOCTL_NWC24_CLEANUP_SOCKET = 0x07,
|
||||
IOCTL_NWC24_LOCK_SOCKET = 0x08,
|
||||
IOCTL_NWC24_UNLOCK_SOCKET = 0x09,
|
||||
IOCTL_NWC24_CHECK_MAIL_NOW = 0x0A,
|
||||
IOCTL_NWC24_SEND_MAIL_NOW = 0x0B,
|
||||
IOCTL_NWC24_RECEIVE_MAIL_NOW = 0x0C,
|
||||
IOCTL_NWC24_SAVE_MAIL_NOW = 0x0D,
|
||||
IOCTL_NWC24_DOWNLOAD_NOW_EX = 0x0E,
|
||||
IOCTL_NWC24_REQUEST_GENERATED_USER_ID = 0x0F,
|
||||
IOCTL_NWC24_REQUEST_REGISTER_USER_ID = 0x10,
|
||||
IOCTL_NWC24_GET_SCHEDULAR_STAT = 0x1E,
|
||||
IOCTL_NWC24_SET_FILTER_MODE = 0x1F,
|
||||
IOCTL_NWC24_SET_DEBUG_MODE = 0x20,
|
||||
IOCTL_NWC24_KD_SET_NEXT_WAKEUP = 0x21,
|
||||
IOCTL_NWC24_SET_SCRIPT_MODE = 0x22,
|
||||
IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IOCTL_NWC24_SUSPEND_SCHEDULAR = 0x01,
|
||||
IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR = 0x02,
|
||||
IOCTL_NWC24_EXEC_RESUME_SCHEDULAR = 0x03,
|
||||
IOCTL_NWC24_KD_GET_TIME_TRIGGERS = 0x04,
|
||||
IOCTL_NWC24_SET_SCHEDULE_SPAN = 0x05,
|
||||
IOCTL_NWC24_STARTUP_SOCKET = 0x06,
|
||||
IOCTL_NWC24_CLEANUP_SOCKET = 0x07,
|
||||
IOCTL_NWC24_LOCK_SOCKET = 0x08,
|
||||
IOCTL_NWC24_UNLOCK_SOCKET = 0x09,
|
||||
IOCTL_NWC24_CHECK_MAIL_NOW = 0x0A,
|
||||
IOCTL_NWC24_SEND_MAIL_NOW = 0x0B,
|
||||
IOCTL_NWC24_RECEIVE_MAIL_NOW = 0x0C,
|
||||
IOCTL_NWC24_SAVE_MAIL_NOW = 0x0D,
|
||||
IOCTL_NWC24_DOWNLOAD_NOW_EX = 0x0E,
|
||||
IOCTL_NWC24_REQUEST_GENERATED_USER_ID = 0x0F,
|
||||
IOCTL_NWC24_REQUEST_REGISTER_USER_ID = 0x10,
|
||||
IOCTL_NWC24_GET_SCHEDULAR_STAT = 0x1E,
|
||||
IOCTL_NWC24_SET_FILTER_MODE = 0x1F,
|
||||
IOCTL_NWC24_SET_DEBUG_MODE = 0x20,
|
||||
IOCTL_NWC24_KD_SET_NEXT_WAKEUP = 0x21,
|
||||
IOCTL_NWC24_SET_SCRIPT_MODE = 0x22,
|
||||
IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28,
|
||||
};
|
||||
|
||||
enum {
|
||||
MODEL_RVT = 0,
|
||||
MODEL_RVV = 0,
|
||||
|
@ -432,15 +432,16 @@ private:
|
|||
MODEL_RVD = 2,
|
||||
MODEL_ELSE = 7
|
||||
};
|
||||
|
||||
|
||||
u8 GetAreaCode(const char * area);
|
||||
u8 GetHardwareModel(const char * model);
|
||||
|
||||
|
||||
s32 NWC24MakeUserID(u64* nwc24_id, u32 hollywood_id, u16 id_ctr, u8 hardware_model, u8 area_code);
|
||||
|
||||
|
||||
NWC24Config config;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CWII_IPC_HLE_Device_net_kd_time : public IWII_IPC_HLE_Device
|
||||
{
|
||||
|
@ -457,14 +458,14 @@ public:
|
|||
|
||||
virtual bool Open(u32 _CommandAddress, u32 _Mode)
|
||||
{
|
||||
INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Open");
|
||||
INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Open");
|
||||
Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool Close(u32 _CommandAddress, bool _bForce)
|
||||
{
|
||||
INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Close");
|
||||
INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Close");
|
||||
if (!_bForce)
|
||||
Memory::Write_U32(0, _CommandAddress + 4);
|
||||
return true;
|
||||
|
@ -472,9 +473,9 @@ public:
|
|||
|
||||
virtual bool IOCtl(u32 _CommandAddress)
|
||||
{
|
||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
|
||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
||||
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
|
||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
||||
|
||||
|
@ -483,8 +484,8 @@ public:
|
|||
// TODO Writes stuff to /shared2/nwc24/misc.bin
|
||||
u32 update_misc = 0;
|
||||
|
||||
switch (Parameter)
|
||||
{
|
||||
switch (Parameter)
|
||||
{
|
||||
case IOCTL_NW24_GET_UNIVERSAL_TIME:
|
||||
Memory::Write_U64(GetAdjustedUTC(), BufferOut + 4);
|
||||
break;
|
||||
|
@ -494,7 +495,7 @@ public:
|
|||
update_misc = Memory::Read_U32(BufferIn + 8);
|
||||
break;
|
||||
|
||||
case IOCTL_NW24_SET_RTC_COUNTER:
|
||||
case IOCTL_NW24_SET_RTC_COUNTER:
|
||||
rtc = Memory::Read_U32(BufferIn);
|
||||
update_misc = Memory::Read_U32(BufferIn + 4);
|
||||
break;
|
||||
|
@ -507,11 +508,11 @@ public:
|
|||
result = -9;
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
ERROR_LOG(WII_IPC_NET, "%s - unknown IOCtl: %x\n",
|
||||
GetDeviceName().c_str(), Parameter);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// write return values
|
||||
Memory::Write_U32(common_result, BufferOut);
|
||||
|
@ -520,14 +521,14 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
IOCTL_NW24_GET_UNIVERSAL_TIME = 0x14,
|
||||
IOCTL_NW24_SET_UNIVERSAL_TIME = 0x15,
|
||||
IOCTL_NW24_UNIMPLEMENTED = 0x16,
|
||||
IOCTL_NW24_SET_RTC_COUNTER = 0x17,
|
||||
IOCTL_NW24_GET_TIME_DIFF = 0x18,
|
||||
};
|
||||
};
|
||||
|
||||
u64 rtc;
|
||||
s64 utcdiff;
|
||||
|
@ -550,6 +551,75 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
struct bind_params
|
||||
{
|
||||
u32 socket;
|
||||
u32 has_name;
|
||||
u8 name[28];
|
||||
};
|
||||
|
||||
struct GC_sockaddr
|
||||
{
|
||||
u8 sa_len;
|
||||
u8 sa_family;
|
||||
s8 sa_data[14];
|
||||
};
|
||||
|
||||
struct GC_in_addr
|
||||
{
|
||||
// this cannot be named s_addr under windows - collides with some crazy define.
|
||||
u32 s_addr_;
|
||||
};
|
||||
|
||||
struct GC_sockaddr_in
|
||||
{
|
||||
u8 sin_len;
|
||||
u8 sin_family;
|
||||
u16 sin_port;
|
||||
struct GC_in_addr sin_addr;
|
||||
s8 sin_zero[8];
|
||||
};
|
||||
|
||||
enum NET_IOCTL
|
||||
{
|
||||
IOCTL_SO_ACCEPT = 1,
|
||||
IOCTL_SO_BIND,
|
||||
IOCTL_SO_CLOSE,
|
||||
IOCTL_SO_CONNECT,
|
||||
IOCTL_SO_FCNTL,
|
||||
IOCTL_SO_GETPEERNAME,
|
||||
IOCTL_SO_GETSOCKNAME,
|
||||
IOCTL_SO_GETSOCKOPT,
|
||||
IOCTL_SO_SETSOCKOPT,
|
||||
IOCTL_SO_LISTEN,
|
||||
IOCTL_SO_POLL,
|
||||
IOCTLV_SO_RECVFROM,
|
||||
IOCTLV_SO_SENDTO,
|
||||
IOCTL_SO_SHUTDOWN,
|
||||
IOCTL_SO_SOCKET,
|
||||
IOCTL_SO_GETHOSTID,
|
||||
IOCTL_SO_GETHOSTBYNAME,
|
||||
IOCTL_SO_GETHOSTBYADDR,
|
||||
IOCTLV_SO_GETNAMEINFO,
|
||||
IOCTL_SO_UNK14,
|
||||
IOCTL_SO_INETATON,
|
||||
IOCTL_SO_INETPTON,
|
||||
IOCTL_SO_INETNTOP,
|
||||
IOCTLV_SO_GETADDRINFO,
|
||||
IOCTL_SO_SOCKATMARK,
|
||||
IOCTLV_SO_UNK1A,
|
||||
IOCTLV_SO_UNK1B,
|
||||
IOCTLV_SO_GETINTERFACEOPT,
|
||||
IOCTLV_SO_SETINTERFACEOPT,
|
||||
IOCTL_SO_SETINTERFACE,
|
||||
IOCTL_SO_STARTUP,
|
||||
IOCTL_SO_ICMPSOCKET = 0x30,
|
||||
IOCTLV_SO_ICMPPING,
|
||||
IOCTL_SO_ICMPCANCEL,
|
||||
IOCTL_SO_ICMPCLOSE
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CWII_IPC_HLE_Device_net_ip_top : public IWII_IPC_HLE_Device
|
||||
{
|
||||
|
@ -562,51 +632,13 @@ public:
|
|||
virtual bool Close(u32 _CommandAddress, bool _bForce);
|
||||
virtual bool IOCtl(u32 _CommandAddress);
|
||||
virtual bool IOCtlV(u32 _CommandAddress);
|
||||
|
||||
|
||||
virtual u32 Update();
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
WSADATA InitData;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
IOCTL_SO_ACCEPT = 1,
|
||||
IOCTL_SO_BIND,
|
||||
IOCTL_SO_CLOSE,
|
||||
IOCTL_SO_CONNECT,
|
||||
IOCTL_SO_FCNTL,
|
||||
IOCTL_SO_GETPEERNAME,
|
||||
IOCTL_SO_GETSOCKNAME,
|
||||
IOCTL_SO_GETSOCKOPT,
|
||||
IOCTL_SO_SETSOCKOPT,
|
||||
IOCTL_SO_LISTEN,
|
||||
IOCTL_SO_POLL,
|
||||
IOCTLV_SO_RECVFROM,
|
||||
IOCTLV_SO_SENDTO,
|
||||
IOCTL_SO_SHUTDOWN,
|
||||
IOCTL_SO_SOCKET,
|
||||
IOCTL_SO_GETHOSTID,
|
||||
IOCTL_SO_GETHOSTBYNAME,
|
||||
IOCTL_SO_GETHOSTBYADDR,
|
||||
IOCTLV_SO_GETNAMEINFO,
|
||||
IOCTL_SO_UNK14,
|
||||
IOCTL_SO_INETATON,
|
||||
IOCTL_SO_INETPTON,
|
||||
IOCTL_SO_INETNTOP,
|
||||
IOCTLV_SO_GETADDRINFO,
|
||||
IOCTL_SO_SOCKATMARK,
|
||||
IOCTLV_SO_UNK1A,
|
||||
IOCTLV_SO_UNK1B,
|
||||
IOCTLV_SO_GETINTERFACEOPT,
|
||||
IOCTLV_SO_SETINTERFACEOPT,
|
||||
IOCTL_SO_SETINTERFACE,
|
||||
IOCTL_SO_STARTUP,
|
||||
IOCTL_SO_ICMPSOCKET = 0x30,
|
||||
IOCTLV_SO_ICMPPING,
|
||||
IOCTL_SO_ICMPCANCEL,
|
||||
IOCTL_SO_ICMPCLOSE
|
||||
};
|
||||
|
||||
u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize);
|
||||
u32 ExecuteCommandV(SIOCtlVBuffer& CommandBuffer);
|
||||
};
|
||||
|
@ -628,7 +660,7 @@ private:
|
|||
enum
|
||||
{
|
||||
IOCTLV_NCD_LOCKWIRELESSDRIVER = 0x1, // NCDLockWirelessDriver
|
||||
IOCTLV_NCD_UNLOCKWIRELESSDRIVER = 0x2, // NCDUnlockWirelessDriver
|
||||
IOCTLV_NCD_UNLOCKWIRELESSDRIVER = 0x2, // NCDUnlockWirelessDriver
|
||||
IOCTLV_NCD_GETCONFIG = 0x3, // NCDiGetConfig
|
||||
IOCTLV_NCD_SETCONFIG = 0x4, // NCDiSetConfig
|
||||
IOCTLV_NCD_READCONFIG = 0x5,
|
||||
|
@ -687,7 +719,7 @@ private:
|
|||
SCAN_PASSIVE
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma pack(push, 1)
|
||||
struct ScanInfo
|
||||
{
|
||||
u16 channel_bitmap;
|
||||
|
@ -731,7 +763,7 @@ private:
|
|||
char wlversion[0x50];
|
||||
u8 unk[0x30];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,14 +17,17 @@
|
|||
|
||||
#include "FileUtil.h"
|
||||
#include "WII_IPC_HLE_Device_net_ssl.h"
|
||||
#include "WII_Socket.h"
|
||||
#include "../Debugger/Debugger_SymbolMap.h"
|
||||
|
||||
WII_SSL CWII_IPC_HLE_Device_net_ssl::_SSL[NET_SSL_MAXINSTANCES];
|
||||
|
||||
CWII_IPC_HLE_Device_net_ssl::CWII_IPC_HLE_Device_net_ssl(u32 _DeviceID, const std::string& _rDeviceName)
|
||||
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
|
||||
{
|
||||
for (int i = 0; i < NET_SSL_MAXINSTANCES; ++i)
|
||||
{
|
||||
memset(&_SSL[i], 0, sizeof(struct _SSL));
|
||||
memset(&_SSL[i], 0, sizeof(WII_SSL));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +48,7 @@ CWII_IPC_HLE_Device_net_ssl::~CWII_IPC_HLE_Device_net_ssl()
|
|||
memset(&_SSL[i].ctx, 0, sizeof(ssl_context));
|
||||
memset(&_SSL[i].session, 0, sizeof(ssl_session));
|
||||
memset(&_SSL[i].hs, 0, sizeof(havege_state));
|
||||
memset(_SSL[i].hostname, 0, MAX_HOSTNAME_LEN);
|
||||
memset(_SSL[i].hostname, 0, NET_SSL_MAX_HOSTNAME_LEN);
|
||||
|
||||
_SSL[i].active = false;
|
||||
}
|
||||
|
@ -94,16 +97,7 @@ bool CWII_IPC_HLE_Device_net_ssl::IOCtl(u32 _CommandAddress)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||
{
|
||||
u32 ReturnValue = 0;
|
||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
||||
|
||||
ReturnValue = ExecuteCommandV(CommandBuffer.Parameter, CommandBuffer);
|
||||
|
||||
Memory::Write_U32(ReturnValue, _CommandAddress+4);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_verify_certificate_callback (void *data, x509_cert *crt, int depth, int *flags)
|
||||
|
@ -145,14 +139,17 @@ _verify_certificate_callback (void *data, x509_cert *crt, int depth, int *flags)
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer)
|
||||
{
|
||||
bool CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
|
||||
{
|
||||
u32 ReturnValue = 0;
|
||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
||||
|
||||
s32 returnValue = 0;
|
||||
|
||||
u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0;
|
||||
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
|
||||
|
||||
u32 _BufferOut = 0, _BufferOut2 = 0, _BufferOut3 = 0;
|
||||
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
|
||||
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
|
||||
|
||||
if (CommandBuffer.InBuffer.size() > 0)
|
||||
|
@ -173,26 +170,26 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C
|
|||
|
||||
if (CommandBuffer.PayloadBuffer.size() > 0)
|
||||
{
|
||||
_BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
||||
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
||||
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
||||
}
|
||||
if (CommandBuffer.PayloadBuffer.size() > 1)
|
||||
{
|
||||
_BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
||||
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
||||
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
||||
}
|
||||
if (CommandBuffer.PayloadBuffer.size() > 2)
|
||||
{
|
||||
_BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
|
||||
BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
|
||||
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
|
||||
}
|
||||
|
||||
switch (_Parameter)
|
||||
switch (CommandBuffer.Parameter)
|
||||
{
|
||||
case IOCTLV_NET_SSL_NEW:
|
||||
{
|
||||
int verifyOption = Memory::Read_U32(_BufferOut);
|
||||
const char * hostname = (const char*) Memory::GetPointer(_BufferOut2);
|
||||
int verifyOption = Memory::Read_U32(BufferOut);
|
||||
const char * hostname = (const char*) Memory::GetPointer(BufferOut2);
|
||||
|
||||
int freeSSL = this->getSSLFreeID();
|
||||
if (freeSSL)
|
||||
|
@ -221,8 +218,8 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C
|
|||
ssl_set_authmode(&_SSL[sslID].ctx, SSL_VERIFY_OPTIONAL);
|
||||
ssl_set_renegotiation(&_SSL[sslID].ctx, SSL_RENEGOTIATION_ENABLED);
|
||||
|
||||
memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, MAX_HOSTNAME_LEN));
|
||||
_SSL[sslID].hostname[MAX_HOSTNAME_LEN-1] = '\0';
|
||||
memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, NET_SSL_MAX_HOSTNAME_LEN));
|
||||
_SSL[sslID].hostname[NET_SSL_MAX_HOSTNAME_LEN-1] = '\0';
|
||||
ssl_set_hostname(&_SSL[sslID].ctx, _SSL[sslID].hostname);
|
||||
|
||||
_SSL[sslID].active = true;
|
||||
|
@ -240,13 +237,13 @@ _SSL_NEW_ERROR:
|
|||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
verifyOption, hostname,
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_SHUTDOWN:
|
||||
{
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
ssl_close_notify(&_SSL[sslID].ctx);
|
||||
|
@ -259,7 +256,7 @@ _SSL_NEW_ERROR:
|
|||
memset(&_SSL[sslID].ctx, 0, sizeof(ssl_context));
|
||||
memset(&_SSL[sslID].session, 0, sizeof(ssl_session));
|
||||
memset(&_SSL[sslID].hs, 0, sizeof(havege_state));
|
||||
memset(_SSL[sslID].hostname, 0, MAX_HOSTNAME_LEN);
|
||||
memset(_SSL[sslID].hostname, 0, NET_SSL_MAX_HOSTNAME_LEN);
|
||||
|
||||
_SSL[sslID].active = false;
|
||||
|
||||
|
@ -274,8 +271,8 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_SETROOTCA:
|
||||
|
@ -285,16 +282,16 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
|
||||
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
int ret = x509parse_crt_der(
|
||||
&_SSL[sslID].cacert,
|
||||
Memory::GetPointer(_BufferOut2),
|
||||
Memory::GetPointer(BufferOut2),
|
||||
BufferOutSize2);
|
||||
|
||||
if (ret)
|
||||
|
@ -322,10 +319,10 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX));
|
||||
|
@ -361,10 +358,10 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
x509_free(&_SSL[sslID].clicert);
|
||||
|
@ -384,7 +381,7 @@ _SSL_NEW_ERROR:
|
|||
}
|
||||
case IOCTLV_NET_SSL_SETBUILTINROOTCA:
|
||||
{
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX));
|
||||
|
@ -411,16 +408,16 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_CONNECT:
|
||||
{
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
_SSL[sslID].sockfd = Memory::Read_U32(_BufferOut2);
|
||||
_SSL[sslID].sockfd = Memory::Read_U32(BufferOut2);
|
||||
WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", _SSL[sslID].sockfd);
|
||||
ssl_set_bio(&_SSL[sslID].ctx, net_recv, &_SSL[sslID].sockfd, net_send, &_SSL[sslID].sockfd);
|
||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
||||
|
@ -434,77 +431,33 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_DOHANDSHAKE:
|
||||
{
|
||||
int ret = 0;
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
ret = ssl_handshake(&_SSL[sslID].ctx);
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn);
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn);
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
||||
break;
|
||||
}
|
||||
WiiSockMan &sm = WiiSockMan::getInstance();
|
||||
sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
|
||||
}
|
||||
WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) "
|
||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
ret,
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_WRITE:
|
||||
{
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
int ret = ssl_write( &_SSL[sslID].ctx, Memory::GetPointer(_BufferOut2), BufferOutSize2);
|
||||
|
||||
#ifdef DEBUG_SSL
|
||||
File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(_BufferOut2), BufferOutSize2);
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
{
|
||||
// Return bytes written or SSL_ERR_ZERO if none
|
||||
Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, _BufferIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn);
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn);
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
WiiSockMan &sm = WiiSockMan::getInstance();
|
||||
sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -515,45 +468,21 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
WARN_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(_BufferOut2));
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
WARN_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(BufferOut2));
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_READ:
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
ret = ssl_read( &_SSL[sslID].ctx, Memory::GetPointer(_BufferIn2), BufferInSize2);
|
||||
#ifdef DEBUG_SSL
|
||||
if (ret > 0)
|
||||
{
|
||||
File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(_BufferIn2), ret);
|
||||
}
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
{
|
||||
// Return bytes read or SSL_ERR_ZERO if none
|
||||
Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, _BufferIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, _BufferIn);
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, _BufferIn);
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
WiiSockMan &sm = WiiSockMan::getInstance();
|
||||
sm.doSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -566,13 +495,13 @@ _SSL_NEW_ERROR:
|
|||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
ret,
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_SETROOTCADEFAULT:
|
||||
{
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
||||
|
@ -586,8 +515,8 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT:
|
||||
|
@ -597,13 +526,13 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
|
||||
int sslID = Memory::Read_U32(_BufferOut) - 1;
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
||||
Memory::Write_U32(SSL_OK, _BufferIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -616,22 +545,24 @@ _SSL_NEW_ERROR:
|
|||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
|
||||
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
|
||||
_Parameter,
|
||||
CommandBuffer.Parameter,
|
||||
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
|
||||
_BufferIn3, BufferInSize3, _BufferOut, BufferOutSize,
|
||||
_BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3);
|
||||
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize,
|
||||
BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
Memory::Write_U32(ReturnValue, _CommandAddress+4);
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommand(u32 _Command,
|
||||
u32 _BufferIn, u32 BufferInSize,
|
||||
u32 _BufferOut, u32 BufferOutSize)
|
||||
u32 BufferOut, u32 BufferOutSize)
|
||||
{
|
||||
WARN_LOG(WII_IPC_SSL, "%s unknown %i "
|
||||
"(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
|
||||
GetDeviceName().c_str(), _Command,
|
||||
_BufferIn, BufferInSize, _BufferOut, BufferOutSize);
|
||||
_BufferIn, BufferInSize, BufferOut, BufferOutSize);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,60 @@
|
|||
#include <polarssl/ssl.h>
|
||||
#include <polarssl/havege.h>
|
||||
|
||||
#define MAX_HOSTNAME_LEN 256
|
||||
#define NET_SSL_MAX_HOSTNAME_LEN 256
|
||||
#define NET_SSL_MAXINSTANCES 4
|
||||
|
||||
#define SSLID_VALID(x) (x >= 0 && x < NET_SSL_MAXINSTANCES && _SSL[x].active)
|
||||
#define SSLID_VALID(x) (x >= 0 && x < NET_SSL_MAXINSTANCES && CWII_IPC_HLE_Device_net_ssl::_SSL[x].active)
|
||||
|
||||
enum ssl_err_t
|
||||
{
|
||||
SSL_OK = 0,
|
||||
SSL_ERR_FAILED = -1,
|
||||
SSL_ERR_RAGAIN = -2,
|
||||
SSL_ERR_WAGAIN = -3,
|
||||
SSL_ERR_SYSCALL = -5,
|
||||
SSL_ERR_ZERO = -6, // read or write returned 0
|
||||
SSL_ERR_CAGAIN = -7, // BIO not connected
|
||||
SSL_ERR_ID = -8, // invalid SSL id
|
||||
SSL_ERR_VCOMMONNAME = -9, // verify failed: common name
|
||||
SSL_ERR_VROOTCA = -10, // verify failed: root ca
|
||||
SSL_ERR_VCHAIN = -11, // verify failed: certificate chain
|
||||
SSL_ERR_VDATE = -12, // verify failed: date invalid
|
||||
SSL_ERR_SERVER_CERT = -13, // certificate cert invalid
|
||||
};
|
||||
|
||||
enum SSL_IOCTL
|
||||
{
|
||||
IOCTLV_NET_SSL_NEW = 0x01,
|
||||
IOCTLV_NET_SSL_CONNECT = 0x02,
|
||||
IOCTLV_NET_SSL_DOHANDSHAKE = 0x03,
|
||||
IOCTLV_NET_SSL_READ = 0x04,
|
||||
IOCTLV_NET_SSL_WRITE = 0x05,
|
||||
IOCTLV_NET_SSL_SHUTDOWN = 0x06,
|
||||
IOCTLV_NET_SSL_SETCLIENTCERT = 0x07,
|
||||
IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08,
|
||||
IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09,
|
||||
IOCTLV_NET_SSL_SETROOTCA = 0x0A,
|
||||
IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B,
|
||||
IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C,
|
||||
IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D,
|
||||
IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E,
|
||||
IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F,
|
||||
IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14,
|
||||
IOCTLV_NET_SSL_DEBUGGETTIME = 0x15,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ssl_context ctx;
|
||||
ssl_session session;
|
||||
havege_state hs;
|
||||
x509_cert cacert;
|
||||
x509_cert clicert;
|
||||
rsa_context rsa;
|
||||
int sockfd;
|
||||
char hostname[NET_SSL_MAX_HOSTNAME_LEN];
|
||||
bool active;
|
||||
} WII_SSL;
|
||||
|
||||
class CWII_IPC_HLE_Device_net_ssl : public IWII_IPC_HLE_Device
|
||||
{
|
||||
|
@ -44,58 +94,11 @@ public:
|
|||
virtual bool IOCtl(u32 _CommandAddress);
|
||||
virtual bool IOCtlV(u32 _CommandAddress);
|
||||
int getSSLFreeID();
|
||||
|
||||
static WII_SSL _SSL[NET_SSL_MAXINSTANCES];
|
||||
|
||||
private:
|
||||
|
||||
struct _SSL{
|
||||
ssl_context ctx;
|
||||
ssl_session session;
|
||||
havege_state hs;
|
||||
x509_cert cacert;
|
||||
x509_cert clicert;
|
||||
rsa_context rsa;
|
||||
int sockfd;
|
||||
char hostname[MAX_HOSTNAME_LEN];
|
||||
bool active;
|
||||
} _SSL[NET_SSL_MAXINSTANCES];
|
||||
|
||||
enum
|
||||
{
|
||||
IOCTLV_NET_SSL_NEW = 0x01,
|
||||
IOCTLV_NET_SSL_CONNECT = 0x02,
|
||||
IOCTLV_NET_SSL_DOHANDSHAKE = 0x03,
|
||||
IOCTLV_NET_SSL_READ = 0x04,
|
||||
IOCTLV_NET_SSL_WRITE = 0x05,
|
||||
IOCTLV_NET_SSL_SHUTDOWN = 0x06,
|
||||
IOCTLV_NET_SSL_SETCLIENTCERT = 0x07,
|
||||
IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08,
|
||||
IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09,
|
||||
IOCTLV_NET_SSL_SETROOTCA = 0x0A,
|
||||
IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B,
|
||||
IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C,
|
||||
IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D,
|
||||
IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E,
|
||||
IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F,
|
||||
IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14,
|
||||
IOCTLV_NET_SSL_DEBUGGETTIME = 0x15,
|
||||
};
|
||||
|
||||
enum ssl_err_t
|
||||
{
|
||||
SSL_OK = 0,
|
||||
SSL_ERR_FAILED = -1,
|
||||
SSL_ERR_RAGAIN = -2,
|
||||
SSL_ERR_WAGAIN = -3,
|
||||
SSL_ERR_SYSCALL = -5,
|
||||
SSL_ERR_ZERO = -6, // read or write returned 0
|
||||
SSL_ERR_CAGAIN = -7, // BIO not connected
|
||||
SSL_ERR_ID = -8, // invalid SSL id
|
||||
SSL_ERR_VCOMMONNAME = -9, // verify failed: common name
|
||||
SSL_ERR_VROOTCA = -10, // verify failed: root ca
|
||||
SSL_ERR_VCHAIN = -11, // verify failed: certificate chain
|
||||
SSL_ERR_VDATE = -12, // verify failed: date invalid
|
||||
SSL_ERR_SERVER_CERT = -13, // certificate cert invalid
|
||||
};
|
||||
|
||||
u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize);
|
||||
u32 ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer);
|
||||
|
|
|
@ -0,0 +1,615 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "WII_Socket.h"
|
||||
#include "WII_IPC_HLE.h"
|
||||
#include "WII_IPC_HLE_Device.h"
|
||||
|
||||
using WII_IPC_HLE_Interface::ECommandType;
|
||||
using WII_IPC_HLE_Interface::COMMAND_IOCTL;
|
||||
using WII_IPC_HLE_Interface::COMMAND_IOCTLV;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ERRORCODE(name) WSA ## name
|
||||
#define EITHER(win32, posix) win32
|
||||
#else
|
||||
#define ERRORCODE(name) name
|
||||
#define EITHER(win32, posix) posix
|
||||
#endif
|
||||
|
||||
char* WiiSockMan::DecodeError(s32 ErrorCode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
static char Message[1024];
|
||||
// If this program was multi-threaded, we'd want to use FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
// instead of a static buffer here.
|
||||
// (And of course, free the buffer when we were done with it)
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)Message, 1024, NULL);
|
||||
return Message;
|
||||
#else
|
||||
return strerror(ErrorCode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
s32 WiiSockMan::getNetErrorCode(s32 ret, std::string caller, bool isRW)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
s32 errorCode = WSAGetLastError();
|
||||
#else
|
||||
s32 errorCode = errno;
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
WARN_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d",
|
||||
caller.c_str(), errorCode, DecodeError(errorCode), ret);
|
||||
|
||||
switch (errorCode)
|
||||
{
|
||||
case ERRORCODE(EMSGSIZE):
|
||||
ERROR_LOG(WII_IPC_NET, "Find out why this happened, looks like PEEK failure?");
|
||||
return -1; // Should be -SO_EMSGSIZE
|
||||
case EITHER(WSAENOTSOCK, EBADF):
|
||||
return -SO_EBADF;
|
||||
case ERRORCODE(EADDRINUSE):
|
||||
return -SO_EADDRINUSE;
|
||||
case ERRORCODE(ECONNRESET):
|
||||
return -SO_ECONNRESET;
|
||||
case ERRORCODE(EISCONN):
|
||||
return -SO_EISCONN;
|
||||
case ERRORCODE(ENOTCONN):
|
||||
return -SO_EAGAIN; // After proper blocking SO_EAGAIN shouldn't be needed...
|
||||
case ERRORCODE(EINPROGRESS):
|
||||
return -SO_EINPROGRESS;
|
||||
case ERRORCODE(EALREADY):
|
||||
return -SO_EALREADY;
|
||||
case ERRORCODE(EACCES):
|
||||
return -SO_EACCES;
|
||||
case EITHER(WSAEWOULDBLOCK, EAGAIN):
|
||||
if(isRW){
|
||||
return -SO_EAGAIN; // EAGAIN
|
||||
}else{
|
||||
return -SO_EINPROGRESS; // EINPROGRESS
|
||||
}
|
||||
// TODO: remove as this should no longer be a problem once blocking is supported.
|
||||
case EITHER(WSA_INVALID_HANDLE, EBADF):
|
||||
return -SO_EINPROGRESS; // EINPROGRESS
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WiiSocket::~WiiSocket()
|
||||
{
|
||||
if (fd >= 0)
|
||||
{
|
||||
(void)closeFd();
|
||||
}
|
||||
}
|
||||
|
||||
void WiiSocket::setFd(s32 s)
|
||||
{
|
||||
if (fd >= 0)
|
||||
(void)closeFd();
|
||||
|
||||
nonBlock = false;
|
||||
fd = s;
|
||||
|
||||
// TODO: Remove on completion of async
|
||||
#ifdef _WIN32
|
||||
u_long iMode = 1;
|
||||
int ioctlret = ioctlsocket(fd, FIONBIO, &iMode);
|
||||
u32 millis = 3000;
|
||||
#else
|
||||
int flags;
|
||||
if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
|
||||
flags = 0;
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
struct timeval millis;
|
||||
millis.tv_sec = 3;
|
||||
millis.tv_usec = 0;
|
||||
#endif
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&millis,sizeof(millis));
|
||||
}
|
||||
|
||||
s32 WiiSocket::closeFd()
|
||||
{
|
||||
s32 ReturnValue = 0;
|
||||
if (fd >= 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
s32 ret = closesocket(fd);
|
||||
#else
|
||||
s32 ret = close(sock);
|
||||
#endif
|
||||
ReturnValue = WiiSockMan::getNetErrorCode(ret, "delSocket", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnValue = WiiSockMan::getNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "delSocket", false);
|
||||
}
|
||||
fd = -1;
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
s32 WiiSocket::_connect(sockaddr_in* name, s32 namelen)
|
||||
{
|
||||
int ret = connect(fd, (sockaddr*)name, namelen);
|
||||
ret = WiiSockMan::getNetErrorCode(ret, "SO_CONNECT", false);
|
||||
|
||||
WARN_LOG(WII_IPC_NET,"IOCTL_SO_CONNECT (%08x, %s:%d)",
|
||||
fd, inet_ntoa(name->sin_addr), Common::swap16(name->sin_port));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 WiiSocket::_bind(sockaddr_in* name, s32 namelen)
|
||||
{
|
||||
int ret = bind(fd, (sockaddr*)name, namelen);
|
||||
ret = WiiSockMan::getNetErrorCode(ret, "SO_BIND", false);
|
||||
|
||||
WARN_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%08X %s:%d) = %d ", fd,
|
||||
inet_ntoa(name->sin_addr), Common::swap16(name->sin_port), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 WiiSocket::_fcntl(u32 cmd, u32 arg)
|
||||
{
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
#define F_NONBLOCK 4
|
||||
s32 ret = 0;
|
||||
if (cmd == F_GETFL)
|
||||
{
|
||||
ret = nonBlock ? F_NONBLOCK : 0;
|
||||
}
|
||||
else if (cmd == F_SETFL)
|
||||
{
|
||||
nonBlock = (arg & F_NONBLOCK) == F_NONBLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(WII_IPC_NET, "SO_FCNTL unknown command");
|
||||
}
|
||||
|
||||
WARN_LOG(WII_IPC_NET, "IOCTL_SO_FCNTL(%08x, %08X, %08X)",
|
||||
fd, cmd, arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WiiSocket::update(bool read, bool write, bool except)
|
||||
{
|
||||
auto it = pending_sockops.begin();
|
||||
while (it != pending_sockops.end())
|
||||
{
|
||||
s32 ReturnValue = 0;
|
||||
bool forceNonBlock = false;
|
||||
ECommandType ct = static_cast<ECommandType>(Memory::Read_U32(it->_CommandAddress));
|
||||
if (!it->is_ssl && ct == COMMAND_IOCTL)
|
||||
{
|
||||
u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10);
|
||||
switch(it->net_type)
|
||||
{
|
||||
case IOCTL_SO_FCNTL:
|
||||
{
|
||||
u32 cmd = Memory::Read_U32(BufferIn + 4);
|
||||
u32 arg = Memory::Read_U32(BufferIn + 8);
|
||||
ReturnValue = _fcntl(cmd, arg);
|
||||
break;
|
||||
}
|
||||
case IOCTL_SO_BIND:
|
||||
{
|
||||
//TODO: tidy
|
||||
bind_params *addr = (bind_params*)Memory::GetPointer(BufferIn);
|
||||
GC_sockaddr_in addrPC;
|
||||
memcpy(&addrPC, addr->name, sizeof(GC_sockaddr_in));
|
||||
sockaddr_in address;
|
||||
address.sin_family = addrPC.sin_family;
|
||||
address.sin_addr.s_addr = addrPC.sin_addr.s_addr_;
|
||||
address.sin_port = addrPC.sin_port;
|
||||
ReturnValue = _bind(&address, sizeof(address));
|
||||
break;
|
||||
}
|
||||
case IOCTL_SO_CONNECT:
|
||||
{
|
||||
|
||||
//struct sockaddr_in echoServAddr;
|
||||
u32 has_addr = Memory::Read_U32(BufferIn + 0x04);
|
||||
sockaddr_in serverAddr;
|
||||
|
||||
u8 addr[28];
|
||||
Memory::ReadBigEData(addr, BufferIn + 0x08, sizeof(addr));
|
||||
|
||||
if (has_addr != 1)
|
||||
{
|
||||
ReturnValue = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&serverAddr, 0, sizeof(serverAddr));
|
||||
memcpy(&serverAddr, addr, addr[0]);
|
||||
// GC/Wii sockets have a length param as well, we dont really care :)
|
||||
serverAddr.sin_family = serverAddr.sin_family >> 8;
|
||||
|
||||
ReturnValue = _connect(&serverAddr, sizeof(serverAddr));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Fix blocking error codes
|
||||
if (!nonBlock)
|
||||
{
|
||||
if (it->net_type == IOCTL_SO_CONNECT
|
||||
&& ReturnValue == -SO_EISCONN)
|
||||
{
|
||||
ReturnValue = SO_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ct == COMMAND_IOCTLV)
|
||||
{
|
||||
SIOCtlVBuffer CommandBuffer(it->_CommandAddress);
|
||||
u32 BufferIn = 0, BufferIn2 = 0;
|
||||
u32 BufferInSize = 0, BufferInSize2 = 0;
|
||||
u32 BufferOut = 0, BufferOut2 = 0;
|
||||
u32 BufferOutSize = 0, BufferOutSize2 = 0;
|
||||
|
||||
if (CommandBuffer.InBuffer.size() > 0)
|
||||
{
|
||||
BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
|
||||
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
|
||||
}
|
||||
|
||||
if (CommandBuffer.PayloadBuffer.size() > 0)
|
||||
{
|
||||
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
|
||||
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
|
||||
}
|
||||
|
||||
if (CommandBuffer.PayloadBuffer.size() > 1)
|
||||
{
|
||||
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
|
||||
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
|
||||
}
|
||||
|
||||
if (CommandBuffer.InBuffer.size() > 1)
|
||||
{
|
||||
BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
|
||||
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
|
||||
}
|
||||
|
||||
if (it->is_ssl)
|
||||
{
|
||||
int sslID = Memory::Read_U32(BufferOut) - 1;
|
||||
if (SSLID_VALID(sslID))
|
||||
{
|
||||
switch(it->ssl_type)
|
||||
{
|
||||
case IOCTLV_NET_SSL_DOHANDSHAKE:
|
||||
{
|
||||
|
||||
int ret = ssl_handshake(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx);
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
Memory::Write_U32(SSL_OK, BufferIn);
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_RAGAIN;
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_WAGAIN;
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||
break;
|
||||
}
|
||||
|
||||
WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) "
|
||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
|
||||
ret,
|
||||
BufferIn, BufferInSize, BufferIn2, BufferInSize2,
|
||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_WRITE:
|
||||
{
|
||||
int ret = ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferOut2), BufferOutSize2);
|
||||
|
||||
#ifdef DEBUG_SSL
|
||||
File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2);
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
{
|
||||
// Return bytes written or SSL_ERR_ZERO if none
|
||||
Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_RAGAIN;
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_WAGAIN;
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTLV_NET_SSL_READ:
|
||||
{
|
||||
int ret = ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx, Memory::GetPointer(BufferIn2), BufferInSize2);
|
||||
#ifdef DEBUG_SSL
|
||||
if (ret > 0)
|
||||
{
|
||||
File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(_BufferIn2), ret);
|
||||
}
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
{
|
||||
// Return bytes read or SSL_ERR_ZERO if none
|
||||
Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case POLARSSL_ERR_NET_WANT_READ:
|
||||
Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_RAGAIN;
|
||||
break;
|
||||
case POLARSSL_ERR_NET_WANT_WRITE:
|
||||
Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
|
||||
if (!nonBlock)
|
||||
ReturnValue = SSL_ERR_WAGAIN;
|
||||
break;
|
||||
default:
|
||||
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory::Write_U32(SSL_ERR_ID, BufferIn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (it->net_type)
|
||||
{
|
||||
case IOCTLV_SO_SENDTO:
|
||||
{
|
||||
|
||||
char * data = (char*)Memory::GetPointer(BufferIn);
|
||||
u32 flags = Common::swap32(BufferIn2 + 0x04);
|
||||
u32 has_destaddr = Common::swap32(BufferIn2 + 0x08);
|
||||
// Act as non blocking when SO_MSG_NONBLOCK is specified
|
||||
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
|
||||
|
||||
// send/sendto only handles PEEK
|
||||
flags &= SO_MSG_PEEK | SO_MSG_OOB;
|
||||
|
||||
u8 destaddr[28];
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)&destaddr;
|
||||
if (has_destaddr)
|
||||
{
|
||||
Memory::ReadBigEData((u8*)&destaddr, BufferIn2 + 0x0C, BufferInSize2 - 0x0C);
|
||||
addr->sin_family = addr->sin_family >> 8;
|
||||
}
|
||||
|
||||
int ret = sendto(fd, data, BufferInSize, flags,
|
||||
has_destaddr ? (struct sockaddr*)addr : NULL,
|
||||
has_destaddr ? sizeof(sockaddr) : 0);
|
||||
ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_SENDTO", true);
|
||||
|
||||
WARN_LOG(WII_IPC_NET,
|
||||
"%s = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u",
|
||||
has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ",
|
||||
ReturnValue, fd, BufferIn, BufferInSize,
|
||||
BufferIn2, BufferInSize2,
|
||||
addr->sin_addr.s_addr & 0xFF,
|
||||
(addr->sin_addr.s_addr >> 8) & 0xFF,
|
||||
(addr->sin_addr.s_addr >> 16) & 0xFF,
|
||||
(addr->sin_addr.s_addr >> 24) & 0xFF
|
||||
);
|
||||
break;
|
||||
}
|
||||
case IOCTLV_SO_RECVFROM:
|
||||
{
|
||||
u32 sock = Memory::Read_U32(BufferIn);
|
||||
u32 flags = Memory::Read_U32(BufferIn + 4);
|
||||
|
||||
char *buf = (char *)Memory::GetPointer(BufferOut);
|
||||
int len = BufferOutSize;
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(sockaddr_in));
|
||||
socklen_t fromlen = 0;
|
||||
|
||||
if (BufferOutSize2 != 0)
|
||||
{
|
||||
fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr);
|
||||
}
|
||||
|
||||
// Act as non blocking when SO_MSG_NONBLOCK is specified
|
||||
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
|
||||
|
||||
// recv/recvfrom only handles PEEK
|
||||
flags &= SO_MSG_PEEK | SO_MSG_OOB;
|
||||
#ifdef _WIN32
|
||||
if(flags & MSG_PEEK){
|
||||
unsigned long totallen = 0;
|
||||
ioctlsocket(sock, FIONREAD, &totallen);
|
||||
ReturnValue = totallen;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
int ret = recvfrom(sock, buf, len, flags,
|
||||
fromlen ? (struct sockaddr*) &addr : NULL,
|
||||
fromlen ? &fromlen : 0);
|
||||
ReturnValue = WiiSockMan::getNetErrorCode(ret, fromlen ? "SO_RECVFROM" : "SO_RECV", true);
|
||||
|
||||
|
||||
WARN_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, "
|
||||
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
|
||||
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
|
||||
fromlen ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ",
|
||||
ReturnValue, buf, sock, flags,
|
||||
BufferIn, BufferInSize, BufferIn2, BufferInSize2,
|
||||
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2);
|
||||
|
||||
if (BufferOutSize2 != 0)
|
||||
{
|
||||
addr.sin_family = (addr.sin_family << 8) | (BufferOutSize2&0xFF);
|
||||
Memory::WriteBigEData((u8*)&addr, BufferOut2, BufferOutSize2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( nonBlock || forceNonBlock
|
||||
|| (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS && ReturnValue != -SO_EALREADY)
|
||||
|| (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN))
|
||||
{
|
||||
WARN_LOG(WII_IPC_NET, "IOCTL(V) Sock: %d ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d",
|
||||
fd, it->is_ssl ? it->ssl_type : it->net_type, ReturnValue, nonBlock, forceNonBlock);
|
||||
WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue);
|
||||
it = pending_sockops.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiiSocket::doSock(u32 _CommandAddress, NET_IOCTL type)
|
||||
{
|
||||
sockop so = {_CommandAddress, false};
|
||||
so.net_type = type;
|
||||
pending_sockops.push_back(so);
|
||||
}
|
||||
|
||||
void WiiSocket::doSock(u32 _CommandAddress, SSL_IOCTL type)
|
||||
{
|
||||
sockop so = {_CommandAddress, true};
|
||||
so.ssl_type = type;
|
||||
pending_sockops.push_back(so);
|
||||
}
|
||||
|
||||
s32 WiiSockMan::newSocket(s32 af, s32 type, s32 protocol)
|
||||
{
|
||||
s32 s = (s32)socket(af, type, protocol);
|
||||
s32 ret = getNetErrorCode(s, "newSocket", false);
|
||||
if (ret >= 0)
|
||||
{
|
||||
WiiSocket& sock = WiiSockets[ret];
|
||||
sock.setFd(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 WiiSockMan::delSocket(s32 s)
|
||||
{
|
||||
s32 ReturnValue = WiiSockets[s].closeFd();
|
||||
WiiSockets.erase(s);
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
void WiiSockMan::Update()
|
||||
{
|
||||
s32 nfds = 0;
|
||||
fd_set read_fds, write_fds, except_fds;
|
||||
struct timeval t = {0,0};
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&except_fds);
|
||||
for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it)
|
||||
{
|
||||
WiiSocket& sock = it->second;
|
||||
if (sock.valid())
|
||||
{
|
||||
FD_SET(sock.fd, &read_fds);
|
||||
FD_SET(sock.fd, &write_fds);
|
||||
FD_SET(sock.fd, &except_fds);
|
||||
nfds = max(nfds, sock.fd+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Good time to clean up invalid sockets.
|
||||
WiiSockets.erase(sock.fd);
|
||||
}
|
||||
}
|
||||
s32 ret = select(nfds, &read_fds, &write_fds, &except_fds, &t);
|
||||
|
||||
if(ret >= 0)
|
||||
{
|
||||
for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it)
|
||||
{
|
||||
WiiSocket& sock = it->second;
|
||||
sock.update(
|
||||
FD_ISSET(sock.fd, &read_fds) != 0,
|
||||
FD_ISSET(sock.fd, &write_fds) != 0,
|
||||
FD_ISSET(sock.fd, &except_fds) != 0
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto it = WiiSockets.begin(); it != WiiSockets.end(); ++it)
|
||||
{
|
||||
it->second.update(false, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue)
|
||||
{
|
||||
Memory::Write_U32(8, CommandAddress);
|
||||
// IOS seems to write back the command that was responded to
|
||||
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
|
||||
|
||||
// Return value
|
||||
Memory::Write_U32(ReturnValue, CommandAddress + 4);
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
|
||||
}
|
||||
|
||||
|
||||
#undef ERRORCODE
|
||||
#undef EITHER
|
|
@ -0,0 +1,214 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _WII_SOCKET_H_
|
||||
#define _WII_SOCKET_H_
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include "fakepoll.h"
|
||||
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||
|
||||
#elif defined(__linux__) or defined(__APPLE__)
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct pollfd pollfd_t;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm> // std::for_each
|
||||
#include <unordered_map>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "WII_IPC_HLE.h"
|
||||
#include "WII_IPC_HLE_Device_net.h"
|
||||
#include "WII_IPC_HLE_Device_net_ssl.h"
|
||||
|
||||
enum {
|
||||
SO_MSG_OOB = 0x01,
|
||||
SO_MSG_PEEK = 0x02,
|
||||
SO_MSG_NONBLOCK = 0x04,
|
||||
};
|
||||
enum {
|
||||
SO_SUCCESS,
|
||||
SO_E2BIG = 1,
|
||||
SO_EACCES,
|
||||
SO_EADDRINUSE,
|
||||
SO_EADDRNOTAVAIL,
|
||||
SO_EAFNOSUPPORT,
|
||||
SO_EAGAIN,
|
||||
SO_EALREADY,
|
||||
SO_EBADF,
|
||||
SO_EBADMSG,
|
||||
SO_EBUSY,
|
||||
SO_ECANCELED,
|
||||
SO_ECHILD,
|
||||
SO_ECONNABORTED,
|
||||
SO_ECONNREFUSED,
|
||||
SO_ECONNRESET,
|
||||
SO_EDEADLK,
|
||||
SO_EDESTADDRREQ,
|
||||
SO_EDOM,
|
||||
SO_EDQUOT,
|
||||
SO_EEXIST,
|
||||
SO_EFAULT,
|
||||
SO_EFBIG,
|
||||
SO_EHOSTUNREACH,
|
||||
SO_EIDRM,
|
||||
SO_EILSEQ,
|
||||
SO_EINPROGRESS,
|
||||
SO_EINTR,
|
||||
SO_EINVAL,
|
||||
SO_EIO,
|
||||
SO_EISCONN,
|
||||
SO_EISDIR,
|
||||
SO_ELOOP,
|
||||
SO_EMFILE,
|
||||
SO_EMLINK,
|
||||
SO_EMSGSIZE,
|
||||
SO_EMULTIHOP,
|
||||
SO_ENAMETOOLONG,
|
||||
SO_ENETDOWN,
|
||||
SO_ENETRESET,
|
||||
SO_ENETUNREACH,
|
||||
SO_ENFILE,
|
||||
SO_ENOBUFS,
|
||||
SO_ENODATA,
|
||||
SO_ENODEV,
|
||||
SO_ENOENT,
|
||||
SO_ENOEXEC,
|
||||
SO_ENOLCK,
|
||||
SO_ENOLINK,
|
||||
SO_ENOMEM,
|
||||
SO_ENOMSG,
|
||||
SO_ENOPROTOOPT,
|
||||
SO_ENOSPC,
|
||||
SO_ENOSR,
|
||||
SO_ENOSTR,
|
||||
SO_ENOSYS,
|
||||
SO_ENOTCONN,
|
||||
SO_ENOTDIR,
|
||||
SO_ENOTEMPTY,
|
||||
SO_ENOTSOCK,
|
||||
SO_ENOTSUP,
|
||||
SO_ENOTTY,
|
||||
SO_ENXIO,
|
||||
SO_EOPNOTSUPP,
|
||||
SO_EOVERFLOW,
|
||||
SO_EPERM,
|
||||
SO_EPIPE,
|
||||
SO_EPROTO,
|
||||
SO_EPROTONOSUPPORT,
|
||||
SO_EPROTOTYPE,
|
||||
SO_ERANGE,
|
||||
SO_EROFS,
|
||||
SO_ESPIPE,
|
||||
SO_ESRCH,
|
||||
SO_ESTALE,
|
||||
SO_ETIME,
|
||||
SO_ETIMEDOUT,
|
||||
SO_ETXTBSY,
|
||||
SO_EXDEV
|
||||
};
|
||||
|
||||
class WiiSocket
|
||||
{
|
||||
struct sockop{
|
||||
u32 _CommandAddress;
|
||||
bool is_ssl;
|
||||
union
|
||||
{
|
||||
NET_IOCTL net_type;
|
||||
SSL_IOCTL ssl_type;
|
||||
};
|
||||
};
|
||||
private:
|
||||
s32 fd;
|
||||
bool nonBlock;
|
||||
std::list<sockop> pending_sockops;
|
||||
|
||||
friend class WiiSockMan;
|
||||
void setFd(s32 s);
|
||||
s32 closeFd();
|
||||
s32 _fcntl(u32 cmd, u32 arg);
|
||||
s32 _bind(sockaddr_in* name, s32 namelen);
|
||||
s32 _connect(sockaddr_in* name, s32 namelen);
|
||||
|
||||
void doSock(u32 _CommandAddress, NET_IOCTL type);
|
||||
void doSock(u32 _CommandAddress, SSL_IOCTL type);
|
||||
void update(bool read, bool write, bool except);
|
||||
bool valid() {return fd >= 0;}
|
||||
public:
|
||||
WiiSocket() : fd(-1), nonBlock(false) {}
|
||||
~WiiSocket();
|
||||
void operator=(WiiSocket const&); // Don't implement
|
||||
|
||||
};
|
||||
|
||||
class WiiSockMan
|
||||
{
|
||||
public:
|
||||
static s32 getNetErrorCode(s32 ret, std::string caller, bool isRW);
|
||||
static char* DecodeError(s32 ErrorCode);
|
||||
|
||||
static WiiSockMan& getInstance()
|
||||
{
|
||||
static WiiSockMan instance; // Guaranteed to be destroyed.
|
||||
return instance; // Instantiated on first use.
|
||||
}
|
||||
void Update();
|
||||
static void EnqueueReply(u32 CommandAddress, s32 ReturnValue);
|
||||
|
||||
// NON-BLOCKING FUNCTIONS
|
||||
s32 newSocket(s32 af, s32 type, s32 protocol);
|
||||
s32 delSocket(s32 s);
|
||||
|
||||
template <typename T>
|
||||
void doSock(s32 sock, u32 CommandAddress, T type)
|
||||
{
|
||||
if (WiiSockets.find(sock) == WiiSockets.end())
|
||||
{
|
||||
ERROR_LOG(WII_IPC_NET,
|
||||
"doSock: Error, fd not found (%08x, %08X, %08X)",
|
||||
sock, CommandAddress, type);
|
||||
EnqueueReply(CommandAddress, -SO_EBADF);
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiSockets[sock].doSock(CommandAddress, type);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
WiiSockMan() {}; // Constructor? (the {} brackets) are needed here.
|
||||
WiiSockMan(WiiSockMan const&); // Don't Implement
|
||||
void operator=(WiiSockMan const&); // Don't implement
|
||||
|
||||
std::unordered_map<s32, WiiSocket> WiiSockets;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue