xenia/src/xenia/kernel/xsocket.h
2016-11-28 22:10:19 -06:00

151 lines
4 KiB
C++

/**
******************************************************************************
* 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_KERNEL_XSOCKET_H_
#define XENIA_KERNEL_XSOCKET_H_
#include <queue>
#include "xenia/base/byte_order.h"
#include "xenia/base/math.h"
#include "xenia/kernel/xobject.h"
namespace xe {
namespace kernel {
struct XSOCKADDR {
xe::be<uint16_t> address_family;
char sa_data[14];
};
struct N_XSOCKADDR {
N_XSOCKADDR() {}
N_XSOCKADDR(const XSOCKADDR* other) { *this = *other; }
N_XSOCKADDR& operator=(const XSOCKADDR& other) {
address_family = other.address_family;
std::memcpy(sa_data, other.sa_data, xe::countof(sa_data));
return *this;
}
uint16_t address_family;
char sa_data[14];
};
struct XSOCKADDR_IN {
xe::be<uint16_t> sin_family;
// Always big-endian!
xe::be<uint16_t> sin_port;
xe::be<uint32_t> sin_addr;
char sin_zero[8];
};
// Xenia native sockaddr_in
struct N_XSOCKADDR_IN {
N_XSOCKADDR_IN() {}
N_XSOCKADDR_IN(const XSOCKADDR_IN* other) { *this = *other; }
N_XSOCKADDR_IN& operator=(const XSOCKADDR_IN& other) {
sin_family = other.sin_family;
sin_port = other.sin_port;
sin_addr = other.sin_addr;
std::memset(sin_zero, 0, 8);
return *this;
}
uint16_t sin_family;
xe::be<uint16_t> sin_port;
xe::be<uint32_t> sin_addr;
char sin_zero[8];
};
class XSocket : public XObject {
public:
static const Type kType = kTypeSocket;
enum AddressFamily {
AF_INET = 2,
};
enum Type {
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
};
enum Protocol {
IPPROTO_TCP = 6,
IPPROTO_UDP = 17,
// LIVE Voice and Data Protocol
// http://blog.csdn.net/baozi3026/article/details/4277227
// Format: [cbGameData][GameData(encrypted)][VoiceData(unencrypted)]
IPPROTO_VDP = 254,
};
XSocket(KernelState* kernel_state);
~XSocket();
uint64_t native_handle() const { return native_handle_; }
uint16_t bound_port() const { return bound_port_; }
X_STATUS Initialize(AddressFamily af, Type type, Protocol proto);
X_STATUS Close();
X_STATUS SetOption(uint32_t level, uint32_t optname, void* optval_ptr,
uint32_t optlen);
X_STATUS IOControl(uint32_t cmd, uint8_t* arg_ptr);
X_STATUS Connect(N_XSOCKADDR* name, int name_len);
X_STATUS Bind(N_XSOCKADDR_IN* name, int name_len);
X_STATUS Listen(int backlog);
object_ref<XSocket> Accept(N_XSOCKADDR* name, int* name_len);
int Recv(uint8_t* buf, uint32_t buf_len, uint32_t flags);
int Send(const uint8_t* buf, uint32_t buf_len, uint32_t flags);
int RecvFrom(uint8_t* buf, uint32_t buf_len, uint32_t flags,
N_XSOCKADDR_IN* from, uint32_t* from_len);
int SendTo(uint8_t* buf, uint32_t buf_len, uint32_t flags, N_XSOCKADDR_IN* to,
uint32_t to_len);
struct packet {
// These values are in network byte order.
xe::be<uint16_t> src_port;
xe::be<uint32_t> src_ip;
uint16_t data_len;
uint8_t data[1];
};
// Queue a packet into our internal buffer.
bool QueuePacket(uint32_t src_ip, uint16_t src_port, const uint8_t* buf,
size_t len);
private:
XSocket(KernelState* kernel_state, uint64_t native_handle);
uint64_t native_handle_ = -1;
AddressFamily af_; // Address family
Type type_; // Type (DGRAM/Stream/etc)
Protocol proto_; // Protocol (TCP/UDP/etc)
bool secure_ = true; // Secure socket (encryption enabled)
bool bound_ = false; // Explicitly bound to an IP address?
uint16_t bound_port_ = 0;
bool broadcast_socket_ = false;
std::unique_ptr<xe::threading::Event> event_;
std::mutex incoming_packet_mutex_;
std::queue<uint8_t*> incoming_packets_;
};
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_XSOCKET_H_