mirror of
https://github.com/wiiu-env/MochaLite.git
synced 2024-11-01 02:25:10 +01:00
240 lines
4.5 KiB
C
240 lines
4.5 KiB
C
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include "imports.h"
|
||
|
#include "net_ifmgr_ncl.h"
|
||
|
#include "socket.h"
|
||
|
#include "fsa.h"
|
||
|
#include "svc.h"
|
||
|
#include "text.h"
|
||
|
#include "logger.h"
|
||
|
#include "ipc.h"
|
||
|
|
||
|
static bool serverKilled;
|
||
|
|
||
|
// overwrites command_buffer with response
|
||
|
// returns length of response (or 0 for no response, negative for error)
|
||
|
int serverCommandHandler(u32* command_buffer, u32 length)
|
||
|
{
|
||
|
if(!command_buffer || !length) return -1;
|
||
|
|
||
|
int out_length = 4;
|
||
|
|
||
|
switch(command_buffer[0])
|
||
|
{
|
||
|
case 0:
|
||
|
// write
|
||
|
// [cmd_id][addr]
|
||
|
{
|
||
|
void* dst = (void*)command_buffer[1];
|
||
|
|
||
|
memcpy(dst, &command_buffer[2], length - 8);
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
// read
|
||
|
// [cmd_id][addr][length]
|
||
|
{
|
||
|
void* src = (void*)command_buffer[1];
|
||
|
length = command_buffer[2];
|
||
|
|
||
|
memcpy(&command_buffer[1], src, length);
|
||
|
out_length = length + 4;
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
// svc
|
||
|
// [cmd_id][svc_id]
|
||
|
{
|
||
|
int svc_id = command_buffer[1];
|
||
|
int size_arguments = length - 8;
|
||
|
|
||
|
u32 arguments[8];
|
||
|
memset(arguments, 0x00, sizeof(arguments));
|
||
|
memcpy(arguments, &command_buffer[2], (size_arguments < 8 * 4) ? size_arguments : (8 * 4));
|
||
|
|
||
|
// return error code as data
|
||
|
out_length = 8;
|
||
|
command_buffer[1] = ((int (*const)(u32, u32, u32, u32, u32, u32, u32, u32))(MCP_SVC_BASE + svc_id * 8))(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
|
||
|
}
|
||
|
break;
|
||
|
case 3:
|
||
|
// kill
|
||
|
// [cmd_id]
|
||
|
{
|
||
|
serverKilled = true;
|
||
|
}
|
||
|
break;
|
||
|
case 4:
|
||
|
// memcpy
|
||
|
// [dst][src][size]
|
||
|
{
|
||
|
void* dst = (void*)command_buffer[1];
|
||
|
void* src = (void*)command_buffer[2];
|
||
|
int size = command_buffer[3];
|
||
|
|
||
|
memcpy(dst, src, size);
|
||
|
}
|
||
|
break;
|
||
|
case 5:
|
||
|
// repeated-write
|
||
|
// [address][value][n]
|
||
|
{
|
||
|
u32* dst = (u32*)command_buffer[1];
|
||
|
u32* cache_range = (u32*)(command_buffer[1] & ~0xFF);
|
||
|
u32 value = command_buffer[2];
|
||
|
u32 n = command_buffer[3];
|
||
|
|
||
|
u32 old = *dst;
|
||
|
int i;
|
||
|
for(i = 0; i < n; i++)
|
||
|
{
|
||
|
if(*dst != old)
|
||
|
{
|
||
|
if(*dst == 0x0) old = *dst;
|
||
|
else
|
||
|
{
|
||
|
*dst = value;
|
||
|
svcFlushDCache(cache_range, 0x100);
|
||
|
break;
|
||
|
}
|
||
|
}else
|
||
|
{
|
||
|
svcInvalidateDCache(cache_range, 0x100);
|
||
|
usleep(50);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
// unknown command
|
||
|
return -2;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// no error !
|
||
|
command_buffer[0] = 0x00000000;
|
||
|
return out_length;
|
||
|
}
|
||
|
|
||
|
void serverClientHandler(int sock)
|
||
|
{
|
||
|
u32 command_buffer[0x180];
|
||
|
|
||
|
while(!serverKilled)
|
||
|
{
|
||
|
int ret = recv(sock, command_buffer, sizeof(command_buffer), 0);
|
||
|
|
||
|
if(ret <= 0) break;
|
||
|
|
||
|
ret = serverCommandHandler(command_buffer, ret);
|
||
|
|
||
|
if(ret > 0)
|
||
|
{
|
||
|
send(sock, command_buffer, ret, 0);
|
||
|
}else if(ret < 0)
|
||
|
{
|
||
|
send(sock, &ret, sizeof(int), 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
closesocket(sock);
|
||
|
}
|
||
|
|
||
|
void serverListenClients()
|
||
|
{
|
||
|
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
||
|
struct sockaddr_in server;
|
||
|
|
||
|
memset(&server, 0x00, sizeof(server));
|
||
|
|
||
|
server.sin_family = AF_INET;
|
||
|
server.sin_port = 1337;
|
||
|
server.sin_addr.s_addr = 0;
|
||
|
|
||
|
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
|
||
|
{
|
||
|
closesocket(sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(listen(sock, 1) < 0)
|
||
|
{
|
||
|
closesocket(sock);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while(!serverKilled)
|
||
|
{
|
||
|
int csock = accept(sock, NULL, NULL);
|
||
|
if(csock < 0)
|
||
|
break;
|
||
|
|
||
|
serverClientHandler(csock);
|
||
|
}
|
||
|
|
||
|
closesocket(sock);
|
||
|
}
|
||
|
|
||
|
int _main(void *arg)
|
||
|
{
|
||
|
while(ifmgrnclInit() <= 0)
|
||
|
{
|
||
|
//print(0, 0, "opening /dev/net/ifmgr/ncl...");
|
||
|
usleep(1000);
|
||
|
}
|
||
|
|
||
|
while(true)
|
||
|
{
|
||
|
u16 out0, out1;
|
||
|
|
||
|
int ret0 = IFMGRNCL_GetInterfaceStatus(0, &out0);
|
||
|
if(!ret0 && out0 == 1) break;
|
||
|
|
||
|
int ret1 = IFMGRNCL_GetInterfaceStatus(1, &out1);
|
||
|
if(!ret1 && out1 == 1) break;
|
||
|
|
||
|
//print(0, 0, "initializing /dev/net/ifmgr/ncl... %08X %08X %08X %08X ", ret0, ret1, out0, out1);
|
||
|
|
||
|
usleep(1000);
|
||
|
}
|
||
|
|
||
|
while(socketInit() <= 0)
|
||
|
{
|
||
|
//print(0, 0, "opening /dev/socket...");
|
||
|
usleep(1000);
|
||
|
}
|
||
|
|
||
|
log_init(0xC0A8B203);
|
||
|
|
||
|
//print(0, 0, "opened /dev/socket !");
|
||
|
usleep(5*1000*1000);
|
||
|
//print(0, 10, "attempting sockets !");
|
||
|
|
||
|
serverKilled = false;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
if(!serverKilled)
|
||
|
{
|
||
|
serverListenClients();
|
||
|
}
|
||
|
usleep(1000*1000);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void _startMainThread(void)
|
||
|
{
|
||
|
drawSplashScreen();
|
||
|
|
||
|
memset((void*)0x050BD000, 0, 0x3000);
|
||
|
|
||
|
int threadId = svcCreateThread(_main, 0, (u32*)(0x050BD000 + 0x1000), 0x1000, 0x78, 1);
|
||
|
if(threadId >= 0)
|
||
|
svcStartThread(threadId);
|
||
|
|
||
|
ipc_init();
|
||
|
}
|