Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

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