From 975af132dcb88043edb4eae1efa0b986a0709ed3 Mon Sep 17 00:00:00 2001 From: Maschell Date: Wed, 7 Mar 2018 18:42:36 +0100 Subject: [PATCH] Simplified the code by using the TCPServer from libutils --- source/ControllerPatcher.cpp | 6 +- source/ControllerPatcherIncludes.hpp | 4 +- source/network/CPTCPServer.cpp | 314 +++++++++++++++ .../{TCPServer.hpp => CPTCPServer.hpp} | 54 ++- source/network/ControllerPatcherNet.cpp | 50 --- source/network/ControllerPatcherNet.hpp | 17 - source/network/TCPServer.cpp | 373 ------------------ source/network/UDPClient.hpp | 2 +- 8 files changed, 352 insertions(+), 468 deletions(-) create mode 100644 source/network/CPTCPServer.cpp rename source/network/{TCPServer.hpp => CPTCPServer.hpp} (64%) delete mode 100644 source/network/ControllerPatcherNet.cpp delete mode 100644 source/network/ControllerPatcherNet.hpp delete mode 100644 source/network/TCPServer.cpp diff --git a/source/ControllerPatcher.cpp b/source/ControllerPatcher.cpp index ddec2aa..de54c7d 100644 --- a/source/ControllerPatcher.cpp +++ b/source/ControllerPatcher.cpp @@ -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;ipad_infos[i]); if(!padinfo->active){ break; diff --git a/source/ControllerPatcherIncludes.hpp b/source/ControllerPatcherIncludes.hpp index f60e1c8..dbee272 100644 --- a/source/ControllerPatcherIncludes.hpp +++ b/source/ControllerPatcherIncludes.hpp @@ -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_ */ diff --git a/source/network/CPTCPServer.cpp b/source/network/CPTCPServer.cpp new file mode 100644 index 0000000..5e0a8ea --- /dev/null +++ b/source/network/CPTCPServer.cpp @@ -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 . + ****************************************************************************/ +#include "CPTCPServer.hpp" +#include +#include +#include + +#include + +#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 +} diff --git a/source/network/TCPServer.hpp b/source/network/CPTCPServer.hpp similarity index 64% rename from source/network/TCPServer.hpp rename to source/network/CPTCPServer.hpp index 38531e6..1d9aafb 100644 --- a/source/network/TCPServer.hpp +++ b/source/network/CPTCPServer.hpp @@ -14,13 +14,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ -#ifndef _TCPSERVER_WINDOW_H_ -#define _TCPSERVER_WINDOW_H_ +#ifndef _CP_TCPSERVER_WINDOW_H_ +#define _CP_TCPSERVER_WINDOW_H_ #include "../ControllerPatcherIncludes.hpp" #include #include +#include +#include #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_ diff --git a/source/network/ControllerPatcherNet.cpp b/source/network/ControllerPatcherNet.cpp deleted file mode 100644 index 429d670..0000000 --- a/source/network/ControllerPatcherNet.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "ControllerPatcherNet.hpp" -#include -#include - -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); -} diff --git a/source/network/ControllerPatcherNet.hpp b/source/network/ControllerPatcherNet.hpp deleted file mode 100644 index cab98b0..0000000 --- a/source/network/ControllerPatcherNet.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _CONTROLLERPATCHERNET_H_ -#define _CONTROLLERPATCHERNET_H_ - -#include - -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 diff --git a/source/network/TCPServer.cpp b/source/network/TCPServer.cpp deleted file mode 100644 index 4daea50..0000000 --- a/source/network/TCPServer.cpp +++ /dev/null @@ -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 . - ****************************************************************************/ -#include "TCPServer.hpp" -#include -#include -#include - -#include - -#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(); -} diff --git a/source/network/UDPClient.hpp b/source/network/UDPClient.hpp index 460096f..c0d0fef 100644 --- a/source/network/UDPClient.hpp +++ b/source/network/UDPClient.hpp @@ -26,7 +26,7 @@ class UDPClient{ friend class ControllerPatcher; friend class ControllerPatcherHID; - friend class TCPServer; + friend class CPTCPServer; public: private: