ggpo: report UDP bind error. Better error reporting for net init
fix ggpo lib warnings
This commit is contained in:
parent
699dcdaf5b
commit
a6248905a0
|
@ -113,7 +113,8 @@ typedef struct GGPOLocalEndpoint {
|
|||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_PLAYER_DISCONNECTED, 9) \
|
||||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_TOO_MANY_SPECTATORS, 10) \
|
||||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INVALID_REQUEST, 11) \
|
||||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INPUT_SIZE_DIFF, 12)
|
||||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_INPUT_SIZE_DIFF, 12) \
|
||||
GGPO_ERRORLIST_ENTRY(GGPO_ERRORCODE_NETWORK_ERROR, 13)
|
||||
|
||||
#define GGPO_ERRORLIST_ENTRY(name, value) name = value,
|
||||
typedef enum {
|
||||
|
|
|
@ -18,13 +18,14 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb,
|
|||
uint16 localport,
|
||||
int num_players,
|
||||
int input_size) :
|
||||
_num_players(num_players),
|
||||
_input_size(input_size),
|
||||
_sync(_local_connect_status),
|
||||
_disconnect_timeout(DEFAULT_DISCONNECT_TIMEOUT),
|
||||
_disconnect_notify_start(DEFAULT_DISCONNECT_NOTIFY_START),
|
||||
_endpoints(nullptr),
|
||||
_num_spectators(0),
|
||||
_next_spectator_frame(0)
|
||||
_input_size(input_size),
|
||||
_num_players(num_players),
|
||||
_next_spectator_frame(0),
|
||||
_disconnect_timeout(DEFAULT_DISCONNECT_TIMEOUT),
|
||||
_disconnect_notify_start(DEFAULT_DISCONNECT_NOTIFY_START)
|
||||
{
|
||||
_callbacks = *cb;
|
||||
_synchronizing = true;
|
||||
|
@ -47,7 +48,7 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb,
|
|||
|
||||
_endpoints = new UdpProtocol[_num_players];
|
||||
memset(_local_connect_status, 0, sizeof(_local_connect_status));
|
||||
for (int i = 0; i < ARRAY_SIZE(_local_connect_status); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(_local_connect_status); i++) {
|
||||
_local_connect_status[i].last_frame = -1;
|
||||
}
|
||||
|
||||
|
@ -386,6 +387,9 @@ Peer2PeerBackend::OnUdpProtocolPeerEvent(UdpProtocol::Event &evt, int queue)
|
|||
case UdpProtocol::Event::Disconnected:
|
||||
DisconnectPlayer(QueueToPlayerHandle(queue));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,17 +400,14 @@ Peer2PeerBackend::OnUdpProtocolSpectatorEvent(UdpProtocol::Event &evt, int queue
|
|||
GGPOPlayerHandle handle = QueueToSpectatorHandle(queue);
|
||||
OnUdpProtocolEvent(evt, handle);
|
||||
|
||||
GGPOEvent info;
|
||||
|
||||
switch (evt.type) {
|
||||
case UdpProtocol::Event::Disconnected:
|
||||
if (evt.type == UdpProtocol::Event::Disconnected)
|
||||
{
|
||||
_spectators[queue].Disconnect();
|
||||
|
||||
GGPOEvent info;
|
||||
info.code = GGPO_EVENTCODE_DISCONNECTED_FROM_PEER;
|
||||
info.u.disconnected.player = handle;
|
||||
_callbacks.on_event(&info);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,6 +449,9 @@ Peer2PeerBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt, GGPOPlayerHandle h
|
|||
info.u.connection_resumed.player = handle;
|
||||
_callbacks.on_event(&info);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -155,12 +155,17 @@ SpectatorBackend::OnUdpProtocolEvent(UdpProtocol::Event &evt)
|
|||
break;
|
||||
|
||||
case UdpProtocol::Event::Input:
|
||||
GameInput& input = evt.u.input.input;
|
||||
{
|
||||
GameInput& input = evt.u.input.input;
|
||||
|
||||
_host.SetLocalFrameNumber(input.frame);
|
||||
_host.SendInputAck();
|
||||
_inputs[input.frame % SPECTATOR_FRAME_BUFFER_SIZE] = input;
|
||||
_host.SetLocalFrameNumber(input.frame);
|
||||
_host.SendInputAck();
|
||||
_inputs[input.frame % SPECTATOR_FRAME_BUFFER_SIZE] = input;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,12 +60,12 @@ void
|
|||
Udp::Init(uint16 port, Poll *poll, Callbacks *callbacks)
|
||||
{
|
||||
_callbacks = callbacks;
|
||||
|
||||
_poll = poll;
|
||||
_poll->RegisterLoop(this);
|
||||
poll->RegisterLoop(this);
|
||||
|
||||
Log("binding udp socket to port %d.\n", port);
|
||||
_socket = CreateSocket(port, 0);
|
||||
if (_socket == INVALID_SOCKET)
|
||||
throw GGPOException("Socket creation or bind failed", GGPO_ERRORCODE_NETWORK_ERROR);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -53,7 +53,6 @@ protected:
|
|||
|
||||
// state management
|
||||
Callbacks *_callbacks;
|
||||
Poll *_poll;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,24 +22,24 @@ static const int UDP_SHUTDOWN_TIMER = 5000;
|
|||
static const int MAX_SEQ_DISTANCE = (1 << 15);
|
||||
|
||||
UdpProtocol::UdpProtocol() :
|
||||
_local_frame_advantage(0),
|
||||
_remote_frame_advantage(0),
|
||||
_queue(-1),
|
||||
_udp(NULL),
|
||||
_magic_number(0),
|
||||
_queue(-1),
|
||||
_remote_magic_number(0),
|
||||
_connected(false),
|
||||
_packets_sent(0),
|
||||
_bytes_sent(0),
|
||||
_stats_start_time(0),
|
||||
_local_frame_advantage(0),
|
||||
_remote_frame_advantage(0),
|
||||
_last_send_time(0),
|
||||
_shutdown_timeout(0),
|
||||
_disconnect_event_sent(false),
|
||||
_disconnect_timeout(0),
|
||||
_disconnect_notify_start(0),
|
||||
_disconnect_notify_sent(false),
|
||||
_disconnect_event_sent(false),
|
||||
_connected(false),
|
||||
_next_send_seq(0),
|
||||
_next_recv_seq(0),
|
||||
_udp(NULL)
|
||||
_next_recv_seq(0)
|
||||
{
|
||||
_last_sent_input.init(-1, NULL, 1);
|
||||
_last_received_input.init(-1, NULL, 1);
|
||||
|
@ -47,7 +47,7 @@ UdpProtocol::UdpProtocol() :
|
|||
|
||||
memset(&_state, 0, sizeof _state);
|
||||
memset(_peer_connect_status, 0, sizeof(_peer_connect_status));
|
||||
for (int i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) {
|
||||
_peer_connect_status[i].last_frame = -1;
|
||||
}
|
||||
memset(&_peer_addr, 0, sizeof _peer_addr);
|
||||
|
@ -123,7 +123,7 @@ UdpProtocol::SendPendingOutput()
|
|||
msg->u.input.start_frame = _pending_output.front().frame;
|
||||
msg->u.input.input_size = (uint8)_pending_output.front().size;
|
||||
|
||||
ASSERT(last.frame == -1 || last.frame + 1 == msg->u.input.start_frame);
|
||||
ASSERT(last.frame == -1 || last.frame + 1 == (int)msg->u.input.start_frame);
|
||||
for (j = 0; j < _pending_output.size(); j++) {
|
||||
GameInput ¤t = _pending_output.item(j);
|
||||
if (memcmp(current.bits, last.bits, current.size) != 0) {
|
||||
|
@ -249,7 +249,10 @@ UdpProtocol::OnLoopPoll(void *cookie)
|
|||
_udp = NULL;
|
||||
_shutdown_timeout = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
@ -455,11 +458,8 @@ UdpProtocol::LogMsg(const char *prefix, UdpMsg *msg)
|
|||
void
|
||||
UdpProtocol::LogEvent(const char *prefix, const UdpProtocol::Event &evt)
|
||||
{
|
||||
switch (evt.type) {
|
||||
case UdpProtocol::Event::Synchronzied:
|
||||
if (evt.type == UdpProtocol::Event::Synchronzied)
|
||||
Log("%s (event: Synchronzied).\n", prefix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -545,7 +545,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len)
|
|||
* of the network.
|
||||
*/
|
||||
UdpMsg::connect_status* remote_status = msg->u.input.peer_connect_status;
|
||||
for (int i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(_peer_connect_status); i++) {
|
||||
ASSERT(remote_status[i].last_frame >= _peer_connect_status[i].last_frame);
|
||||
_peer_connect_status[i].disconnected = _peer_connect_status[i].disconnected || remote_status[i].disconnected;
|
||||
_peer_connect_status[i].last_frame = MAX(_peer_connect_status[i].last_frame, remote_status[i].last_frame);
|
||||
|
@ -734,7 +734,7 @@ UdpProtocol::PumpSendQueue()
|
|||
// should really come up with a gaussian distributation based on the configured
|
||||
// value, but this will do for now.
|
||||
int jitter = (_send_latency * 2 / 3) + ((rand() % _send_latency) / 3);
|
||||
if (Platform::GetCurrentTimeMS() < _send_queue.front().queue_time + jitter) {
|
||||
if ((int)Platform::GetCurrentTimeMS() < _send_queue.front().queue_time + jitter) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ UdpProtocol::PumpSendQueue()
|
|||
}
|
||||
_send_queue.pop();
|
||||
}
|
||||
if (_oo_packet.msg && _oo_packet.send_time < Platform::GetCurrentTimeMS()) {
|
||||
if (_oo_packet.msg && _oo_packet.send_time < (int)Platform::GetCurrentTimeMS()) {
|
||||
Log("sending rogue oop!");
|
||||
_udp->SendTo((char *)_oo_packet.msg, _oo_packet.msg->PacketSize(), 0,
|
||||
(struct sockaddr *)&_oo_packet.dest_addr, sizeof _oo_packet.dest_addr);
|
||||
|
|
|
@ -375,7 +375,7 @@ void startSession(int localPort, int localPlayerNum)
|
|||
{
|
||||
WARN_LOG(NETWORK, "GGPO start sync session failed: %d", result);
|
||||
ggpoSession = nullptr;
|
||||
return;
|
||||
throw FlycastException("GGPO start sync session failed");
|
||||
}
|
||||
ggpo_idle(ggpoSession, 0);
|
||||
ggpo::localPlayerNum = localPlayerNum;
|
||||
|
@ -413,7 +413,7 @@ void startSession(int localPort, int localPlayerNum)
|
|||
{
|
||||
WARN_LOG(NETWORK, "GGPO start session failed: %d", result);
|
||||
ggpoSession = nullptr;
|
||||
return;
|
||||
throw FlycastException("GGPO network initialization failed");
|
||||
}
|
||||
|
||||
// automatically disconnect clients after 3000 ms and start our count-down timer
|
||||
|
@ -429,7 +429,7 @@ void startSession(int localPort, int localPlayerNum)
|
|||
{
|
||||
WARN_LOG(NETWORK, "GGPO cannot add local player: %d", result);
|
||||
stopSession();
|
||||
return;
|
||||
throw FlycastException("GGPO cannot add local player");
|
||||
}
|
||||
ggpo_set_frame_delay(ggpoSession, localPlayer, config::GGPODelay.get());
|
||||
|
||||
|
@ -458,6 +458,7 @@ void startSession(int localPort, int localPlayerNum)
|
|||
{
|
||||
WARN_LOG(NETWORK, "GGPO cannot add remote player: %d", result);
|
||||
stopSession();
|
||||
throw FlycastException("GGPO cannot add remote player");
|
||||
}
|
||||
DEBUG_LOG(NETWORK, "GGPO session started");
|
||||
#endif
|
||||
|
@ -616,11 +617,16 @@ std::future<bool> startNetwork()
|
|||
miniupnp.Init();
|
||||
miniupnp.AddPortMapping(SERVER_PORT, false);
|
||||
|
||||
if (config::ActAsServer)
|
||||
startSession(SERVER_PORT, 0);
|
||||
else
|
||||
// Use SERVER_PORT-1 as local port if connecting to ourselves
|
||||
startSession(config::NetworkServer.get().empty() || config::NetworkServer.get() == "127.0.0.1" ? SERVER_PORT - 1 : SERVER_PORT, 1);
|
||||
try {
|
||||
if (config::ActAsServer)
|
||||
startSession(SERVER_PORT, 0);
|
||||
else
|
||||
// Use SERVER_PORT-1 as local port if connecting to ourselves
|
||||
startSession(config::NetworkServer.get().empty() || config::NetworkServer.get() == "127.0.0.1" ? SERVER_PORT - 1 : SERVER_PORT, 1);
|
||||
} catch (...) {
|
||||
miniupnp.Term();
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
while (!synchronized && active())
|
||||
|
|
|
@ -49,6 +49,7 @@ bool MiniUPnP::Init()
|
|||
return false;
|
||||
}
|
||||
wanAddress[0] = 0;
|
||||
initialized = true;
|
||||
if (UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, wanAddress) != 0)
|
||||
WARN_LOG(NETWORK, "Cannot determine external IP address");
|
||||
DEBUG_LOG(NETWORK, "MiniUPnP: public IP is %s", wanAddress);
|
||||
|
@ -57,12 +58,15 @@ bool MiniUPnP::Init()
|
|||
|
||||
void MiniUPnP::Term()
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
DEBUG_LOG(NETWORK, "MiniUPnP::Term");
|
||||
for (const auto& port : mappedPorts)
|
||||
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.first.c_str(),
|
||||
port.second ? "TCP" : "UDP", nullptr);
|
||||
mappedPorts.clear();
|
||||
FreeUPNPUrls(&urls);
|
||||
initialized = false;
|
||||
DEBUG_LOG(NETWORK, "MiniUPnP: terminated");
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ private:
|
|||
char lanAddress[32];
|
||||
char wanAddress[32];
|
||||
std::vector<std::pair<std::string, bool>> mappedPorts;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
#else
|
||||
|
|
|
@ -2194,15 +2194,22 @@ static void gui_network_start()
|
|||
|
||||
if (networkStatus.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready)
|
||||
{
|
||||
if (networkStatus.get())
|
||||
{
|
||||
gui_state = GuiState::Closed;
|
||||
ImGui::Text("STARTING...");
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
if (networkStatus.get())
|
||||
{
|
||||
gui_state = GuiState::Closed;
|
||||
ImGui::Text("STARTING...");
|
||||
}
|
||||
else
|
||||
{
|
||||
gui_state = GuiState::Main;
|
||||
emu.unloadGame();
|
||||
}
|
||||
} catch (const FlycastException& e) {
|
||||
NetworkHandshake::instance->stop();
|
||||
gui_state = GuiState::Main;
|
||||
settings.content.path.clear();
|
||||
emu.unloadGame();
|
||||
error_msg = e.what();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2219,9 +2226,12 @@ static void gui_network_start()
|
|||
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
|
||||
{
|
||||
NetworkHandshake::instance->stop();
|
||||
networkStatus.get();
|
||||
try {
|
||||
networkStatus.get();
|
||||
} catch (const FlycastException& e) {
|
||||
}
|
||||
gui_state = GuiState::Main;
|
||||
settings.content.path.clear();
|
||||
emu.unloadGame();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
|
|
Loading…
Reference in New Issue