runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "tcpserver",
  "category": "io/net",
  "keywords": [
    "tcpserver",
    "tcp",
    "socket",
    "networking",
    "server",
    "loopback"
  ],
  "summary": "Create a TCP server that listens for MATLAB-compatible client connections.",
  "references": [
    "https://www.mathworks.com/help/matlab/ref/tcpserver.html"
  ],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [],
    "broadcasting": "none",
    "notes": "TCP sockets run on the host CPU. GPU-resident inputs are gathered automatically before binding sockets."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 1,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::io::net::tcpserver::tests",
    "integration": "builtins::io::net::tcpserver::tests::tcpserver_accepts_loopback_connection"
  },
  "description": "`tcpserver(address, port)` creates a TCP/IP listener that waits for clients and exposes MATLAB-compatible properties describing the socket. RunMat mirrors this behaviour: addresses may be IPv4, IPv6, or hostnames, and the function returns a handle-like struct whose fields match MATLAB’s `tcpserver` object (including `ServerAddress`, `ServerPort`, `Timeout`, `UserData`, and `BytesAvailableFcn` metadata). The builtin validates inputs, binds the socket, records configuration, and raises MATLAB-style diagnostics on failure.",
  "behaviors": [
    "`tcpserver(address, port)` binds to the requested interface; pass `\"0.0.0.0\"` or `\"::\"` to listen on every IPv4 or IPv6 adapter respectively.",
    "Ports must be in the range `0–65535`. Passing `0` requests an ephemeral OS-assigned port that RunMat reports in the returned struct.",
    "Supported name-value pairs mirror MATLAB defaults: `Timeout` (non-negative seconds, default `10`), `UserData` (stored verbatim), `Name` (defaults to `\"tcpserver:<address>:<port>\"`), and `ByteOrder` (`\"little-endian\"` or `\"big-endian\"`). Unsupported options raise `RunMat:tcpserver:InvalidNameValue`.",
    "The returned struct mirrors MATLAB properties, including connection state, callback metadata, and an internal `__tcpserver_id` identifier that future networking builtins use to locate the listener.",
    "GPU-resident scalars are gathered automatically before binding so that socket setup always executes on the host CPU.",
    "Bind failures raise `RunMat:tcpserver:BindFailed` with the OS-provided error message, preserving MATLAB-style diagnostics."
  ],
  "examples": [
    {
      "description": "Creating a loopback TCP server on a fixed port",
      "input": "srv = tcpserver(\"127.0.0.1\", 55000);\ndisp(srv.ServerAddress)\ndisp(srv.ServerPort)",
      "output": "127.0.0.1\n55000"
    },
    {
      "description": "Requesting an ephemeral port and inspecting the assigned value",
      "input": "srv = tcpserver(\"0.0.0.0\", 0);\nfprintf(\"Listening on %s:%d\\n\", srv.ServerAddress, srv.ServerPort)",
      "output": "Listening on 0.0.0.0:54873   % actual port varies by run"
    },
    {
      "description": "Configuring the timeout and storing metadata in UserData",
      "input": "srv = tcpserver(\"localhost\", 60000, \"Timeout\", 5, \"UserData\", struct(\"name\", \"demo\"));\ndisp(srv.Timeout)\ndisp(srv.UserData.name)",
      "output": "5\ndemo"
    },
    {
      "description": "Assigning a custom server name",
      "input": "srv = tcpserver(\"::1\", 45000, \"Name\", \"LoopbackServer\");\ndisp(srv.Name)",
      "output": "LoopbackServer"
    },
    {
      "description": "Selecting big-endian byte order for binary protocols",
      "input": "srv = tcpserver(\"127.0.0.1\", 45001, \"ByteOrder\", \"big-endian\");\ndisp(srv.ByteOrder)",
      "output": "big-endian"
    },
    {
      "description": "Handling invalid ports with MATLAB-style diagnostics",
      "input": "try\n    srv = tcpserver(\"127.0.0.1\", 99999);\ncatch err\n    disp(err.identifier)\n    disp(err.message)\nend",
      "output": "RunMat:tcpserver:InvalidPort\nRunMat:tcpserver:InvalidPort: tcpserver: port 99999 is outside the valid range 0–65535"
    }
  ],
  "faqs": [
    {
      "question": "What range of ports can I use?",
      "answer": "Valid ports are `0–65535`. Port `0` lets the OS choose an available ephemeral port, which RunMat reports in the returned struct."
    },
    {
      "question": "How do I discover which clients are connected?",
      "answer": "The returned struct exposes MATLAB-compatible fields (`Connected`, `ClientAddress`, `ClientPort`). Future networking builtins will use the internal `__tcpserver_id` to inspect active connections."
    },
    {
      "question": "Does RunMat support IPv6?",
      "answer": "Yes. Pass an IPv6 literal (e.g., `\"::1\"`) or hostname that resolves to IPv6. The returned `ServerAddress` reflects the bound address."
    },
    {
      "question": "Can I change the timeout after creating the server?",
      "answer": "Not yet. The current builtin records the timeout value for future builtins. A forthcoming setter will update the listener configuration."
    },
    {
      "question": "Does `tcpserver` fire callbacks like MATLAB’s `BytesAvailableFcn`?",
      "answer": "Callback-related properties are present for compatibility, and future updates will allow callers to configure them. They currently act as placeholders while connection management matures."
    },
    {
      "question": "How do I close the server?",
      "answer": "A companion builtin (planned) will accept the returned struct and release the underlying listener. Tests can invoke internal helpers until that builtin lands."
    },
    {
      "question": "Can I use GPU arrays for address or port?",
      "answer": "Yes—RunMat gathers them automatically before binding."
    },
    {
      "question": "What happens if the port is already in use?",
      "answer": "`tcpserver` raises `RunMat:tcpserver:BindFailed` with the OS error message."
    },
    {
      "question": "How do I pass additional socket options?",
      "answer": "Current support covers `Timeout`, `Name`, `UserData`, and `ByteOrder`. Additional name-value options (broadcast, reuse, keep-alive) will land alongside their corresponding provider hooks."
    },
    {
      "question": "Is TLS supported?",
      "answer": "Not directly. Combine `tcpserver` with application-layer protocol helpers or custom TLS wrappers until dedicated support lands."
    }
  ],
  "links": [
    {
      "label": "fopen",
      "url": "./fopen"
    },
    {
      "label": "fread",
      "url": "./fread"
    },
    {
      "label": "fwrite",
      "url": "./fwrite"
    },
    {
      "label": "fprintf",
      "url": "./fprintf"
    },
    {
      "label": "accept",
      "url": "./accept"
    },
    {
      "label": "close",
      "url": "./close"
    },
    {
      "label": "read",
      "url": "./read"
    },
    {
      "label": "readline",
      "url": "./readline"
    },
    {
      "label": "tcpclient",
      "url": "./tcpclient"
    },
    {
      "label": "write",
      "url": "./write"
    }
  ],
  "source": {
    "label": "crates/runmat-runtime/src/builtins/io/net/tcpserver.rs",
    "url": "crates/runmat-runtime/src/builtins/io/net/tcpserver.rs"
  },
  "gpu_residency": "No. `tcpserver` is a host-side operation. RunMat transparently gathers GPU scalars before binding the socket, so keeping address or port values on the GPU provides no performance benefit.",
  "gpu_behavior": [
    "Networking occurs entirely on the host CPU. If the address or port arguments originate on the GPU, RunMat gathers them before binding the socket. The struct returned by `tcpserver` is always CPU-resident, and acceleration providers do not need to implement any hooks for this builtin."
  ]
}