ludic/packages/ludic.net/session.ludic

106 lines
3.2 KiB
Text

# session.ludic - hosting, joining and leaving. The host is pid 1 and hands out 2 upwards; this
# machine's pid is what its packets say. A token picked by the host names the session.
var net__why: int = 0
# open a socket on `port` and take guests; false (net_why) when the port is taken
export function net_host(port: int, token: int) -> bool {
net__init()
if net_live() { return true }
net__sock = NetSocket.open(port)
if net__sock <= 0 {
net__sock = 0
net__why = NET_WHY_PORT_TAKEN
return false
}
for i in 0 .. NET_PEERS { np_close(i) }
net_become_host(token)
net__log(`hosting on port {NetSocket.port(net__sock)}`)
net_room_host()
return true
}
# dial a host at an address; the hello (net_hello_set) goes until a welcome or a refusal
export function net_join(ip: int, port: int) -> bool {
net__init()
if net_live() { return false }
if not net__socket() { return false }
for i in 0 .. NET_PEERS { np_close(i) }
net__token = 0
net__my_pid = 0
net__state = NET_JOINING
net_dial(ip, port)
net__log(`joining {Udp.ip_text(ip)}:{port}`)
return true
}
function net__socket() -> bool {
if net__sock <= 0 { net__sock = NetSocket.open(0) }
if net__sock > 0 { return true }
net__sock = 0
net__why = NET_WHY_NO_SOCKET
return false
}
# the message just written is the hello: what a host is asked to let this machine in with
export function net_hello_set() -> void {
net__init()
nb_copy(net__hello_b, 0, net__wb, 0, net__wl)
net__hello_l = net__wl
if net__hello_l > NET_MTU - 40 { net__hello_l = NET_MTU - 40 }
}
# (again) to that address, with a fresh connection and the hello sent anew
export function net_dial(ip: int, port: int) -> void {
net__init()
np_close(0)
net__join_ip = ip
net__join_port = port
net__open(0, ip, port, 1)
net__hello_t = -1.0
}
# a host that set out on a new trip, or a new host: the same socket asks to be let in there
export function net_follow(ip: int, port: int) -> void {
net_dial(ip, port)
net__token = 0
net__my_pid = 0
net__state = NET_JOINING
}
# the old host is gone and this machine keeps the socket, alone (it may become the host)
export function net_stand_alone() -> void { net__state = NET_IDLE }
export function net_become_host(token: int) -> void {
net__init()
net__state = NET_HOSTING
net__my_pid = 1
net__next_pid = 2
net__token = token
}
# a welcome: this machine is `pid` in the session `token`
export function net_joined_as(token: int, pid: int) -> void {
net__token = token
net__my_pid = pid
net__state = NET_JOINED
net__wait_more = 0
}
# the host lets the stranger in `slot` in: its pid, from 2 upwards
export function net_accept(slot: int) -> int {
if net__state != NET_HOSTING or not net_peer_on(slot) { return 0 }
let p = net__peers[slot]
if p.pid >= 2 { return p.pid }
p.pid = net__next_pid
net__next_pid += 1
return p.pid
}
# a slow host is given this many more seconds to answer (a map switch, a matchmaker)
export function net_hello_wait(secs: int) -> void { net__wait_more = secs }
# a room code: joining, with no address yet - the matchmaker's answer brings one
function net__wait_for_host() -> void {
net__state = NET_JOINING
net__hello_t = 0.0
}