70 lines
2.4 KiB
GDScript3
70 lines
2.4 KiB
GDScript3
|
|
class_name EndpointParser
|
||
|
|
extends RefCounted
|
||
|
|
|
||
|
|
const DEFAULT_PORT: int = 7777
|
||
|
|
|
||
|
|
|
||
|
|
static func parse(value: String, default_port: int = DEFAULT_PORT) -> ConnectionEndpoint:
|
||
|
|
var result := ConnectionEndpoint.new()
|
||
|
|
result.original_display = value.strip_edges()
|
||
|
|
result.port = default_port
|
||
|
|
if default_port < 1 or default_port > 65535:
|
||
|
|
result.error_message = "The configured default port is invalid."
|
||
|
|
return result
|
||
|
|
var input: String = result.original_display
|
||
|
|
if input.is_empty():
|
||
|
|
result.error_message = "Enter a hostname or IP address."
|
||
|
|
return result
|
||
|
|
|
||
|
|
var host: String = ""
|
||
|
|
var port_text: String = ""
|
||
|
|
if input.begins_with("["):
|
||
|
|
var closing: int = input.find("]")
|
||
|
|
if closing < 0:
|
||
|
|
result.error_message = "The IPv6 address is missing a closing bracket."
|
||
|
|
return result
|
||
|
|
host = input.substr(1, closing - 1).strip_edges()
|
||
|
|
var suffix: String = input.substr(closing + 1).strip_edges()
|
||
|
|
if not suffix.is_empty():
|
||
|
|
if not suffix.begins_with(":") or suffix.length() == 1:
|
||
|
|
result.error_message = "Use [IPv6]:port for an IPv6 port."
|
||
|
|
return result
|
||
|
|
port_text = suffix.substr(1).strip_edges()
|
||
|
|
elif input.contains("[") or input.contains("]"):
|
||
|
|
result.error_message = "IPv6 brackets are malformed."
|
||
|
|
return result
|
||
|
|
else:
|
||
|
|
var colon_count: int = input.count(":")
|
||
|
|
if colon_count == 1:
|
||
|
|
var separator: int = input.rfind(":")
|
||
|
|
host = input.substr(0, separator).strip_edges()
|
||
|
|
port_text = input.substr(separator + 1).strip_edges()
|
||
|
|
else:
|
||
|
|
# Zero colons is a hostname/IPv4 host. More than one is a raw
|
||
|
|
# IPv6 host; an explicit port for it must use brackets.
|
||
|
|
host = input.strip_edges()
|
||
|
|
|
||
|
|
if host.is_empty():
|
||
|
|
result.error_message = "The hostname or IP address is empty."
|
||
|
|
return result
|
||
|
|
if host.contains(" ") or host.contains("\t") or host.contains("\n"):
|
||
|
|
result.error_message = "The hostname or IP address contains whitespace."
|
||
|
|
return result
|
||
|
|
if not port_text.is_empty():
|
||
|
|
if not port_text.is_valid_int():
|
||
|
|
result.error_message = "The port must be a number from 1 to 65535."
|
||
|
|
return result
|
||
|
|
result.port = int(port_text)
|
||
|
|
if result.port < 1 or result.port > 65535:
|
||
|
|
result.error_message = "The port must be from 1 to 65535."
|
||
|
|
return result
|
||
|
|
|
||
|
|
result.host = host.to_lower()
|
||
|
|
var is_ipv6: bool = result.host.contains(":")
|
||
|
|
result.normalized_display = (
|
||
|
|
"[%s]:%d" % [result.host, result.port]
|
||
|
|
if is_ipv6
|
||
|
|
else "%s:%d" % [result.host, result.port]
|
||
|
|
)
|
||
|
|
return result
|