Simplified the code by using the TCPServer from libutils

This commit is contained in:
Maschell 2018-03-07 18:42:36 +01:00
parent bb4484645a
commit 975af132dc
8 changed files with 352 additions and 468 deletions

View File

@ -528,14 +528,14 @@ void ControllerPatcher::startNetworkServer(){
if(!gNetworkControllerActivated) return;
DEBUG_FUNCTION_LINE("statedNetworkServer! \n");
UDPServer::getInstance();
TCPServer::getInstance();
CPTCPServer::getInstance();
}
void ControllerPatcher::stopNetworkServer(){
DEBUG_FUNCTION_LINE("called! \n");
UDPServer::destroyInstance();
UDPClient::destroyInstance();
TCPServer::destroyInstance();
CPTCPServer::destroyInstance();
}
void ControllerPatcher::DeInit(){
@ -734,7 +734,7 @@ HID_Mouse_Data * ControllerPatcher::getMouseData(){
HID_Mouse_Data * result = NULL;
for(s32 i;i<HID_MAX_DEVICES_PER_SLOT;i++){
for(s32 i = 0;i<HID_MAX_DEVICES_PER_SLOT;i++){
ControllerMappingPADInfo * padinfo = &(CMPAD->pad_infos[i]);
if(!padinfo->active){
break;

View File

@ -36,10 +36,8 @@
#include "./config/ConfigValues.hpp"
#include "./config/ConfigParser.hpp"
#include "./network/ControllerPatcherNet.hpp"
#include "./network/TCPServer.hpp"
#include "./network/CPTCPServer.hpp"
#include "./network/UDPServer.hpp"
#include "./network/UDPClient.hpp"
#endif /* _CONTROLLER_PATCHER_INCLUDES_H_ */

View File

@ -0,0 +1,314 @@
/****************************************************************************
* Copyright (C) 2016-2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "CPTCPServer.hpp"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <utils/logger.h>
#define wiiu_errno (*__gh_errno_ptr())
CPTCPServer * CPTCPServer::instance = NULL;
CPTCPServer::CPTCPServer(s32 port): TCPServer(port,CPTCPServer::getPriority()) {
CPTCPServer::AttachDetach(DETACH);
}
CPTCPServer::~CPTCPServer() {
CPTCPServer::AttachDetach(DETACH);
}
void CPTCPServer::AttachDetach(s32 attach) {
if(HID_DEBUG) {
if(attach) {
DEBUG_FUNCTION_LINE("Network Attach\n");
} else {
DEBUG_FUNCTION_LINE("Network Detach\n");
}
}
for(s32 i= 0; i< gHIDMaxDevices; i++) {
for(s32 j= 0; j< HID_MAX_PADS_COUNT; j++) {
if(gNetworkController[i][j][NETWORK_CONTROLLER_ACTIVE] > 0) {
DEBUG_FUNCTION_LINE("Found a registered pad in deviceslot %d and padslot %d! Lets detach it.\n",i,j);
HIDDevice device;
memset(&device,0,sizeof(device));
device.interface_index = 0;
device.vid = gNetworkController[i][j][NETWORK_CONTROLLER_VID];
device.pid = gNetworkController[i][j][NETWORK_CONTROLLER_PID];
device.handle = gNetworkController[i][j][NETWORK_CONTROLLER_HANDLE];
device.max_packet_size_rx = 8;
ControllerPatcherHID::externAttachDetachCallback(&device,attach);
memset(gNetworkController[i][j],0,sizeof(gNetworkController[i][j]));
}
}
}
if(HID_DEBUG) {
if(attach) {
DEBUG_FUNCTION_LINE("Network Attach DONE!\n");
} else {
DEBUG_FUNCTION_LINE("Network Detach DONE!\n");
}
}
}
void CPTCPServer::DetachAndDelete() {
CPTCPServer::AttachDetach(DETACH);
memset(&gNetworkController,0,sizeof(gNetworkController));
}
bool CPTCPServer::whileLoop() {
s32 ret;
s32 clientfd = getClientFD();
while (1) {
if(shouldExit()) {
break;
}
ret = checkbyte(clientfd);
if (ret < 0) {
if(wiiu_errno != 6) {
return false;
}
os_usleep(1000);
continue;
}
//DEBUG_FUNCTION_LINE("got byte from tcp! %01X\n",ret);
switch (ret) {
case WIIU_CP_TCP_ATTACH: { /*attach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1) {
s32 handle;
ret = recvwait(clientfd, &handle, 4);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: recvwait handle\n",WIIU_CP_TCP_ATTACH);
return false;
}
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("got handle %d\n",handle);
}
u16 vid = 0;
u16 pid = 0;
ret = recvwait(clientfd, &vid, 2);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: recvwait vid\n",WIIU_CP_TCP_ATTACH);
return false;
}
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("got vid %04X\n",vid);
}
ret = recvwait(clientfd, &pid, 2);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: recvwait pid\n",WIIU_CP_TCP_ATTACH);
return false;
}
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("got pid %04X\n",pid);
}
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vid);
device.pid = SWAP16(pid);
device.max_packet_size_rx = 8;
my_cb_user * user = NULL;
ControllerPatcherHID::externAttachDetachCallback(&device,1);
if((ret = ControllerPatcherUtils::getDataByHandle(handle,&user)) < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: getDataByHandle(%d,%08X).\n",WIIU_CP_TCP_ATTACH,handle,&user);
DEBUG_FUNCTION_LINE("Error in %02X: Config for the controller is missing.\n",WIIU_CP_TCP_ATTACH);
if((ret = sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND) < 0)) {
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
}
return false;
}
if((ret = sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_FOUND) < 0)) {
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_FOUND byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return false;
}
if(user != NULL) {
if((ret = sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_OKAY) < 0)) {
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_OKAY byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return false;
}
ret = sendwait(clientfd,&user->slotdata.deviceslot,2);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: sendwait slotdata: %04X\n",WIIU_CP_TCP_ATTACH,user->slotdata.deviceslot);
return false;
}
ret = sendwait(clientfd,&user->pad_slot,1);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: sendwait pad_slot: %04X\n",WIIU_CP_TCP_ATTACH,user->pad_slot);
return false;
}
} else {
DEBUG_FUNCTION_LINE("Error in %02X: invalid user data.\n",WIIU_CP_TCP_ATTACH);
if((ret = sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_BAD) < 0)) {
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_BAD byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return false;
}
return false;
break;
}
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("attachted to device slot: %d , pad slot is: %d\n",user->slotdata.deviceslot,user->pad_slot);
}
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_VID] = device.vid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_PID] = device.pid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_ACTIVE] = 1;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_HANDLE] = handle;
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("handle %d connected! vid: %02X pid: %02X deviceslot %d, padslot %d\n",handle,vid,pid,user->slotdata.deviceslot,user->pad_slot);
}
break;
}
break;
}
case WIIU_CP_TCP_DETACH: { /*detach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1) {
s32 handle;
ret = recvwait(clientfd, &handle, 4);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: recvwait handle\n",WIIU_CP_TCP_DETACH);
return false;
break;
}
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("got detach for handle: %d\n",handle);
}
my_cb_user * user = NULL;
if(ControllerPatcherUtils::getDataByHandle(handle,&user) < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: getDataByHandle(%d,%08X).\n",WIIU_CP_TCP_DETACH,handle,&user);
return false;
break;
}
if(user == NULL) {
DEBUG_FUNCTION_LINE("Error in %02X: invalid user data.\n",WIIU_CP_TCP_DETACH);
return false;
break;
}
s32 deviceslot = user->slotdata.deviceslot;
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("device slot is: %d , pad slot is: %d\n",deviceslot,user->pad_slot);
}
DeviceVIDPIDInfo vidpid;
s32 result;
if((result = ControllerPatcherUtils::getVIDPIDbyDeviceSlot(deviceslot,&vidpid)) < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: Couldn't find a valid VID/PID for device slot %d. Error: %d\n",WIIU_CP_TCP_DETACH,deviceslot,ret);
return false;
break;
}
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vidpid.vid);
device.pid = SWAP16(vidpid.pid);
device.max_packet_size_rx = 14;
ControllerPatcherHID::externAttachDetachCallback(&device,DETACH);
memset(gNetworkController[deviceslot][user->pad_slot],0,sizeof(gNetworkController[deviceslot][user->pad_slot]));
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("handle %d disconnected!\n",handle);
}
break;
}
break;
}
case WIIU_CP_TCP_PING: { /*ping*/
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1) {
if(HID_DEBUG) {
DEBUG_FUNCTION_LINE("Got Ping, sending now a Pong\n");
}
s32 ret = sendbyte(clientfd, WIIU_CP_TCP_PONG);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error in %02X: sendbyte PONG\n");
return false;
}
break;
}
break;
}
default:
return false;
break;
}
}
return true;
}
bool CPTCPServer::acceptConnection() {
s32 clientfd = getClientFD();
DEBUG_FUNCTION_LINE("TCP Connection accepted! Sending my protocol version: %d (0x%02X)\n", (WIIU_CP_TCP_HANDSHAKE - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,WIIU_CP_TCP_HANDSHAKE);
gUDPClientip = getSockAddr().sin_addr.s_addr;
UDPClient::createInstance();
s32 ret;
ret = sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE); //Hey I'm a WiiU console!
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error sendbyte: %02X\n",WIIU_CP_TCP_HANDSHAKE);
return false;
}
u8 clientProtocolVersion = recvbyte(clientfd);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error recvbyte: %02X\n",WIIU_CP_TCP_HANDSHAKE);
return false;
}
if(clientProtocolVersion == WIIU_CP_TCP_HANDSHAKE_ABORT) {
DEBUG_FUNCTION_LINE("The network client wants to abort.\n");
return false;
}
DEBUG_FUNCTION_LINE("received protocol version: %d (0x%02X)\n",(clientProtocolVersion - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,clientProtocolVersion);
if(clientProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_MIN && clientProtocolVersion <= WIIU_CP_TCP_HANDSHAKE_VERSION_MAX) {
DEBUG_FUNCTION_LINE("We support this protocol version. Let's confirm it to the network client.\n");
gUsedProtocolVersion = clientProtocolVersion;
ret = sendbyte(clientfd, clientProtocolVersion);
if(ret < 0) {
DEBUG_FUNCTION_LINE("Error sendbyte: %02X\n",clientProtocolVersion);
return false;
}
} else {
DEBUG_FUNCTION_LINE("We don't support this protocol version. We need to abort =(.\n");
ret = sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE_ABORT);
return false;
}
DEBUG_FUNCTION_LINE("Handshake done! Success!\n");
return true;
}
void CPTCPServer::onConnectionClosed() {
gUDPClientip = 0;
UDPClient::destroyInstance();
CPTCPServer::DetachAndDelete(); //Clear connected controller
}

