net/server.fz
# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation. If not, see <https://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------
#
# Tokiwa Software GmbH, Germany
#
# Source code of Fuzion standard library feature net.server
#
# -----------------------------------------------------------------------
# server -- effect for storing a bound - and in the
# case of TCP, listening - socket descriptor.
#
# Basic usage description:
# 1) Initialize the server, e.g. like this:
# `server family.ipv4 protocol.tcp 8080`
# 2) accept a new connection:
# `server.accept`
#
module:public server(
state outcome i32,
p protocol.val
) : effect
is
# get the last error that occurred
#
public last_error => state.bind unit (_ -> unit)
# is the server running?
#
public is_active =>
state.ok
# close server, stop listening on port
#
public close =>
_ := state.bind unit d->
(match fuzion.sys.net.close d
unit =>
server (error "not initialized") nil
error error =>
server error nil
).replace
# accept new TCP connection
# does nothing for UDP etc.
# blocks until connection is established
#
# NYI: accept that returns a Future and does not block
#
public accept outcome net.connection =>
state.bind net.connection d->
match fuzion.sys.net.accept d
desc i32 =>
net.connections.add desc
net.connection desc
e error =>
# NYI we may not need to close server on every error...
(server e nil).replace
e
# open new server bound to the any address listening on port
# closes currently installed server
#
# NYI blocking / none blocking
#
public type.start(f net.family.val, p net.protocol.val, port u16) outcome unit =>
any_addr := (
match f
net.family.ipv4 => "0.0.0.0"
net.family.ipv6 => "0:0:0:0:0:0:0:0"
)
net.server.start f p any_addr port
# open new server bound to addr listening on port
# closes currently installed server
#
# NYI blocking / none blocking
#
public type.start(f net.family.val, p net.protocol.val, addr String, port u16) outcome unit =>
net.server.close
backlog := 10
s := net.socket_type.by_protocol p
# bind to port
(fuzion.sys.net.bind f.as_num s.as_num p.as_num addr port)
.bind i32 sd->
match p
net.protocol.tcp =>
# listen
listen_res := fzE_listen sd backlog
if listen_res != 0
_ := fuzion.sys.net.close sd
error "listening on socket failed with error $listen_res."
else
sd
* =>
sd
.bind unit desc->
(net.server desc p).replace
# get currently installed server from env
#
public server =>
if !server.is_instated
(server (error "not initialized") nil).default
server.env
last changed: 2025-01-23