(index ("socket" 0) ("socket" 0) ("socket?" 0) ("socket-fileno" 0) ("socket-family" 0) ("socket-type" 0) ("socket-protocol" 0) ("af/inet" 1488) ("af/inet6" 1488) ("af/unix" 1488) ("af/unspec" 1488) ("integer->address-family" 1488) ("address-family->integer" 1488) ("sock/stream" 2016) ("sock/dgram" 2016) ("sock/raw" 2016) ("integer->socket-type" 2016) ("socket-type->integer" 2016) ("ipproto/tcp" 2329) ("ipproto/udp" 2329) ("integer->protocol-type" 2329) ("protocol-type->integer" 2329) ("sockaddr" 2613) ("sockaddr?" 2613) ("sockaddr-family" 2613) ("sockaddr-address" 2613) ("sockaddr-port" 2613) ("sockaddr-path" 2613) ("sockaddr->string" 2613) ("inet-address" 4221) ("unix-address" 5107) ("address-information" 5398) ("ai/numerichost" 5398) ("ai/passive" 5398) ("ai/canonname" 5398) ("addrinfo" 9970) ("addrinfo?" 9970) ("addrinfo-family" 9970) ("addrinfo-socktype" 9970) ("addrinfo-protocol" 9970) ("addrinfo-address" 9970) ("addrinfo-canonname" 9970) ("addrinfo-flags" 9970) ("name-information" 11134) ("ni/numerichost" 11134) ("ni/numericserv" 11134) ("ni/dgram" 11134) ("ni/namereqd" 11134) ("ni/nofqdn" 11134) ("socket-connect" 13835) ("socket-connect/ai" 13835) ("socket-bind" 16513) ("socket-listen" 17279) ("socket-accept" 17544) ("socket-accept-ready?" 17544) ("socket-shutdown" 18400) ("shut/rd" 18400) ("shut/wr" 18400) ("shut/rdwr" 18400) ("socket-close" 19122) ("socket-close*" 19364) ("socket-name" 19772) ("socket-peer-name" 20119) ("socket-receive!" 20657) ("socket-receive-ready?" 20657) ("socket-receive" 21753) ("socket-receive-from!" 22039) ("socket-receive-from" 22359) ("socket-send" 22724) ("socket-send-to" 23440) ("socket-send-all" 23730) ("socket-i/o-ports" 24435) ("socket-i/o-port->socket" 27802) ("socket-abandon-port" 28259) ("socket-connect-timeout" 28790) ("socket-accept-timeout" 28790) ("socket-receive-timeout" 28790) ("socket-send-timeout" 28790) ("socket-send-buffer-size" 29396) ("socket-send-size" 29396) ("socket-receive-buffer-size" 29396) ("so-reuse-address?" 30607) ("so-debug?" 30607) ("so-keep-alive?" 30607) ("so-dont-route?" 30607) ("so-broadcast?" 30607) ("so-oob-inline?" 30607) ("so-accept-connections?" 30607) ("so-send-buffer" 30607) ("so-receive-buffer" 30607) ("so-send-low-water" 30607) ("so-receive-low-water" 30607) ("so-error" 30607) ("so-type" 30607) ("tcp-no-delay?" 32364) ("tcp-no-push?" 32364) ("tcp-no-options?" 32364) ("tcp-keep-alive" 32364) ("tcp-max-segment-size" 32364) ("ip-header-included?" 32896) ("ip-type-of-service" 32896) ("ip-time-to-live" 32896) ("ipv6-v6-only?" 33277) ("set-socket-option" 33528) ("get-socket-option" 34566) ("so/reuseaddr" 35825) ("so/debug" 35825) ("so/acceptconn" 35825) ("so/keepalive" 35825) ("so/dontroute" 35825) ("so/broadcast" 35825) ("so/linger" 35825) ("so/oobinline" 35825) ("so/sndbuf" 35825) ("so/rcvbuf" 35825) ("so/sndlowat" 35825) ("so/rcvlowat" 35825) ("so/sndtimeo" 35825) ("so/rcvtimeo" 35825) ("so/error" 35825) ("so/type" 35825) ("so/useloopback" 35825) ("so/reuseport" 35825) ("so/timestamp" 35825) ("so/exclusiveaddruse" 35825) ("tcp/nodelay" 36826) ("tcp/nopush" 36826) ("tcp/noopt" 36826) ("tcp/keepalive" 36826) ("tcp/maxseg" 36826) ("ip/options" 37183) ("ip/hdrincl" 37183) ("ip/tos" 37183) ("ip/ttl" 37183) ("ip/mtu" 37183) ("ip/mtu-discover" 37183) ("ip/pktinfo" 37183) ("ip/recverr" 37183) ("ip/recvtos" 37183) ("ip/recvttl" 37183) ("ip/router-alert" 37183) ("ip/recvopts" 37183) ("ip/recvretopts" 37183) ("ip/retopts" 37183) ("ip/recvdstaddr" 37183) ("ip/multicast-if" 37183) ("ip/multicast-ttl" 37183) ("ip/multicast-loop" 37183) ("ip/add-membership" 37183) ("ip/drop-membership" 37183) ("sol/socket" 38212) ("ipproto/ip" 38212) ("ipproto/ipv6" 38212) ("ipproto/tcp" 38212) ("ipproto/icmp" 38212) ("ipproto/udp" 38212))
(def (sig (record "socket" (id socket)) (procedure "(socket family type #!optional (protocol 0))" (id socket)) (procedure "(socket? so)" (id socket?)) (procedure "(socket-fileno so)" (id socket-fileno)) (procedure "(socket-family so)" (id socket-family)) (procedure "(socket-type so)" (id socket-type)) (procedure "(socket-protocol so)" (id socket-protocol))) (p "Socket objects.  You construct a socket using the " (tt "socket") " procedure, passing an address family " (tt "af/*") " constant for " (tt "family") " (IPv4, IPv6) and a socket type " (tt "sock/*") " constant for socket " (tt "type") " (TCP, UDP).  " (tt "protocol") " should almost always be zero, unless you are creating raw sockets; it is implicit in the socket type.  Sockets take up a file descriptor in the system until closed, which may or may not happen automatically on error. All sockets are created in non-blocking mode.") (p "Accessors:") (dl (dt (tt "socket-fileno")) (dd "The socket's file descriptor.") (dt (tt "socket-family")) (dd "The socket family, an integer constant.") (dt (tt "socket-type")) (dd "The socket type, an integer constant.") (dt (tt "socket-protocol")) (dd "The socket protocol, an integer constant.")) (p "Note that sockets are also implicitly created by " (tt "socket-connect/ai") " and " (tt "socket-accept") ".") (p "Example:") (pre "(socket af/inet sock/stream)\n  ; => #<socket fd:19 af/inet sock/stream>\n(socket af/inet6 sock/dgram)\n  ; => #<socket fd:20 af/inet6 sock/dgram>"))
(def (sig (constant "af/inet" (id af/inet)) (constant "af/inet6" (id af/inet6)) (constant "af/unix" (id af/unix)) (constant "af/unspec" (id af/unspec)) (procedure "(integer->address-family int)" (id integer->address-family)) (procedure "(address-family->integer sym)" (id address-family->integer))) (p "Address family constants for socket creation.  It is possible to convert between integer constants and symbols using the provided procedures, but this is just for debugging convenience; the API requires integer constants."))
(def (sig (constant "sock/stream" (id sock/stream)) (constant "sock/dgram" (id sock/dgram)) (constant "sock/raw" (id sock/raw)) (procedure "(integer->socket-type int)" (id integer->socket-type)) (procedure "(socket-type->integer sym)" (id socket-type->integer))) (p "Socket type constants for socket creation."))
(def (sig (constant "ipproto/tcp" (id ipproto/tcp)) (constant "ipproto/udp" (id ipproto/udp)) (procedure "(integer->protocol-type int)" (id integer->protocol-type)) (procedure "(protocol-type->integer sym)" (id protocol-type->integer))) (p "Protocol constants for socket creation."))
(def (sig (record "sockaddr" (id sockaddr)) (procedure "(sockaddr? sa)" (id sockaddr?)) (procedure "(sockaddr-family sa)" (id sockaddr-family)) (procedure "(sockaddr-address sa)" (id sockaddr-address)) (procedure "(sockaddr-port sa)" (id sockaddr-port)) (procedure "(sockaddr-path sa)" (id sockaddr-path)) (procedure "(sockaddr->string sa)" (id sockaddr->string))) (p "The socket address object.  " (tt "sockaddr") " is used throughout the BSD sockets API to represent the address of a local or remote socket endpoint.") (p "The most convenient constructor for Internet socket addresses is " (tt "inet-address") ".  The fundamental Internet socket address constructor is " (tt "address-information") ", which is more powerful but also more complex to use.  For UNIX sockets, use " (tt "unix-address") ".") (p "Socket address object accessors are:") (dl (dt (tt "sockaddr-family")) (dd "returns the socket address family as an integer constant, e.g. " (tt "af/inet") ".") (dt (tt "sockaddr-address")) (dd "returns the address of a socket as a string (for Internet sockets, this is the IP address).") (dt (tt "sockaddr-port")) (dd "returns the socket port for Internet sockets; it is an error to call it on another type of socket.") (dt (tt "sockaddr-path")) (dd "returns the pathname for UNIX sockets, or an error for other socket types.") (dt (tt "sockaddr->string")) (dd "returns a compact representation of the socket address as a string.  For Internet sockets, it returns \"address\" when port is 0; otherwise, it returns \"address:port\" for IPv4 addresses and \"[address]:port\" for IPv6 addresses.")))
(def (sig (procedure "(inet-address addr port)" (id inet-address))) (p "Returns a " (tt "sockaddr") " object constructed from IP address " (tt "addr") " (a string) and port " (tt "port") " (a number or numeric string).  If the address or port input is invalid, an error is raised.") (p "If " (tt "addr") " is " (tt "#f") ", the unspecified address is used (\"::\" or \"0.0.0.0\"). If " (tt "port") " is " (tt "#f") ", the unspecified port is used (integer 0). It is an error for both " (tt "addr") " and " (tt "port") " to be unspecified.") (p "Note that when IPv6 is preferred on your system, the unspecified address " (tt "#f") " is typically \"::\" and the resulting object will be of family " (tt "af/inet6") ".  This may not be what you want, so it is a good idea to specify which unspecified address (yes, really) you mean -- \"::\" or \"0.0.0.0\" -- in lieu of " (tt "#f") "."))
(def (sig (procedure "(unix-address path)" (id unix-address))) (p "Returns a " (tt "sockaddr") " object constructed from the pathname " (tt "path") ", suitable for use with a socket in address family " (tt "af/unix") ". Throws an error if UNIX sockets are not supported on your platform."))
(def (sig (procedure "(address-information node service #!key family (type sock/stream) protocol flags)" (id address-information)) (constant "ai/numerichost" (id ai/numerichost)) (constant "ai/passive" (id ai/passive)) (constant "ai/canonname" (id ai/canonname))) (p "Looks up node name and service name and translates them to numeric values.  Returns a list of " (tt "addrinfo") " objects, each of which contains a socket address (" (tt "sockaddr") " object) suitable for use in socket calls such as " (tt "socket-bind") " and " (tt "socket-connect") ".") (p (tt "node") " is either a node name (string) or IP address (string). " (tt "service") " may be a string representing a service name or port number, or an integer.  If " (tt "node") " is " (tt "#f") ", it is treated as the loopback address; however, if " (tt "ai/passive") " is set it is treated as the unspecified address.  If " (tt "service") " is " (tt "#f") ", it is treated as unspecified (0).") (p "Keyword arguments accept numeric constants and restrict the returned addresses accordingly:") (dl (dt (tt "family")) (dd "Address family, either " (tt "af/inet") " or " (tt "af/inet6") ", defaulting to " (tt "#f") ".  If " (tt "#f") ", both IPv6 and IPv4 addresses may be returned, depending on your system's configuration and IP stack.") (dt (tt "type")) (dd "Socket type; usually " (tt "sock/stream") " or " (tt "sock/dgram") ", defaulting to " (tt "sock/stream") ".  Can be " (tt "#f") ", but results may vary between systems, so it is safer to specify one.  See examples.") (dt (tt "protocol")) (dd "Protocol type, usually " (tt "#f") ".  Can also be " (tt "ipproto/tcp") " or " (tt "ipproto/udp") "; however, some systems (such as Windows) do not construct a proper socket address when " (tt "type") " is unspecified, so it is safer to just provide a value for " (tt "type") " and leave this as " (tt "#f") ".")) (p "The behavior of " (tt "address-information") " can be influenced by the value of " (tt "flags") ", which should be the " (tt "bitwise-ior") " (or simply " (tt "+") ") of any of the following constants:") (dl (dt (tt "ai/numerichost")) (dd "The host is an IP address string; do not attempt to resolve it.") (dt (tt "ai/passive")) (dd "The socket address is intended to be used in a call to bind().  The only difference is that an address of " (tt "#f") " is translated into the unspecified address \"::\" or \"0.0.0.0\", rather than the loopback address.") (dt (tt "ai/canonname")) (dd "Include the canonical (usually FQDN) hostname in the " (tt "addrinfo") " object.  If not provided, that field will be " (tt "#f") ".")) (p "Examples:") (pre "(address-information \"localhost\" \"http\")\n  ; => (#<addrinfo \"[::1]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"[fe80::1%lo0]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"127.0.0.1:80\" af/inet sock/stream ipproto/tcp>)\n(address-information \"127.0.0.1\" 53 type: sock/dgram)\n  ; => (#<addrinfo \"127.0.0.1:53\" af/inet sock/stream ipproto/udp>)\n(address-information \"he.net\" 80)\n  ; => (#<addrinfo \"[2001:470:0:76::2]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"216.218.186.2:80\" af/inet sock/stream ipproto/tcp>)\n(address-information \"he.net\" 80 type: #f)\n  ; Possible response on UNIX -- return both TCP and UDP addresses.\n  ; Might also just return TCP.\n  ; => (#<addrinfo \"[2001:470:0:76::2]:80\" af/inet6 sock/dgram ipproto/udp>\n        #<addrinfo \"[2001:470:0:76::2]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"216.218.186.2:80\" af/inet sock/dgram ipproto/udp>\n        #<addrinfo \"216.218.186.2:80\" af/inet sock/stream ipproto/tcp>)\n  ; Possible response on Windows -- socket addresses are not valid for use\n  ; => (#<addrinfo \"[2001:470:0:76::2]:80\" af/inet6 0 0>\n        #<addrinfo \"216.218.186.2:80\" af/inet 0 0>)\n(address-information #f \"http\")\n  ; => (#<addrinfo \"[::1]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"127.0.0.1:80\" af/inet sock/stream ipproto/tcp>)\n(address-information #f \"http\" flags: ai/passive)\n  ; => (#<addrinfo \"[::]:80\" af/inet6 sock/stream ipproto/tcp>\n        #<addrinfo \"0.0.0.0:80\" af/inet sock/stream ipproto/tcp>)\n  ; As an example of inconsistent per-platform behavior, note that\n  ; recent Ubuntu among others returns the above in reverse order.\n(address-information \"allie\" 0 flags: ai/canonname)\n  ; => (#<addrinfo \"192.168.1.7\" af/inet sock/stream ipproto/tcp\n                   canonical: \"allie.xorinia.dim\">)\n(address-information #f #f)\n  ; => ()"))
(def (sig (record "addrinfo" (id addrinfo)) (procedure "(addrinfo? ai)" (id addrinfo?)) (procedure "(addrinfo-family ai)" (id addrinfo-family)) (procedure "(addrinfo-socktype ai)" (id addrinfo-socktype)) (procedure "(addrinfo-protocol ai)" (id addrinfo-protocol)) (procedure "(addrinfo-address ai)" (id addrinfo-address)) (procedure "(addrinfo-canonname ai)" (id addrinfo-canonname)) (procedure "(addrinfo-flags ai)" (id addrinfo-flags))) (p "Address information record returned by " (tt "address-information") ".") (ul (li (tt "addrinfo-address") " is the " (tt "sockaddr") " socket address object;") (li (tt "addrinfo-family") ", " (tt "addrinfo-socktype") " and " (tt "addrinfo-protocol") " are numeric constants in the " (tt "af/") ", " (tt "sock/") " and " (tt "ipproto/") " families respectively;") (li (tt "addrinfo-canonname") " is the canonical (FQDN) name of this host and is present only if the " (tt "ai/canonname") " flag was used; otherwise " (tt "#f") ";") (li (tt "addrinfo-flags") " is the bitwise OR of " (tt "ai/") " flags used when constructing this object.  The system may set certain flags itself so this is probably not reliably useful.")))
(def (sig (procedure "(name-information saddr #!optional (flags 0))" (id name-information)) (constant "ni/numerichost" (id ni/numerichost)) (constant "ni/numericserv" (id ni/numericserv)) (constant "ni/dgram" (id ni/dgram)) (constant "ni/namereqd" (id ni/namereqd)) (constant "ni/nofqdn" (id ni/nofqdn))) (p "Given a socket address object " (tt "saddr") ", performs a reverse-lookup to obtain the node and service names, returning them as the pair " (tt "(\"node\" . \"service\")") ".  If hostname lookup fails, the numeric representation of the address is returned as a string.  If service number lookup fails, it is returned as an integer.") (p "The socket address object is usually constructed with " (tt "inet-address") " or obtained from a socket call, e.g. " (tt "socket-peer-name") ".  As a convenience in socket 0.2.1 and later, if " (tt "saddr") " is a string, it is converted to a socket address object with " (tt "(inet-address saddr #f)") ".") (p "The behavior of " (tt "name-information") " can be influenced by FLAGS.  FLAGS may be the " (tt "bitwise-ior") " (or simply " (tt "+") ") of the following constants:") (dl (dt (tt "ni/numerichost")) (dd "Do not resolve the node address to a name; instead, return the canonical string representation of the address, as in " (tt "inet_ntop()") ".  " (tt "(sockaddr-address saddr)") " returns the same representation.") (dt (tt "ni/numericserv")) (dd "Do not attempt to resolve the service number to a name.") (dt (tt "ni/namereqd")) (dd "If hostname lookup fails, raise an error.") (dt (tt "ni/nofqdn")) (dd "Return only the local part of the hostname for local hosts.") (dt (tt "ni/dgram")) (dd "Look up the service as a datagram service.  A few service names may differ between TCP and UDP.")) (p "Examples:") (pre "(name-information (inet-address \"127.0.0.1\" 80))\n  ; => (\"localhost\" . \"http\")\n(name-information (inet-address \"::1\" 80))\n  ; => (\"localhost\" . \"http\")\n(name-information (inet-address \"::1\" #f))\n  ; => (\"localhost\" . 0)\n(name-information \"::1\")\n  ; => (\"localhost\" . 0)\n(name-information (inet-address \"::1\" 80) ni/numerichost)\n  ; => (\"::1\" . \"http\")\n(name-information (inet-address \"::1\" 80) (+ ni/numerichost ni/numericserv))\n  ; => (\"::1\" . 80)\n(name-information (inet-address \"127.0.0.2\" 80))\n  ; => (\"127.0.0.2\" . \"http\")\n(name-information (inet-address \"127.0.0.2\" 80) ni/namereqd)\n  ; => error: nodename nor servname provided, or not known\n(name-information (inet-address \"2001:470:0:64::2\" 80) ni/numericserv)\n  ; => (\"ipv6.he.net\" . 80)\n(name-information (socket-peer-name s))  ;; s being an accept()ed socket\n  ; => (\"taco.universe12.dim\" . 31828)"))
(def (sig (procedure "(socket-connect so saddr)" (id socket-connect)) (procedure "(socket-connect/ai ais)" (id socket-connect/ai))) (p (tt "socket-connect") " connects to the remote socket address " (tt "saddr") " over the socket " (tt "so") ".  Upon completion, " (tt "so") " will be connected; on connection failure an error is thrown.  The return value is unspecified.  This is a non-blocking operation; other SRFI-18 threads can continue to run.") (p "If connection fails due to refusal, network down, unreachable host or system enforced timeout, it raises a \"transient\" error of type " (tt "(exn i/o net transient)") ", signalling the connection can be retried later if desired.  A connection may also raise an " (tt "(exn i/o net timeout)") " error after " (tt "(socket-connect-timeout)") " milliseconds.  If a fatal error occurs, it raises an error of type " (tt "(exn i/o net)") ", like all other socket procedures.") (p (tt "socket-connect/ai") " connects to the addresses in the " (tt "addrinfo") " list " (tt "ais") " sequentially until the connection succeeds or there are no more addresses.  If a fatal error occurs while connecting, it aborts immediately; but transient or timeout errors cause it to try the next address.  If all attempts fail, the error raised is that of the last attempt.  On success, the return value is a fresh connected socket of the appropriate family and type.") (p "Examples:") (pre " ;; Connect to localhost:22 over IPv4.\n (define so (socket af/inet sock/stream))\n (socket-connect so (inet-address \"127.0.0.1\" 22))") (pre " ;; Connect to localhost:22 over IPv6.\n (define so (socket af/inet6 sock/stream))\n (socket-connect so (inet-address \"::1\" 22))") (pre " ;; Connect to localhost:22 over IPv4 and return the connected socket.\n (socket-connect/ai\n   (address-information \"localhost\" 22 family: af/inet))\n ; => #<socket fd:8 af/inet sock/stream>") (pre " ;; Try to connect to localhost:ssh via any address family.  \n ;; In this case, address-information may return the IPv6 loopback\n ;; address \"::1\" and perhaps \"fe80::1\", along with the usual \n ;; IPv4 \"127.0.0.1\".  socket-connect/ai will try them all in order\n ;; and return a new connected socket.  For illustrative purposes\n ;; we use socket-peer-name to show where we connected.\n\n (socket-peer-name\n  (socket-connect/ai (address-information \"localhost\" \"ssh\")))\n ; => #<sockaddr \"[::1]:22\">         ;; If ssh listening on ::1\n ; => #<sockaddr \"[fe80::1%lo0]:22\"> ;; If listening on link-local loopback\n ; => #<sockaddr \"127.0.0.1:22\">     ;; If listening on 127.0.0.1 only\n ; => error: connection refused      ;; If ssh isn't running"))
(def (sig (procedure "(socket-bind so saddr)" (id socket-bind))) (p "Binds socket " (tt "so") " to socket address " (tt "saddr") ".  The return value is unspecified.") (pre "; Bind to the IPv4 unspecified address on port 8000.\n(define so (socket af/inet sock/stream))\n(socket-bind so (inet-address \"0.0.0.0\" 8000))") (pre "; Bind to the IPv6 unspecified address on port 8000.  This may also\n; allow IPv4 connections, depending on your system settings. \n(define so (socket af/inet6 sock/stream))\n(socket-bind so (inet-address \"::\" 8000))") (pre "; Bind to the IPv6 unspecified address on port 8000, limiting\n; connections to IPv6 only.\n(define so (socket af/inet6 sock/stream))\n(set! (ipv6-v6-only? so) #t)\n(socket-bind so (inet-address \"::\" 8000))"))
(def (sig (procedure "(socket-listen so backlog)" (id socket-listen))) (p "Listen for incoming connections on socket " (tt "so") ", with a connection queue of integer length " (tt "backlog") ".   This call is only valid for connection-oriented (stream) sockets."))
(def (sig (procedure "(socket-accept so)" (id socket-accept)) (procedure "(socket-accept-ready? so)" (id socket-accept-ready?))) (p (tt "socket-accept") " accepts a connection on listening socket " (tt "so") ", returning a new connected " (tt "socket") " object.  The address of the peer can be obtained by calling " (tt "socket-peer-name") " on the socket.") (p "This is a non-blocking operation; other SRFI-18 threads can continue to run in the meantime, although this one will block.  If the accept does not complete within " (tt "socket-accept-timeout") " milliseconds, a timeout error is raised.") (p (tt "socket-accept-ready?") " tests whether there is a connection waiting to be accepted, so you can avoid blocking the current thread. However, if a peer resets his connection between your testing and accepting, the accept may block nonetheless."))
(def (sig (procedure "(socket-shutdown so how)" (id socket-shutdown)) (constant "shut/rd" (id shut/rd)) (constant "shut/wr" (id shut/wr)) (constant "shut/rdwr" (id shut/rdwr))) (p "Shutdown the full-duplex connection on socket " (tt "so") " in the manner of " (tt "how") ":") (dl (dt (tt "shut/rd")) (dd "disallow further receiving") (dt (tt "shut/wr")) (dd "disallow further sending") (dt (tt "shut/rdwr")) (dd "disallow further receiving and sending")) (p "The system normally shuts down the connection itself when closing, so calling this manually is not often necessary.  One usage example is using " (tt "shut/wr") " to inform a server you have finished transmitting, while allowing it to continue sending to you."))
(def (sig (procedure "(socket-close so)" (id socket-close))) (p "Close socket " (tt "so") ".  If a connection was established, the socket is shut down gracefully.") (p (tt "socket-close") " throws an error if the " (tt "close()") " fails."))
(def (sig (procedure "(socket-close* so)" (id socket-close*))) (p "Same as " (tt "socket-close") ", except that " (tt "socket-close*") " does " (i "not") " throw an error if the " (tt "close()") " fails.") (p "This could be useful in certain lowlevel code, such as after a network error, but you should not use this unless you know what you're doing. This might go away or change semantics in the future."))
(def (sig (procedure "(socket-name so)" (id socket-name))) (p "Return a " (tt "sockaddr") " object representing the address of the local endpoint of socket " (tt "so") ".  If the socket has not been bound, it returns " (tt "#f") ".") (p "The procedure name is derived from getsockname(), hence the use of \"name\" to describe a socket address."))
(def (sig (procedure "(socket-peer-name so)" (id socket-peer-name))) (p "Return a " (tt "sockaddr") " object representing the address of the remote endpoint of socket " (tt "so") ".  If no connection exists, returns " (tt "#f") ".  This can be used after " (tt "socket-connect") " or on a socket returned by " (tt "socket-accept") ".  Note that this also works with UDP \"connections\" made with " (tt "socket-connect") ".") (p "The procedure name is derived from getpeername(), hence the use of \"name\" to describe a socket address."))
(def (sig (procedure "(socket-receive! so buf #!optional (start 0) (end #f) (flags 0))" (id socket-receive!)) (procedure "(socket-receive-ready? so)" (id socket-receive-ready?))) (p "Receives data from socket " (tt "so") " and writes it into " (tt "buf") ", which may be a string or a blob.  " (tt "start") " and " (tt "end") " are optional offsets into " (tt "buf") "; the call attempts to read " (tt "end") " - " (tt "start") " = " (tt "len") " bytes.  If " (tt "end") " is " (tt "#f") ", it is interpreted as the end of the blob or string.") (p "This call will block until data is available, but other threads can proceed.  If the receive does not complete within " (tt "socket-receive-timeout") " milliseconds, a timeout error is raised. To avoid blocking the current thread, you can check if data is ready via " (tt "socket-receive-ready?") ".") (p "Returns the number of bytes actually received (and updates " (tt "buf") " as a side effect).") (p "For datagram sockets, if " (tt "len") " is smaller than the amount of data in the next datagram, the rest of the data is irrevocably lost."))
(def (sig (procedure "(socket-receive so len #!optional (flags 0))" (id socket-receive))) (p "Receives up to " (tt "len") " bytes from data from socket " (tt "so") " and returns it in a string (sized to fit the returned data).  Otherwise, it behaves like " (tt "socket-receive!") "."))
(def (sig (procedure "(socket-receive-from! so buf #!optional (start 0) (end #f) (flags 0))" (id socket-receive-from!))) (p "Like " (tt "socket-receive!") ", but receives data on a connectionless datagram socket, returning 2 values: the number of bytes read, and a " (tt "sockaddr") " object representing the source."))
(def (sig (procedure "(socket-receive-from so len #!optional (flags 0))" (id socket-receive-from))) (p "Receives up to " (tt "len") " bytes from data from socket " (tt "so") " and returns two values: a string (sized to fit the returned data), and a " (tt "sockaddr") " object representing the source.  Otherwise, it behaves like " (tt "socket-receive-from!") "."))
(def (sig (procedure "(socket-send so buf #!optional (start 0) (end #f) (flags 0))" (id socket-send))) (p "Sends data to socket " (tt "so") " from the buffer " (tt "buf") ", which may be a string or a blob.  " (tt "start") " and " (tt "end") " are optional offsets into " (tt "buf") "; the call attempts to write " (tt "end") " - " (tt "start") " = " (tt "len") " bytes.  If " (tt "end") " is " (tt "#f") ", it is interpreted as the end of the blob or string.") (p "This call will block until at least some data is sent, but other threads can proceed.  If the send does not complete within " (tt "(socket-send-timeout)") " milliseconds, a timeout error is raised.") (p "Returns the number of bytes actually sent."))
(def (sig (procedure "(socket-send-to so buf saddr #!optional (start 0) (end #f) (flags 0))" (id socket-send-to))) (p "Like " (tt "socket-send") ", but sends data over a connectionless datagram socket to " (tt "sockaddr") " " (tt "saddr") ", returning the number of bytes actually sent."))
(def (sig (procedure "(socket-send-all so buf #!optional (start 0) (end #f) (flags 0))" (id socket-send-all))) (p "Sends all data between " (tt "start") " and " (tt "end") " in " (tt "buf") " over connected socket " (tt "so") " by calling " (tt "socket-send") " multiple times until all data is sent.") (p "Data is sent in chunks of size " (tt "(socket-send-size)") "; the last chunk sent may be smaller than this.  A " (tt "#f") " value for " (tt "socket-send-size") " will attempt to send all remaining data with each call to send().  Note that this chunking works for connected datagram sockets as well as stream sockets; you can use it to send a large buffer divided into, say, 512-byte datagrams."))
(def (sig (procedure "(socket-i/o-ports so)" (id socket-i/o-ports))) (p "Constructs an input port I and an output port O associated with the connected socket " (tt "so") ", returning " (tt "(values I O)") ".  This procedure works on both stream and datagram sockets.") (p "To enable output buffering on stream socket ports, see the parameter " (tt "socket-send-buffer-size") ".  Setting it to a value of 1024 bytes is reasonable.") (p "Below is a fairly involved explanation of input and output buffering and chunking, as well as recommendations for use with datagrams.") (p (tt "socket-i/o-ports") " is normally used with stream sockets.  Input data is always buffered in a buffer of size " (tt "(socket-receive-buffer-size)") ". Whenever the buffer is empty, " (tt "socket-receive!") " is called once to read up to that many bytes.  Output data is sent with " (tt "socket-send-all") ", so it may be divided into chunks of size " (tt "(socket-send-size)") ".  If output is unbuffered, " (tt "socket-send-all") " is called as soon as data is written to the port.") (p "If output is buffered by setting " (tt "(socket-send-buffer-size)") " to N, then N characters are buffered before sending the data.  Note that only multiples of the buffer size are sent (any overage is kept in the buffer).  For example, if the buffer can hold 512 bytes and contains 500 bytes, writing 526 more bytes brings the total unsent size to 1026 bytes.  1024 bytes (2 blocks) are written out in a single call to " (tt "socket-send-all") " and the last 2 bytes are retained in the buffer.") (p "When the output buffer size and chunk size are both set, it is recommended to make the chunk size a multiple of the buffer size; for example, buffer size = 1024, chunk size = 8192.  If not aligned, extraneous small packets may be sent.  Buffer size is almost always less than or equal to chunk size.  If greater, it should be a multiple of the chunk size.  Using powers of 2 for both satisfies all cases.") (p "Note that " (tt "socket-i/o-ports") " can also be used to create ports on connected datagram sockets.  Input is always buffered and a single chunk of up to size " (tt "(socket-receive-buffer-size)") " is read into the buffer whenever the buffer is empty.  (If the datagram is smaller than the buffer, repeated reads are not performed; rather, the buffer is used until exhausted again.  Any datagram exceeding the buffer size will be truncated.)  Output is divided into chunks of size " (tt "(socket-send-size)") ", as in " (tt "socket-send-all") " -- this is useful for placing a maximum cap on datagram size transmitted.  Finally, output buffering may be enabled, which behaves the same as with TCP ports; characters are buffered and sent in blocks of " (tt "(socket-send-buffer-size)") " bytes.  Again, to avoid excessive transmission, the chunk size should be a multiple of the buffer size or vice versa.") (p "For example, to accept up to 4K datagrams, buffer 128 characters at a time and send 128-, 256-, 384- or 512-byte datagrams at a time:") (pre "(parameterize ((socket-receive-buffer-size 4096)\n               (socket-send-buffer-size 128)\n               (socket-send-size 512))\n  (define so (socket-connect/ai\n              (address-information host port type: sock/dgram)))\n  (define-values (i o) (socket-i/o-ports so))\n  ;; a useful example would be nice\n  ...)"))
(def (sig (procedure "(socket-i/o-port->socket port)" (id socket-i/o-port->socket))) (p "Returns the socket object assocated with input or output port " (tt "port") ".  From there you can obtain a file descriptor with " (tt "socket-fileno") ".") (p "Alternatively, " (tt "port->fileno") " from " (int-link "/man/4/Unit posix" "posix") " is supported to obtain a file descriptor.  (Also see " (int-link "#Bugs and limitations" "Bugs and limitations") ".)"))
(def (sig (procedure "(socket-abandon-port port)" (id socket-abandon-port))) (p "Marks the socket input or output port " (tt "port") " as abandoned.  Normally, when an socket input port is closed the read side of the connection is shut down; similarly closing the output port shuts down the write side. Marking a port as abandoned skips this shutdown.  This is useful to ensure a connection stays open after the port is closed.") (p "The socket is still closed after both ports are closed, regardless of their abandoned status."))
(def (sig (parameter "(socket-connect-timeout ms) [default: #f]" (id socket-connect-timeout)) (parameter "(socket-accept-timeout ms)  [default: #f]" (id socket-accept-timeout)) (parameter "(socket-receive-timeout ms) [default: 1 minute]" (id socket-receive-timeout)) (parameter "(socket-send-timeout ms)    [default: 1 minute]" (id socket-send-timeout))) (p "Timeouts in milliseconds for connect, receive, send and accept operations.  If these timeout are exceeded, the error " (tt "(exn i/o net timeout)") " is raised.  If " (tt "#f") ", the operation never times out (unless the system forces it to)."))
(def (sig (parameter "(socket-send-buffer-size n)       [default: #f]" (id socket-send-buffer-size)) (parameter "(socket-send-size n)              [default: 16384]" (id socket-send-size)) (parameter "(socket-receive-buffer-size n)    [default: 4096]" (id socket-receive-buffer-size))) (p "These parameters are used mostly to adjust the behavior of socket ports, and take effect when the ports are created.") (p (tt "(socket-send-buffer-size)") " is the buffer size used by socket output ports.  If " (tt "#f") ", no buffering is done.  A power of 2, such as 1K or 4K, is an appropriate value.") (p (tt "(socket-send-size)") " is used by socket output ports, and is the size used in a single call to " (tt "socket-send") " by " (tt "socket-send-all") ".  It can be " (tt "#f") ", meaning infinite, so that any remaining data is sent at each call.  When set, it should usually be a multiple of " (tt "(socket-send-buffer-size)") ", assuming buffering is also enabled.  A power of 2 is an appropriate value, such as 8K or 16K.") (p (tt "(socket-receive-buffer-size)") " is the size used for the input buffer in socket input ports.  A power of 2, such as 4K, is appropriate. Input buffering can not be disabled."))
(def (sig (procedure "(so-reuse-address? s)      [so/reuseaddr]       " (id so-reuse-address?)) (procedure "(so-debug? s)              [so/debug]           " (id so-debug?)) (procedure "(so-keep-alive? s)         [so/keepalive]       " (id so-keep-alive?)) (procedure "(so-dont-route? s)         [so/dontroute]       " (id so-dont-route?)) (procedure "(so-broadcast? s)          [so/broadcast]       " (id so-broadcast?)) (procedure "(so-oob-inline? s)         [so/oobinline]       " (id so-oob-inline?)) (procedure "(so-accept-connections? s) [so/acceptconn] (r/o)" (id so-accept-connections?)) (procedure "(so-send-buffer s)         [so/sndbuf]          " (id so-send-buffer)) (procedure "(so-receive-buffer s)      [so/rcvbuf]          " (id so-receive-buffer)) (procedure "(so-send-low-water s)      [so/sndlowat]        " (id so-send-low-water)) (procedure "(so-receive-low-water s)   [so/rcvlowat]        " (id so-receive-low-water)) (procedure "(so-error s)               [so/error]      (r/o)" (id so-error)) (procedure "(so-type s)                [so/type]       (r/o)" (id so-type))) (p "Getters / setters for boolean and integer socket-level options, where " (tt "s") " is a " (i "socket") " object or an integer file descriptor.  To set an option, use SRFI-17 generalized set:") (pre "(set! (so-reuse-address? s) #t)") (p "\"(r/o)\" indicates the option is read-only; an error will be raised if you attempt to set it.") (p "As a special note on " (tt "so-reuse-address?") ", on Windows platforms it will first attempt to use option " (tt "so/exclusiveaddruse") " because this option matches UNIX semantics.  If this fails it will fall back to " (tt "so/reuseaddr") ", which allows any processes to rebind a previously bound address and port."))
(def (sig (procedure "(tcp-no-delay? s)        [tcp/nodelay]" (id tcp-no-delay?)) (procedure "(tcp-no-push? s)         [tcp/nopush]" (id tcp-no-push?)) (procedure "(tcp-no-options? s)      [tcp/noopt]" (id tcp-no-options?)) (procedure "(tcp-keep-alive s)       [tcp/keepalive]" (id tcp-keep-alive)) (procedure "(tcp-max-segment-size s) [tcp/maxseg]" (id tcp-max-segment-size))) (p "Getters / setters for TCP-level socket options (" (tt "ipproto/tcp") ").  " (tt "s") " is a " (i "socket") " object or an integer file descriptor."))
(def (sig (procedure "(ip-header-included? s)  [ip/hdrincl]" (id ip-header-included?)) (procedure "(ip-type-of-service s)   [ip/tos]" (id ip-type-of-service)) (procedure "(ip-time-to-live s)      [ip/ttl]" (id ip-time-to-live))) (p "Getters / setters for IP-level socket options (" (tt "ipproto/ip") ").  " (tt "s") " is a " (i "socket") " object or an integer file descriptor."))
(def (sig (procedure "(ipv6-v6-only? s)        [ipv6/v6only]            " (id ipv6-v6-only?))) (p "Getters / setters for IPv6-level socket options (" (tt "ipproto/ipv6") ").  " (tt "s") " is a " (i "socket") " object or an integer file descriptor."))
(def (sig (procedure "(set-socket-option s level name val)" (id set-socket-option))) (p "Set the value of option " (tt "name") " at socket level " (tt "level") " on socket " (tt "s") " to " (tt "val") ". " (tt "val") " may be a fixnum or a boolean.  It may also be a blob or a string; if so, the raw contents are passed to the option, which is useful when a structure is required.  The return value is unspecified.") (p "If an unsupported option or level is requested, a condition of type " (tt "(exn i/o net unsupported)") " is raised.") (p "Note: due to the vagaries of structure member alignment (and 32 vs. 64-bit sizes), it's not generally safe to pack raw data yourself into a blob or a SRFI-4 vector.  Instead, you should treat the blob contents as a C struct.  See the longer example down the page for more.") (pre "(set-socket-option S ipproto/tcp tcp/nodelay 1)\n(set-socket-option S ipproto/tcp tcp/nodelay (make-string 4 #\\x0))\n(set-socket-option S sol/socket so/rcvlowat (u32vector->blob/shared (u32vector #x01020304)))"))
(def (sig (procedure "(get-socket-option s level name #!optional (len #f))" (id get-socket-option))) (p "Get the value of option " (tt "name") " at socket level " (tt "level") " on socket " (tt "s") ".  If " (tt "len") " is " (tt "#f") ", the default, we interpret the option value as an integer and return that.  Otherwise, temporary storage of length " (tt "len") " is allocated to receive the binary option data; after the call it is resized to fit the data, and returned.  If " (tt "len") " is too small to hold the returned data, the result is undefined.") (p "If an unsupported option or level is requested, a condition of type " (tt "(exn i/o net unsupported)") " is raised.") (p "This procedure does not convert integers to boolean values---if you expect a boolean flag, assume zero means " (tt "#f") " and non-zero means " (tt "#t") ".  Don't be surprised if boolean flags return different non-zero integer values from those you put in; that's an implementation detail. You can only rely on true being some non-zero value.") (pre "(get-socket-option S ipproto/tcp tcp/nodelay)     ; => 8, perhaps, meaning #t\n(get-socket-option S ipproto/tcp tcp/nodelay 64)  ; => #${08000000}\n(get-socket-option S ipproto/tcp tcp/nodelay 4)   ; => #${08000000}"))
(def (sig (constant "so/reuseaddr" (id so/reuseaddr)) (constant "so/debug" (id so/debug)) (constant "so/acceptconn" (id so/acceptconn)) (constant "so/keepalive" (id so/keepalive)) (constant "so/dontroute" (id so/dontroute)) (constant "so/broadcast" (id so/broadcast)) (constant "so/linger" (id so/linger)) (constant "so/oobinline" (id so/oobinline)) (constant "so/sndbuf" (id so/sndbuf)) (constant "so/rcvbuf" (id so/rcvbuf)) (constant "so/sndlowat" (id so/sndlowat)) (constant "so/rcvlowat" (id so/rcvlowat)) (constant "so/sndtimeo" (id so/sndtimeo)) (constant "so/rcvtimeo" (id so/rcvtimeo)) (constant "so/error" (id so/error)) (constant "so/type" (id so/type)) (constant "so/useloopback" (id so/useloopback)) (constant "so/reuseport" (id so/reuseport)) (constant "so/timestamp" (id so/timestamp)) (constant "so/exclusiveaddruse" (id so/exclusiveaddruse))) (p "Socket-level socket options for use with " (tt "set-socket-option") " and " (tt "get-socket-option") " at level " (tt "sol/socket") "."))
(def (sig (constant "tcp/nodelay" (id tcp/nodelay)) (constant "tcp/nopush" (id tcp/nopush)) (constant "tcp/noopt" (id tcp/noopt)) (constant "tcp/keepalive" (id tcp/keepalive)) (constant "tcp/maxseg" (id tcp/maxseg))) (p "TCP-level socket options for use with " (tt "set-socket-option") " and " (tt "get-socket-option") " at level " (tt "ipproto/tcp") "."))
(def (sig (constant "ip/options" (id ip/options)) (constant "ip/hdrincl" (id ip/hdrincl)) (constant "ip/tos" (id ip/tos)) (constant "ip/ttl" (id ip/ttl)) (constant "ip/mtu" (id ip/mtu)) (constant "ip/mtu-discover" (id ip/mtu-discover)) (constant "ip/pktinfo" (id ip/pktinfo)) (constant "ip/recverr" (id ip/recverr)) (constant "ip/recvtos" (id ip/recvtos)) (constant "ip/recvttl" (id ip/recvttl)) (constant "ip/router-alert" (id ip/router-alert)) (constant "ip/recvopts" (id ip/recvopts)) (constant "ip/recvretopts" (id ip/recvretopts)) (constant "ip/retopts" (id ip/retopts)) (constant "ip/recvdstaddr" (id ip/recvdstaddr)) (constant "ip/multicast-if" (id ip/multicast-if)) (constant "ip/multicast-ttl" (id ip/multicast-ttl)) (constant "ip/multicast-loop" (id ip/multicast-loop)) (constant "ip/add-membership" (id ip/add-membership)) (constant "ip/drop-membership" (id ip/drop-membership))) (p "IP-level socket options for use with " (tt "set-socket-option") " and " (tt "get-socket-option") " at level " (tt "ipproto/ip") "."))
(def (sig (constant "sol/socket" (id sol/socket)) (constant "ipproto/ip" (id ipproto/ip)) (constant "ipproto/ipv6" (id ipproto/ipv6)) (constant "ipproto/tcp" (id ipproto/tcp)) (constant "ipproto/icmp" (id ipproto/icmp)) (constant "ipproto/udp" (id ipproto/udp))) (p "Socket level constants, for use with " (tt "set-socket-option") " and " (tt "get-socket-option") "."))
