diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xenia/kernel/xnet.cc | 20 | ||||
| -rw-r--r-- | src/xenia/net/net_proxy.h | 48 | ||||
| -rw-r--r-- | src/xenia/net/net_proxy_main.cc | 339 | ||||
| -rw-r--r-- | src/xenia/net/premake5.lua | 39 |
4 files changed, 9 insertions, 437 deletions
diff --git a/src/xenia/kernel/xnet.cc b/src/xenia/kernel/xnet.cc index 07c194944..6238663a5 100644 --- a/src/xenia/kernel/xnet.cc +++ b/src/xenia/kernel/xnet.cc @@ -19,7 +19,6 @@ #include "xenia/kernel/user_module.h" #include "xenia/kernel/xsocket.h" #include "xenia/kernel/xthread.h" -#include "xenia/net/net_proxy.h" #include "third_party/crypto/TinySHA1.hpp" #include "third_party/crypto/des/des3.h" @@ -206,13 +205,11 @@ int XNet::ProxyRecvThreadEntry() { break; } - auto proxy_packet = (net::proxypacket*)buf; - if (proxy_packet->type == net::proxypacket::kTypeData) { - auto packet = (net::proxypacket_data*)buf; - - RecvPacket(packet->enet_src, packet->enet_dest, packet->data, - packet->data_len); - } + // TODO + /* + RecvPacket(packet->enet_src, packet->enet_dest, packet->data, + packet->data_len); + */ } return 0; @@ -220,11 +217,10 @@ int XNet::ProxyRecvThreadEntry() { int XNet::SendPacket(XSocket* socket, N_XSOCKADDR_IN* to, const uint8_t* buf, size_t buf_len) { - auto data = net::proxypacket_data(); - data.type = net::proxypacket::kTypeData; - + /* std::memset(data.enet_src, 0, 6); // Ignored. std::memset(data.enet_dest, 0xFF, 6); // broadcast (hardcoded for now) + */ size_t rounded_buf_len = xe::round_up(buf_len, 8); std::vector<uint8_t> xnet_packet_data; @@ -310,6 +306,7 @@ int XNet::SendPacket(XSocket* socket, N_XSOCKADDR_IN* to, const uint8_t* buf, std::memcpy(footer->hmac, digest, 0xA); + /* // Copy the XNet packet into our proxy buffer std::memcpy(data.data, xnet_packet, std::min(0x4 + buf_len + padding_bytes + sizeof(packet_footer), @@ -317,6 +314,7 @@ int XNet::SendPacket(XSocket* socket, N_XSOCKADDR_IN* to, const uint8_t* buf, data.data_len = (uint16_t)(0x4 + buf_len + padding_bytes + sizeof(packet_footer)); proxy_socket_->Send(&data, sizeof(data)); + */ return 0; } diff --git a/src/xenia/net/net_proxy.h b/src/xenia/net/net_proxy.h deleted file mode 100644 index a6fee3a60..000000000 --- a/src/xenia/net/net_proxy.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_NET_NET_PROXY_H_ -#define XENIA_NET_NET_PROXY_H_ - -#include <cstdint> - -namespace xe { -namespace net { - -struct proxypacket { - enum Type { - kTypeInvalid = 0, - kTypeData, - - kTypeGetDeviceList, - kTypeDeviceList, - kTypeSetDevice, - }; - uint8_t type = 0; -}; - -struct proxypacket_data : public proxypacket { - static const uint32_t kHeaderSize = 16; // Size - data - uint8_t enet_dest[0x6]; - uint8_t enet_src[0x6]; - - uint16_t data_len; - uint8_t data[1500]; -}; - -struct proxypacket_devicelist : public proxypacket { - struct device { - - }; -}; - -} -} - -#endif // XENIA_NET_NET_PROXY_H_
\ No newline at end of file diff --git a/src/xenia/net/net_proxy_main.cc b/src/xenia/net/net_proxy_main.cc deleted file mode 100644 index 50c60f872..000000000 --- a/src/xenia/net/net_proxy_main.cc +++ /dev/null @@ -1,339 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -// Xenia network proxy -// This acts as a proxy between Xenia and XBOX 360 consoles. -// Unfortunately, the XBOX 360 sends packets that WinSock2 cannot receive. -// So, we have to listen for any packets sent from an XBOX 360, modify them, -// then redirect them into Xenia for HLE. - -#include "xenia/base/main.h" - -#include "xenia/base/byte_order.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/socket.h" -#include "xenia/base/string_buffer.h" -#include "xenia/base/threading.h" -#include "xenia/net/net_proxy.h" - -#include <pcap/pcap.h> - -// DEBUG -#include <WinSock2.h> - -namespace xe { -namespace net { - -// Ethernet II header -struct enet_header { - uint8_t dest[6]; - uint8_t src[6]; - uint16_t type = 0x8; // IPv4 = 0x0008 (LE) -}; - -struct ipv4_header { - uint8_t header_len : 4; // 0x0 0x5 (4 * 5 = 20) - uint8_t version : 4; // 0x0 IPv4 = 0x4 - uint8_t dscp; // 0x1 - xe::be<uint16_t> total_length; // 0x2 - xe::be<uint16_t> ident; // 0x4 - xe::be<uint16_t> flags; // 0x6 flags and fragment offset (unused by UDP) - uint8_t ttl; // 0x8 Time to live (usually 128) - uint8_t protocol; // 0x9 UDP = 0x11 - uint16_t checksum; // 0xA - xe::be<uint32_t> ip_src; // 0xC - xe::be<uint32_t> ip_dst; // 0x10 -}; - -struct udp_pseudo_header { - xe::be<uint32_t> ip_src; // 0x0 - xe::be<uint32_t> ip_dst; // 0x4 - uint8_t zero; // 0x8 - uint8_t protocol; // 0x9 - xe::be<uint16_t> udp_length; // 0xA -}; - -struct udp_header { - xe::be<uint16_t> port_src; // 0x0 - xe::be<uint16_t> port_dst; // 0x2 - xe::be<uint16_t> length; // 0x4 - uint16_t checksum; // 0x6 -}; - -std::vector<std::unique_ptr<Socket>> clients; -std::mutex clients_mutex; -threading::Fence clients_fence; - -pcap_t* device_handle = nullptr; -uint8_t device_mac[6] = {0xC8, 0x60, 0x00, 0x9F, 0x0A, 0xDD}; -static const uint8_t broadcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -void packet_callback(uint8_t* param, const pcap_pkthdr* header, - const uint8_t* data) { - auto enet = (enet_header*)data; - if (enet->type != 0x8) { - // Not IPv4. - return; - } - - auto ipv4 = (ipv4_header*)(data + sizeof(enet_header)); - if (ipv4->protocol != 0x11) { - // Not UDP. - return; - } - - if (!std::memcmp(enet->src, device_mac, 6)) { - // Drop if it's from this computer - return; - } - - // Check if it's a broadcast/destined for this computer - if (std::memcmp(enet->dest, broadcast_mac, 6) && - std::memcmp(enet->dest, device_mac, 6)) { - return; - } - - proxypacket_data dp; - std::memset(&dp, 0, sizeof(dp)); - dp.type = proxypacket::kTypeData; - std::memcpy(dp.enet_dest, enet->dest, 6); - std::memcpy(dp.enet_src, enet->src, 6); - std::memcpy(dp.data, data + 0x2A, - (size_t)std::min(1500u, header->len - 0x2A)); - dp.data_len = (uint16_t)std::min(1500u, header->len - 0x2A); - - // Send the packet over to Xenia. - std::lock_guard<std::mutex> lock(clients_mutex); - for (auto it = clients.begin(); it != clients.end(); it++) { - (*it)->Send(&dp, proxypacket_data::kHeaderSize + header->len - 0x2A); - } -} - -uint16_t calculate_checksum(const uint8_t** buffers, uint16_t* buffer_len, - size_t num_buffers) { - uint64_t sum = 0; - for (size_t i = 0; i < num_buffers; i++) { - uint16_t* data16 = (uint16_t*)buffers[i]; - uint16_t data16len = buffer_len[i] & ~1; - - for (uint16_t j = 0; j < data16len; j += 2) { - sum += data16[j / 2]; - } - - if (buffer_len[i] & 1) { - // Handle any stragglers. - sum += buffers[i][buffer_len[i] - 1]; - } - } - - while (sum > 0xFFFF) { - // Carry - sum = (sum & 0xFFFF) + (sum >> 16); - } - - return (uint16_t)~sum; -} - -uint16_t calculate_checksum(const uint8_t* buffer, uint16_t buffer_len) { - return calculate_checksum(&buffer, &buffer_len, 1); -} - -int send_packet(uint8_t* enet_src, uint8_t* enet_dest, const uint8_t* data, - uint16_t data_len) { - std::vector<uint8_t> packet_mem; - packet_mem.reserve(data_len + 0x100); - - // Assuming UDP for now. If it's TCP we're fucked. - auto enet = (enet_header*)packet_mem.data(); - std::memcpy(enet->src, enet_src, 6); - std::memcpy(enet->dest, enet_dest, 6); - enet->type = 0x8; // IPv4 - - // Check if it's a broadcast packet. - bool broadcast_packet = false; - static const uint8_t enet_broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - if (!std::memcmp(enet_dest, enet_broadcast, 6)) { - broadcast_packet = true; - } - - auto ipv4 = (ipv4_header*)(packet_mem.data() + sizeof(enet_header)); - ipv4->version = 4; - ipv4->header_len = 5; - ipv4->dscp = 0; - ipv4->total_length = data_len + sizeof(ipv4_header) + sizeof(udp_header); - ipv4->ident = 'XE'; // Not too important. - ipv4->flags = 0; - ipv4->ttl = 64; - ipv4->protocol = 0x11; // IPPROTO_UDP - ipv4->checksum = 0; - ipv4->ip_src = 0x00000001; // 0.0.0.1 (required for 360 packets) - ipv4->ip_dst = broadcast_packet ? 0xFFFFFFFF // 255.255.255.255 - : 0x00000001; // 0.0.0.1 - ipv4->checksum = calculate_checksum((uint8_t*)ipv4, sizeof(ipv4_header)); - - auto udp = (udp_header*)(packet_mem.data() + sizeof(enet_header) + - sizeof(ipv4_header)); - udp->port_src = 3074; - udp->port_dst = 3074; - udp->length = data_len + sizeof(udp_header); - udp->checksum = 0; - - // UDP uses a pseudo-header for its checksum. - // Calculating the checksum is optional for UDP! - udp_pseudo_header pseudo_header; - pseudo_header.ip_src = ipv4->ip_src; - pseudo_header.ip_dst = ipv4->ip_dst; - pseudo_header.zero = 0; - pseudo_header.protocol = ipv4->protocol; - pseudo_header.udp_length = udp->length; - - const uint8_t* buffers[] = {(uint8_t*)&pseudo_header, (uint8_t*)udp, data}; - uint16_t lengths[] = {sizeof(udp_pseudo_header), sizeof(udp_header), - data_len}; - udp->checksum = calculate_checksum(buffers, lengths, xe::countof(buffers)); - - // Copy in user data. - auto pkt_data = packet_mem.data() + sizeof(enet_header) + - sizeof(ipv4_header) + sizeof(udp_header); - std::memcpy(pkt_data, data, data_len); - - // Now send the packet - // TODO: Linux can just use a raw socket here. - pcap_sendpacket(device_handle, packet_mem.data(), - sizeof(enet_header) + sizeof(ipv4_header) + - sizeof(udp_header) + data_len); - - return 0; -} - -int net_proxy_client_thread() { - while (true) { - // Read from the client sockets. - if (clients.size() == 0) { - clients_fence.Wait(); - } - - std::vector<threading::WaitHandle*> wait_handles; - for (int i = 0; i < clients.size(); i++) { - wait_handles.push_back(clients[i]->wait_handle()); - } - - auto wr = threading::WaitMultiple(wait_handles.data(), wait_handles.size(), - false, false); - if (wr.first != threading::WaitResult::kSuccess) { - continue; - } - - uint8_t buf[0x800]; - for (size_t i = wr.second; i < clients.size(); i++) { - size_t r = clients[i]->Receive(buf, 0x800); - if (r == -1) { - // Dead client. - std::lock_guard<std::mutex> lock(clients_mutex); - clients.erase(clients.begin() + i); - i--; - - continue; - } else if (r == 0) { - // No data. - continue; - } - - auto pkt = (proxypacket*)buf; - if (pkt->type == proxypacket::kTypeData) { - // Send data on Xenia's behalf - auto pkt_data = (proxypacket_data*)pkt; - - send_packet(device_mac, pkt_data->enet_dest, pkt_data->data, - pkt_data->data_len); - } else if (pkt->type == proxypacket::kTypeGetDeviceList) { - // Send a device list over to Xenia. - pcap_if_t* all_devices; - char error_buffer[PCAP_ERRBUF_SIZE]; - - int res = pcap_findalldevs(&all_devices, error_buffer); - if (res < 0) { - XELOGE("Could not generate device list: pcap_findalldevs failed (%s)", - error_buffer); - continue; - } - - // TODO: Need a utility class that can stream into a buffer (or - // whatever) - - // Free the device list. - pcap_freealldevs(all_devices); - } - } - } -} - -int net_proxy_main(const std::vector<std::wstring>& args) { - pcap_if_t* all_devices; - char error_buffer[PCAP_ERRBUF_SIZE]; - - int res = pcap_findalldevs(&all_devices, error_buffer); - if (res < 0) { - XELOGE("pcap_findalldevs failed!"); - return 1; - } - - // DEBUG: blah use device 2 - device_handle = - pcap_open_live(all_devices->next->name, 65536, 1, 1000, error_buffer); - if (device_handle == NULL) { - return 1; - } - - StringBuffer filter; - filter.Append( - "(udp and ((ip host 0.0.0.1) or (dst portrange 3074-3075) or (dst " - "portrange 14000-14001)))"); - - bpf_program filter_code; - if (pcap_compile(device_handle, &filter_code, filter.GetString(), 1, - 0xFFFFFFFF)) { - return 1; - } - - if (pcap_setfilter(device_handle, &filter_code) < 0) { - return 1; - } - - XELOGD("Listening on %s", all_devices->next->description); - - // Create the socket server. - auto server = SocketServer::Create(45981, [](std::unique_ptr<Socket> client) { - std::lock_guard<std::mutex> lock(clients_mutex); - clients.push_back(std::move(client)); - clients_fence.Signal(); - }); - - // We no longer need this buffer. - pcap_freealldevs(all_devices); - - // Create a server thread - threading::Thread::CreationParameters params; - params.create_suspended = false; - params.initial_priority = 0; - params.stack_size = 1024 * 1024; - auto thread = threading::Thread::Create(params, net_proxy_client_thread); - - pcap_loop(device_handle, 0, packet_callback, NULL); - - pcap_close(device_handle); - return 0; -} - -} // namespace net -} // namespace xe - -DEFINE_ENTRY_POINT(L"xenia-net-proxy", L"xenia-net-proxy", - xe::net::net_proxy_main);
\ No newline at end of file diff --git a/src/xenia/net/premake5.lua b/src/xenia/net/premake5.lua deleted file mode 100644 index 119d72080..000000000 --- a/src/xenia/net/premake5.lua +++ /dev/null @@ -1,39 +0,0 @@ -project_root = "../../.." -include(project_root.."/build_tools") - -group("src") -project("xenia-net-proxy") - uuid("02A982D7-7E59-45DF-8402-46C84127652F") - kind("WindowedApp") - language("C++") - links({ - project_root.."/third_party/winpcap/Lib/x64/Packet", - project_root.."/third_party/winpcap/Lib/x64/wpcap", - "gflags", - "xenia-base", - "xxhash", - }) - flags({ - "WinMain", -- Use WinMain instead of main. - }) - defines({ - "HAVE_REMOTE=1" - }) - includedirs({ - project_root.."/third_party/elemental-forms/src", - project_root.."/third_party/winpcap/Include", - project_root.."/build_tools/third_party/gflags/src", - }) - files({ - "net_proxy_main.cc", - "net_proxy.h", - "../base/main_"..platform_suffix..".cc", - }) - - filter("platforms:Windows") - debugdir(project_root) - debugargs({ - "--flagfile=scratch/flags.txt", - "2>&1", - "1>scratch/stdout-net-proxy.txt", - })
\ No newline at end of file |