View File

@ -14,13 +14,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _TCPSERVER_WINDOW_H_
#define _TCPSERVER_WINDOW_H_
#ifndef _CP_TCPSERVER_WINDOW_H_
#define _CP_TCPSERVER_WINDOW_H_
#include "../ControllerPatcherIncludes.hpp"
#include <dynamic_libs/socket_functions.h>
#include <dynamic_libs/os_functions.h>
#include <utils/TCPServer.hpp>
#include <utils/net.h>
#define WIIU_CP_TCP_HANDSHAKE WIIU_CP_TCP_HANDSHAKE_VERSION_3
@ -48,13 +50,15 @@
#define DEFAULT_TCP_PORT 8112
class TCPServer{
class CPTCPServer: TCPServer{
friend class ControllerPatcher;
private:
static TCPServer *getInstance() {
if(!instance)
instance = new TCPServer(DEFAULT_TCP_PORT);
static CPTCPServer *getInstance() {
if(!instance){
instance = new CPTCPServer(DEFAULT_TCP_PORT);
}
return instance;
}
@ -65,29 +69,37 @@ private:
}
}
TCPServer(s32 port);
~TCPServer();
static s32 getPriority(){
s32 priority = 28;
if(OSGetTitleID() == 0x00050000101c9300 || //The Legend of Zelda Breath of the Wild JPN
OSGetTitleID() == 0x00050000101c9400 || //The Legend of Zelda Breath of the Wild USA
OSGetTitleID() == 0x00050000101c9500 || //The Legend of Zelda Breath of the Wild EUR
OSGetTitleID() == 0x00050000101c9b00 || //The Binding of Isaac: Rebirth EUR
OSGetTitleID() == 0x00050000101a3c00){ //The Binding of Isaac: Rebirth USA
priority = 10;
DEBUG_FUNCTION_LINE("This game needs higher thread priority. We set it to %d\n",priority);
}
return priority;
}
void CloseSockets();
void ErrorHandling();
CPTCPServer(s32 port);
virtual ~CPTCPServer();
void StartTCPThread(TCPServer * server);
static void DoTCPThread(CThread *thread, void *arg);
void DoTCPThreadInternal();
static void DetachConnectedNetworkController();
static void AttachDetach(s32 attach);
void DetachAndDelete();
static TCPServer *instance;
s32 RunTCP();
virtual void DetachAndDelete();
struct sockaddr_in sock_addr;
volatile s32 sockfd = -1;
volatile s32 clientfd = -1;
virtual bool whileLoop();
virtual bool acceptConnection();
virtual void onConnectionClosed();
static CPTCPServer * instance;
volatile s32 exitThread = 0;
static CThread *pThread;
};
#endif //_TCPSERVER_WINDOW_H_

View File

@ -1,50 +0,0 @@
#include "ControllerPatcherNet.hpp"
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/socket_functions.h>
s32 ControllerPatcherNet::recvwait(s32 sock, void *buffer, s32 len) {
s32 ret;
while (len > 0) {
ret = recv(sock, buffer, len, 0);
if(ret < 0) return ret;
len -= ret;
buffer = (void *)(((char *) buffer) + ret);
}
return 0;
}
u8 ControllerPatcherNet::recvbyte(s32 sock) {
unsigned char buffer[1];
s32 ret;
ret = recvwait(sock, buffer, 1);
if (ret < 0) return ret;
return buffer[0];
}
s32 ControllerPatcherNet::checkbyte(s32 sock) {
unsigned char buffer[1];
s32 ret;
ret = recv(sock, buffer, 1, MSG_DONTWAIT);
if (ret < 0) return ret;
if (ret == 0) return -1;
return buffer[0];
}
s32 ControllerPatcherNet::sendwait(s32 sock, const void *buffer, s32 len) {
s32 ret;
while (len > 0) {
ret = send(sock, buffer, len, 0);
if(ret < 0) return ret;
len -= ret;
buffer = (void *)(((char *) buffer) + ret);
}
return 0;
}
s32 ControllerPatcherNet::sendbyte(s32 sock, unsigned char byte) {
unsigned char buffer[1];
buffer[0] = byte;
return sendwait(sock, buffer, 1);
}

