102 lines
3.7 KiB
Text
102 lines
3.7 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.
|
|
|
|
# open a socket on `port` and take guests; false (net_why) when the port is taken
|
|
@alloc_ok("once per party hosted")
|
|
export function net_host(net_st: mut NetState, port: int, token: int) -> bool {
|
|
if net_live(net_st) { return true }
|
|
net_st.net__sock = NetSocket.open(port)
|
|
if net_st.net__sock <= 0 {
|
|
net_st.net__sock = 0
|
|
net_st.net__why = NET_WHY_PORT_TAKEN
|
|
return false
|
|
}
|
|
for i in 0 .. NET_PEERS { np_close(net_st, i) }
|
|
net_become_host(net_st, token)
|
|
net__log(`hosting on port {NetSocket.port(net_st.net__sock)}`)
|
|
net_room_host(net_st)
|
|
return true
|
|
}
|
|
|
|
# dial a host at an address; the hello (net_hello_set) goes until a welcome or a refusal
|
|
@alloc_ok("once per join")
|
|
export function net_join(net_st: mut NetState, ip: int, port: int) -> bool {
|
|
if net_live(net_st) { return false }
|
|
if not net__socket(net_st) { return false }
|
|
for i in 0 .. NET_PEERS { np_close(net_st, i) }
|
|
net_st.net__token = 0
|
|
net_st.net__my_pid = 0
|
|
net_st.net__state = NET_JOINING
|
|
net_dial(net_st, ip, port)
|
|
net__log(`joining {Udp.ip_text(ip)}:{port}`)
|
|
return true
|
|
}
|
|
|
|
function net__socket(net_st: mut NetState) -> bool {
|
|
if net_st.net__sock <= 0 { net_st.net__sock = NetSocket.open(0) }
|
|
if net_st.net__sock > 0 { return true }
|
|
net_st.net__sock = 0
|
|
net_st.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(net_st: mut NetState) -> void {
|
|
nb_copy(net_st.net__hello_b, 0, net_st.net__wb, 0, net_st.net__wl)
|
|
net_st.net__hello_l = net_st.net__wl
|
|
if net_st.net__hello_l > NET_MTU - 40 { net_st.net__hello_l = NET_MTU - 40 }
|
|
}
|
|
|
|
# (again) to that address, with a fresh connection and the hello sent anew
|
|
export function net_dial(net_st: mut NetState, ip: int, port: int) -> void {
|
|
np_close(net_st, 0)
|
|
net_st.net__join_ip = ip
|
|
net_st.net__join_port = port
|
|
net__open(net_st, 0, ip, port, 1)
|
|
net_st.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(net_st: mut NetState, ip: int, port: int) -> void {
|
|
net_dial(net_st, ip, port)
|
|
net_st.net__token = 0
|
|
net_st.net__my_pid = 0
|
|
net_st.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(net_st: mut NetState) -> void { net_st.net__state = NET_IDLE }
|
|
|
|
export function net_become_host(net_st: mut NetState, token: int) -> void {
|
|
net_st.net__state = NET_HOSTING
|
|
net_st.net__my_pid = 1
|
|
net_st.net__next_pid = 2
|
|
net_st.net__token = token
|
|
}
|
|
|
|
# a welcome: this machine is `pid` in the session `token`
|
|
export function net_joined_as(net_st: mut NetState, token: int, pid: int) -> void {
|
|
net_st.net__token = token
|
|
net_st.net__my_pid = pid
|
|
net_st.net__state = NET_JOINED
|
|
net_st.net__wait_more = 0
|
|
}
|
|
|
|
# the host lets the stranger in `slot` in: its pid, from 2 upwards
|
|
export function net_accept(net_st: mut NetState, slot: int) -> int {
|
|
if net_st.net__state != NET_HOSTING or not net_peer_on(net_st, slot) { return 0 }
|
|
let p = net_st.net__peers[slot]
|
|
if p.pid >= 2 { return p.pid }
|
|
p.pid = net_st.net__next_pid
|
|
net_st.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(net_st: mut NetState, secs: int) -> void { net_st.net__wait_more = secs }
|
|
|
|
# a room code: joining, with no address yet - the matchmaker's answer brings one
|
|
function net__wait_for_host(net_st: mut NetState) -> void {
|
|
net_st.net__state = NET_JOINING
|
|
net_st.net__hello_t = 0.0
|
|
}
|