You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.8 KiB
156 lines
5.8 KiB
/// nat_handle_tcp_message(message_map)
|
|
// Handles incoming TCP messages from mediation server
|
|
// message_map: ds_map returned from json_parse_nat_message()
|
|
// Call this from Async Networking event
|
|
|
|
var msg = argument0;
|
|
|
|
if (!ds_exists(msg, ds_type_map)) {
|
|
exit;
|
|
}
|
|
|
|
var msg_id = ds_map_find_value(msg, "ID");
|
|
if (is_undefined(msg_id)) {
|
|
exit;
|
|
}
|
|
|
|
switch (msg_id) {
|
|
case MSG_CONNECTED:
|
|
// Connected to mediation server - start NAT detection
|
|
mediation_connected = true;
|
|
nat_state = NAT_STATE_NAT_DETECTING;
|
|
|
|
// Send NAT type request
|
|
var params = ds_map_create();
|
|
ds_map_add(params, "LocalPort", nat_local_port);
|
|
ds_map_add(params, "ClientID", nat_client_id);
|
|
nat_send_tcp_message(mediation_socket, MSG_NAT_TYPE_REQUEST, params);
|
|
ds_map_destroy(params);
|
|
break;
|
|
|
|
case MSG_NAT_TEST_BEGIN:
|
|
// Mediation server wants us to send UDP to test ports
|
|
var test_port_one = ds_map_find_value(msg, "NATTestPortOne");
|
|
var test_port_two = ds_map_find_value(msg, "NATTestPortTwo");
|
|
|
|
if (!is_undefined(test_port_one) && !is_undefined(test_port_two)) {
|
|
// Send NAT test packets to both ports
|
|
var test_params = ds_map_create();
|
|
ds_map_add(test_params, "ClientID", nat_client_id);
|
|
var test_json = json_encode_nat_message(MSG_NAT_TEST, test_params);
|
|
ds_map_destroy(test_params);
|
|
|
|
var test_buf = buffer_create(string_length(test_json) + 1, buffer_fixed, 1);
|
|
buffer_seek(test_buf, buffer_seek_start, 0);
|
|
buffer_write(test_buf, buffer_text, test_json);
|
|
|
|
network_send_udp_raw(socket, mediation_server_ip, test_port_one, test_buf, buffer_tell(test_buf));
|
|
network_send_udp_raw(socket, mediation_server_ip, test_port_two, test_buf, buffer_tell(test_buf));
|
|
|
|
buffer_delete(test_buf);
|
|
}
|
|
break;
|
|
|
|
case MSG_NAT_TYPE_RESPONSE:
|
|
// Received NAT type from server
|
|
nat_type = ds_map_find_value(msg, "NATType");
|
|
|
|
if (!is_undefined(nat_type)) {
|
|
nat_state = NAT_STATE_WAITING;
|
|
|
|
var type_name = "Unknown";
|
|
if (nat_type == NAT_TYPE_DIRECT_MAPPING) type_name = "Direct Mapping (Full Cone)";
|
|
else if (nat_type == NAT_TYPE_RESTRICTED) type_name = "Restricted";
|
|
else if (nat_type == NAT_TYPE_SYMMETRIC) type_name = "Symmetric";
|
|
|
|
// Now request connection to the game server
|
|
nat_request_connection();
|
|
}
|
|
break;
|
|
|
|
case MSG_CONNECTION_BEGIN:
|
|
// Mediation server is coordinating connection - start hole punching
|
|
var endpoint_str = ds_map_find_value(msg, "EndpointString");
|
|
var peer_nat = ds_map_find_value(msg, "NATType");
|
|
var conn_id = ds_map_find_value(msg, "ConnectionID");
|
|
|
|
if (!is_undefined(endpoint_str) && !is_undefined(peer_nat)) {
|
|
// Parse endpoint "ip:port"
|
|
var colon_pos = string_pos(":", endpoint_str);
|
|
if (colon_pos > 0) {
|
|
nat_peer_ip = string_copy(endpoint_str, 1, colon_pos - 1);
|
|
nat_peer_port = real(string_copy(endpoint_str, colon_pos + 1, string_length(endpoint_str) - colon_pos));
|
|
nat_peer_nat_type = peer_nat;
|
|
nat_connection_id = conn_id;
|
|
|
|
// Check for unsupported Symmetric-to-Symmetric
|
|
if (nat_type == NAT_TYPE_SYMMETRIC && nat_peer_nat_type == NAT_TYPE_SYMMETRIC) {
|
|
show_message("Connection not possible - both sides have Symmetric NAT");
|
|
nat_state = NAT_STATE_ERROR;
|
|
exit;
|
|
}
|
|
|
|
// Start hole punching
|
|
nat_state = NAT_STATE_PUNCHING;
|
|
nat_hole_punch_timer = 0;
|
|
nat_hole_punch_count = 0;
|
|
nat_hole_punch_received = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_CONNECTION_COMPLETE:
|
|
// Connection established!
|
|
nat_state = NAT_STATE_CONNECTED;
|
|
|
|
// Update oClient to use the discovered endpoint
|
|
server_ip = nat_peer_ip;
|
|
server_port = nat_peer_port;
|
|
|
|
// Mark as connected so game protocol can start
|
|
isConnected = 1;
|
|
connected = true; // Mark as connected to prevent duplicate connection flow in Step event
|
|
|
|
popup_text("Connected to server!");
|
|
|
|
// Send initial connection packet to server
|
|
buffer_delete(buffer);
|
|
var size, type, alignment;
|
|
size = 1024;
|
|
type = buffer_grow;
|
|
alignment = 1;
|
|
buffer = buffer_create(size, type, alignment);
|
|
buffer_seek(buffer, buffer_seek_start, 0);
|
|
buffer_write(buffer, buffer_u8, 1);
|
|
buffer_write(buffer, buffer_string, name + "," + global.multitroid_version);
|
|
buffer_write(buffer, buffer_u8, global.sax);
|
|
var bufferSize = buffer_tell(buffer);
|
|
buffer_seek(buffer, buffer_seek_start, 0);
|
|
buffer_write(buffer, buffer_s32, bufferSize);
|
|
buffer_write(buffer, buffer_u8, 1);
|
|
buffer_write(buffer, buffer_string, name + "," + global.multitroid_version);
|
|
buffer_write(buffer, buffer_u8, global.sax);
|
|
network_send_udp(socket, server_ip, server_port, buffer, buffer_tell(buffer));
|
|
|
|
// Create nametag instance
|
|
instance_create(x, y, oNametag);
|
|
|
|
// Disconnect from mediation server - we don't need it anymore
|
|
if (mediation_socket != -1) {
|
|
network_destroy(mediation_socket);
|
|
mediation_socket = -1;
|
|
mediation_connected = false;
|
|
}
|
|
break;
|
|
|
|
case MSG_SERVER_NOT_AVAILABLE:
|
|
show_message("Server not available");
|
|
nat_state = NAT_STATE_ERROR;
|
|
break;
|
|
|
|
case MSG_CONNECTION_TIMEOUT:
|
|
show_message("Connection timeout");
|
|
nat_state = NAT_STATE_ERROR;
|
|
break;
|
|
}
|