View File

@ -1,17 +0,0 @@
#ifndef _CONTROLLERPATCHERNET_H_
#define _CONTROLLERPATCHERNET_H_
#include <dynamic_libs/os_types.h>
class ControllerPatcherNet{
friend class TCPServer;
friend class UDPServer;
private:
static s32 recvwait(s32 sock, void *buffer, s32 len);
static u8 recvbyte(s32 sock);
static s32 checkbyte(s32 sock);
static s32 sendwait(s32 sock, const void *buffer, s32 len);
static s32 sendbyte(s32 sock, unsigned char byte);
};
#endif

View File

@ -1,373 +0,0 @@
/****************************************************************************
* Copyright (C) 2016,2017 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "TCPServer.hpp"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <utils/logger.h>
#define wiiu_errno (*__gh_errno_ptr())
CThread * TCPServer::pThread = NULL;
TCPServer * TCPServer::instance = NULL;
TCPServer::TCPServer(s32 port){
this->sockfd = -1;
this->clientfd = -1;
memset(&(this->sock_addr),0,sizeof(this->sock_addr));
TCPServer::AttachDetach(DETACH);
StartTCPThread(this);
}
TCPServer::~TCPServer(){
CloseSockets();
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("Thread will be closed\n"); }
TCPServer::AttachDetach(DETACH);
exitThread = 1;
if(TCPServer::pThread != NULL){
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("Deleting it!\n"); }
delete TCPServer::pThread;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("Thread done\n"); }
TCPServer::pThread = NULL;
}
void TCPServer::CloseSockets(){
if (this->sockfd != -1){
socketclose(this->sockfd);
}
if (this->clientfd != -1){
socketclose(this->clientfd);
}
this->sockfd = -1;
this->clientfd = -1;
}
void TCPServer::StartTCPThread(TCPServer * server){
s32 priority = 28;
if(OSGetTitleID() == 0x00050000101c9300 || //The Legend of Zelda Breath of the Wild JPN
OSGetTitleID() == 0x00050000101c9400 || //The Legend of Zelda Breath of the Wild USA
OSGetTitleID() == 0x00050000101c9500 || //The Legend of Zelda Breath of the Wild EUR
OSGetTitleID() == 0x00050000101c9b00 || //The Binding of Isaac: Rebirth EUR
OSGetTitleID() == 0x00050000101a3c00){ //The Binding of Isaac: Rebirth USA
priority = 10;
DEBUG_FUNCTION_LINE("This game needs higher thread priority. We set it to %d\n",priority);
}
TCPServer::pThread = CThread::create(TCPServer::DoTCPThread, (void*)server, CThread::eAttributeAffCore2,priority);
TCPServer::pThread->resumeThread();
}
void TCPServer::AttachDetach(s32 attach){
if(HID_DEBUG){
if(attach){
DEBUG_FUNCTION_LINE("Network Attach\n");
}else{
DEBUG_FUNCTION_LINE("Network Detach\n");
}
}
for(s32 i= 0;i< gHIDMaxDevices;i++){
for(s32 j= 0;j< HID_MAX_PADS_COUNT;j++){
if(gNetworkController[i][j][NETWORK_CONTROLLER_ACTIVE] > 0){
DEBUG_FUNCTION_LINE("Found a registered pad in deviceslot %d and padslot %d! Lets detach it.\n",i,j);
HIDDevice device;
memset(&device,0,sizeof(device));
device.interface_index = 0;
device.vid = gNetworkController[i][j][NETWORK_CONTROLLER_VID];
device.pid = gNetworkController[i][j][NETWORK_CONTROLLER_PID];
device.handle = gNetworkController[i][j][NETWORK_CONTROLLER_HANDLE];
device.max_packet_size_rx = 8;
ControllerPatcherHID::externAttachDetachCallback(&device,attach);
memset(gNetworkController[i][j],0,sizeof(gNetworkController[i][j]));
}
}
}
if(HID_DEBUG){
if(attach){
DEBUG_FUNCTION_LINE("Network Attach DONE!\n");
}else{
DEBUG_FUNCTION_LINE("Network Detach DONE!\n");
}
}
}
void TCPServer::DetachAndDelete(){
TCPServer::AttachDetach(DETACH);
memset(&gNetworkController,0,sizeof(gNetworkController));
}
s32 TCPServer::RunTCP(){
s32 ret;
while (1) {
if(exitThread) break;
ret = ControllerPatcherNet::checkbyte(clientfd);
if (ret < 0) {
if(wiiu_errno != 6) return ret;
os_usleep(1000);
continue;
}
//DEBUG_FUNCTION_LINE("got byte from tcp! %01X\n",ret);
switch (ret) {
case WIIU_CP_TCP_ATTACH: { /*attach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
s32 handle;
ret = ControllerPatcherNet::recvwait(clientfd, &handle, 4);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: recvwait handle\n",WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("got handle %d\n",handle); }
u16 vid = 0;
u16 pid = 0;
ret = ControllerPatcherNet::recvwait(clientfd, &vid, 2);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: recvwait vid\n",WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("got vid %04X\n",vid); }
ret = ControllerPatcherNet::recvwait(clientfd, &pid, 2);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: recvwait pid\n",WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("got pid %04X\n",pid); }
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vid);
device.pid = SWAP16(pid);
device.max_packet_size_rx = 8;
my_cb_user * user = NULL;
ControllerPatcherHID::externAttachDetachCallback(&device,1);
if((ret = ControllerPatcherUtils::getDataByHandle(handle,&user)) < 0){
DEBUG_FUNCTION_LINE("Error in %02X: getDataByHandle(%d,%08X).\n",WIIU_CP_TCP_ATTACH,handle,&user);
DEBUG_FUNCTION_LINE("Error in %02X: Config for the controller is missing.\n",WIIU_CP_TCP_ATTACH);
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND) < 0)){
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
}
return -1;
}
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_FOUND) < 0)){
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_FOUND byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return ret;
}
if(user != NULL){
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_OKAY) < 0)){
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_OKAY byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return ret;
}
ret = ControllerPatcherNet::sendwait(clientfd,&user->slotdata.deviceslot,2);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: sendwait slotdata: %04X\n",WIIU_CP_TCP_ATTACH,user->slotdata.deviceslot);
return ret;
}
ret = ControllerPatcherNet::sendwait(clientfd,&user->pad_slot,1);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: sendwait pad_slot: %04X\n",WIIU_CP_TCP_ATTACH,user->pad_slot);
return ret;
}
}else{
DEBUG_FUNCTION_LINE("Error in %02X: invalid user data.\n",WIIU_CP_TCP_ATTACH);
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_BAD) < 0)){
DEBUG_FUNCTION_LINE("Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_BAD byte failed. Error: %d.\n",WIIU_CP_TCP_ATTACH,ret);
return ret;
}
return -1;
break;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("attachted to device slot: %d , pad slot is: %d\n",user->slotdata.deviceslot,user->pad_slot); }
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_VID] = device.vid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_PID] = device.pid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_ACTIVE] = 1;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_HANDLE] = handle;
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("handle %d connected! vid: %02X pid: %02X deviceslot %d, padslot %d\n",handle,vid,pid,user->slotdata.deviceslot,user->pad_slot); }
break;
}
break;
}
case WIIU_CP_TCP_DETACH: { /*detach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
s32 handle;
ret = ControllerPatcherNet::recvwait(clientfd, &handle, 4);
if(ret < 0){
DEBUG_FUNCTION_LINE("Error in %02X: recvwait handle\n",WIIU_CP_TCP_DETACH);
return ret;
break;
}
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("got detach for handle: %d\n",handle); }
my_cb_user * user = NULL;
if(ControllerPatcherUtils::getDataByHandle(handle,&user) < 0){
DEBUG_FUNCTION_LINE("Error in %02X: getDataByHandle(%d,%08X).\n",WIIU_CP_TCP_DETACH,handle,&user);
return -1;
break;
}
if(user == NULL){
DEBUG_FUNCTION_LINE("Error in %02X: invalid user data.\n",WIIU_CP_TCP_DETACH);
return -1;
break;
}
s32 deviceslot = user->slotdata.deviceslot;
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("device slot is: %d , pad slot is: %d\n",deviceslot,user->pad_slot); }
DeviceVIDPIDInfo vidpid;
s32 result;
if((result = ControllerPatcherUtils::getVIDPIDbyDeviceSlot(deviceslot,&vidpid)) < 0){
DEBUG_FUNCTION_LINE("Error in %02X: Couldn't find a valid VID/PID for device slot %d. Error: %d\n",WIIU_CP_TCP_DETACH,deviceslot,ret);
return -1;
break;
}
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vidpid.vid);
device.pid = SWAP16(vidpid.pid);
device.max_packet_size_rx = 14;
ControllerPatcherHID::externAttachDetachCallback(&device,DETACH);
memset(gNetworkController[deviceslot][user->pad_slot],0,sizeof(gNetworkController[deviceslot][user->pad_slot]));
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("handle %d disconnected!\n",handle); }
break;
}
break;
}
case WIIU_CP_TCP_PING: { /*ping*/
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("Got Ping, sending now a Pong\n"); }
s32 ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_PONG);
if(ret < 0){ DEBUG_FUNCTION_LINE("Error in %02X: sendbyte PONG\n"); return -1;}
break;
}
break;
}
default:
return -1;
break;
}
}
return 0;
}
void TCPServer::ErrorHandling(){
CloseSockets();
os_usleep(1000*1000*2);
}
void TCPServer::DoTCPThreadInternal(){
s32 ret;
s32 len;
while (1) {
if(exitThread) break;
memset(&(this->sock_addr),0,sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = DEFAULT_TCP_PORT;
sock_addr.sin_addr.s_addr = 0;
this->sockfd = ret = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ret == -1){ ErrorHandling(); continue;}
s32 enable = 1;
setsockopt(this->sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
ret = bind(this->sockfd, (sockaddr *)&sock_addr, 16);
if(ret < 0) { ErrorHandling(); continue;}
ret = listen(this->sockfd, 1);
if(ret < 0){ ErrorHandling(); continue;}
do{
if(HID_DEBUG){ DEBUG_FUNCTION_LINE("Waiting for a connection\n"); }
if(exitThread) break;
len = 16;
/**
Handshake
1. At first this server sends his protocol version
2. The network clients answers with his preferred version (which needs to be equals or lower the version this server sent him) or an abort command.
3a. If the client sent a abort, close the connection and wait for another connection
3b. If the client sent his highest supported version, the server confirm that he is able to use this version (by sending the version back) or sending a abort command to disconnect.
**/
clientfd = ret = accept(sockfd, (sockaddr *)&(sock_addr), &len);
if(ret == -1){ ErrorHandling(); break;}
DEBUG_FUNCTION_LINE("TCP Connection accepted! Sending my protocol version: %d (0x%02X)\n", (WIIU_CP_TCP_HANDSHAKE - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,WIIU_CP_TCP_HANDSHAKE);
gUDPClientip = sock_addr.sin_addr.s_addr;
UDPClient::createInstance();
s32 ret;
ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE); //Hey I'm a WiiU console!
if(ret < 0){ DEBUG_FUNCTION_LINE("Error sendbyte: %02X\n",WIIU_CP_TCP_HANDSHAKE); ErrorHandling(); break;}
u8 clientProtocolVersion = ControllerPatcherNet::recvbyte(clientfd);
if(ret < 0){ DEBUG_FUNCTION_LINE("Error recvbyte: %02X\n",WIIU_CP_TCP_HANDSHAKE); ErrorHandling(); break;}
if(clientProtocolVersion == WIIU_CP_TCP_HANDSHAKE_ABORT){
DEBUG_FUNCTION_LINE("The network client wants to abort.\n");
ErrorHandling(); break;
}
DEBUG_FUNCTION_LINE("received protocol version: %d (0x%02X)\n",(clientProtocolVersion - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,clientProtocolVersion);
if(clientProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_MIN && clientProtocolVersion <= WIIU_CP_TCP_HANDSHAKE_VERSION_MAX){
DEBUG_FUNCTION_LINE("We support this protocol version. Let's confirm it to the network client.\n");
gUsedProtocolVersion = clientProtocolVersion;
ret = ControllerPatcherNet::sendbyte(clientfd, clientProtocolVersion);
if(ret < 0){ DEBUG_FUNCTION_LINE("Error sendbyte: %02X\n",clientProtocolVersion); ErrorHandling(); break;}
}else{
DEBUG_FUNCTION_LINE("We don't support this protocol version. We need to abort =(.\n");
ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE_ABORT);
ErrorHandling(); break;
}
DEBUG_FUNCTION_LINE("Handshake done! Success!\n");
TCPServer::DetachAndDelete(); //Clear connected controller
RunTCP();
if(clientfd != -1){
socketclose(clientfd);
}
clientfd = -1;
}while(0);
DEBUG_FUNCTION_LINE("Connection closed\n");
gUDPClientip = 0;
UDPClient::destroyInstance();
TCPServer::DetachAndDelete(); //Clear connected controller
CloseSockets();
continue;
}
}
void TCPServer::DoTCPThread(CThread *thread, void *arg){
TCPServer * args = (TCPServer * )arg;
return args->DoTCPThreadInternal();
}

View File

@ -26,7 +26,7 @@
class UDPClient{
friend class ControllerPatcher;
friend class ControllerPatcherHID;
friend class TCPServer;
friend class CPTCPServer;
public:
private: