mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-18 16:09:53 +00:00
net: Listen on ipv6 and ipv4.
Hurray, no longer "part of the problem" for ipv4.
This commit is contained in:
parent
30a07c2e8d
commit
5b95de663e
@ -69,25 +69,36 @@ static ServerStatus RetrieveStatus() {
|
||||
// relay that address to a mobile device searching for the server.
|
||||
static void RegisterServer(int port) {
|
||||
http::Client http;
|
||||
Buffer theVoid;
|
||||
|
||||
char resource[1024] = {};
|
||||
// We register both IPv4 and IPv6 in case the other client is using a different one.
|
||||
// Our server is (currently?) ipv4 only, so we always register the ipv4 local for now.
|
||||
char resource4[1024] = {};
|
||||
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV4)) {
|
||||
Buffer theVoid;
|
||||
if (http.Connect(2, 20.0, &scanCancelled)) {
|
||||
std::string ip = fd_util::GetLocalIP(http.sock());
|
||||
snprintf(resource, sizeof(resource) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port);
|
||||
snprintf(resource4, sizeof(resource4) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port);
|
||||
|
||||
http.GET(resource, &theVoid);
|
||||
http.GET(resource4, &theVoid);
|
||||
theVoid.Skip(theVoid.size());
|
||||
http.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT, net::DNSType::IPV6)) {
|
||||
Buffer theVoid;
|
||||
// We register both IPv4 and IPv6 in case the other client is using a different one.
|
||||
if (resource4[0] != 0 && http.Connect()) {
|
||||
http.GET(resource4, &theVoid);
|
||||
theVoid.Skip(theVoid.size());
|
||||
http.Disconnect();
|
||||
}
|
||||
|
||||
// Currently, we're not using keepalive, so gotta reconnect...
|
||||
if (http.Connect()) {
|
||||
http.GET(resource, &theVoid);
|
||||
char resource6[1024] = {};
|
||||
std::string ip = fd_util::GetLocalIP(http.sock());
|
||||
snprintf(resource6, sizeof(resource6) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port);
|
||||
|
||||
http.GET(resource6, &theVoid);
|
||||
theVoid.Skip(theVoid.size());
|
||||
http.Disconnect();
|
||||
}
|
||||
}
|
||||
|
@ -130,9 +130,21 @@ void Server::SetFallbackHandler(UrlHandlerFunc handler) {
|
||||
fallback_ = handler;
|
||||
}
|
||||
|
||||
bool Server::Listen(int port) {
|
||||
bool Server::Listen(int port, net::DNSType type) {
|
||||
bool success = false;
|
||||
if (type == net::DNSType::ANY || type == net::DNSType::IPV6) {
|
||||
success = Listen6(port, type == net::DNSType::IPV6);
|
||||
}
|
||||
if (!success && (type == net::DNSType::ANY || type == net::DNSType::IPV4)) {
|
||||
success = Listen4(port);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Server::Listen4(int port) {
|
||||
listener_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||
CHECK_GE(listener_, 0);
|
||||
if (listener_ < 0)
|
||||
return false;
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
@ -145,6 +157,7 @@ bool Server::Listen(int port) {
|
||||
setsockopt(listener_, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt));
|
||||
|
||||
if (bind(listener_, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
||||
closesocket(listener_);
|
||||
ELOG("Failed to bind to port %i. Bailing.", port);
|
||||
return false;
|
||||
}
|
||||
@ -152,7 +165,10 @@ bool Server::Listen(int port) {
|
||||
fd_util::SetNonBlocking(listener_, true);
|
||||
|
||||
// 1024 is the max number of queued requests.
|
||||
CHECK_GE(listen(listener_, 1024), 0);
|
||||
if (listen(listener_, 1024) < 0) {
|
||||
closesocket(listener_);
|
||||
return false;
|
||||
}
|
||||
|
||||
socklen_t len = sizeof(server_addr);
|
||||
if (getsockname(listener_, (struct sockaddr *)&server_addr, &len) == 0) {
|
||||
@ -165,6 +181,50 @@ bool Server::Listen(int port) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Server::Listen6(int port, bool ipv6_only) {
|
||||
listener_ = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
if (listener_ < 0)
|
||||
return false;
|
||||
|
||||
struct sockaddr_in6 server_addr;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin6_family = AF_INET6;
|
||||
server_addr.sin6_addr = in6addr_any;
|
||||
server_addr.sin6_port = htons(port);
|
||||
|
||||
int opt = 1;
|
||||
// Enable re-binding to avoid the pain when restarting the server quickly.
|
||||
setsockopt(listener_, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt));
|
||||
|
||||
// Enable listening on IPv6 and IPv4?
|
||||
opt = ipv6_only ? 1 : 0;
|
||||
setsockopt(listener_, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&opt, sizeof(opt));
|
||||
|
||||
if (bind(listener_, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
||||
closesocket(listener_);
|
||||
ELOG("Failed to bind to port %i. Bailing.", port);
|
||||
return false;
|
||||
}
|
||||
|
||||
fd_util::SetNonBlocking(listener_, true);
|
||||
|
||||
// 1024 is the max number of queued requests.
|
||||
if (listen(listener_, 1024) < 0) {
|
||||
closesocket(listener_);
|
||||
return false;
|
||||
}
|
||||
|
||||
socklen_t len = sizeof(server_addr);
|
||||
if (getsockname(listener_, (struct sockaddr *)&server_addr, &len) == 0) {
|
||||
port = ntohs(server_addr.sin6_port);
|
||||
}
|
||||
|
||||
ILOG("HTTP server started on port %i", port);
|
||||
port_ = port;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Server::RunSlice(double timeout) {
|
||||
if (listener_ < 0 || port_ == 0) {
|
||||
return false;
|
||||
@ -177,9 +237,13 @@ bool Server::RunSlice(double timeout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr client_addr;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in ipv4;
|
||||
struct sockaddr_in6 ipv6;
|
||||
} client_addr;
|
||||
socklen_t client_addr_size = sizeof(client_addr);
|
||||
int conn_fd = accept(listener_, &client_addr, &client_addr_size);
|
||||
int conn_fd = accept(listener_, &client_addr.sa, &client_addr_size);
|
||||
if (conn_fd >= 0) {
|
||||
executor_->Run(std::bind(&Server::HandleConnection, this, conn_fd));
|
||||
return true;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/buffer.h"
|
||||
#include "net/http_headers.h"
|
||||
#include "net/resolve.h"
|
||||
#include "thread/executor.h"
|
||||
|
||||
namespace net {
|
||||
@ -73,7 +74,7 @@ public:
|
||||
// May run for (significantly) longer than timeout, but won't wait longer than that
|
||||
// for a new connection to handle.
|
||||
bool RunSlice(double timeout);
|
||||
bool Listen(int port);
|
||||
bool Listen(int port, net::DNSType type = net::DNSType::ANY);
|
||||
void Stop();
|
||||
|
||||
void RegisterHandler(const char *url_path, UrlHandlerFunc handler);
|
||||
@ -89,6 +90,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool Listen6(int port, bool ipv6_only);
|
||||
bool Listen4(int port);
|
||||
|
||||
void HandleConnection(int conn_fd);
|
||||
|
||||
// Things like default 404, etc.
|
||||
|
Loading…
x
Reference in New Issue
Block a user