/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package std.net
/**
* Package-private function that checks unix domain socket address for validity (to connect or bind)
*/
func checkUnixSocketAddress(address: SocketAddress, name: String): SocketAddress {
if (!(address is UnixSocketAddress)) {
throw IllegalArgumentException("${name} should be a Unix Path address but got ${address.family}: ${address}")
}
return address
}
/*
* Represents a Unix domain streaming socket.
*
* Once an instance is created, it is not yet connected so should be connected explicitly via connect().
*
* Instances of this type should be explicitly closed even when the connect() hasn't been invoked.
*
* @see StreamingSocket for more details on how do streaming sockets work.
*/
@When[os != "Windows"]
public class UnixSocket <: StreamingSocket {
private let impl: SocketCommon<ActualPlatformSocket>
private func setLocalAddress(address: SocketAddress) {
checkUnixSocketAddress(address, "localAddress")
impl.localAddress = address
}
/**
* Create an unconnected Unix domain socket ready to connect to the specified socket path
*
* @param path to connect to
*/
public init(path: String, localPath!: ?String = None) {
this(UnixSocketAddress(path))
if (let Some(_localPath) <- localPath) {
setLocalAddress(UnixSocketAddress(_localPath))
}
}
/**
* Create an unconnected Unix domain socket ready to connect to the specified socket path
* @param address to connect to
*/
public init(address: SocketAddress, localAddress!: ?SocketAddress = None) {
checkUnixSocketAddress(address, "address")
this.impl = SocketCommon(SocketNet.UNIX, AddressFamily.UNIX, StreamingMode)
impl.remoteAddress = address
if (let Some(_localAddress) <- localAddress) {
setLocalAddress(_localAddress)
}
}
/**
* Creates an internally precreated socket. See UnixServerSocket.accept.
*/
init(impl: SocketCommon<ActualPlatformSocket>) {
this.impl = impl
}
/**
* Remote address the socket will be or is currently connected to.
*
* @throws SocketException is the socket is already closed.
*/
public override prop remoteAddress: SocketAddress {
get() {
impl.remoteAddress ?? SocketException.notYetConnected()
}
}
/**
* Local address the socket will be or currently is bound at.
*
* @throws SocketException is the socket is already closed
* or no local address is available (local address was not provided during creation and the socket is not connected).
*/
public override prop localAddress: SocketAddress {
get() {
impl.localAddress ?? SocketException.notYetConnected()
}
}
/**
* Read operation time limit or `None` for infinite read attempts.
* The value specified here is actually the minimal amount of time before a read operation cancelled.
* The actual time is not guaranteed but it will be never cancelled earlier than the specified timeout value.
* If the duration is too big than it can be bumped to the infinite. When it's too small then if will be bumped to the minimal clock granularity.
*
* The default value is None.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override mut prop readTimeout: ?Duration {
get() {
impl.readTimeout
}
set(timeout) {
impl.readTimeout = timeout?.throwIfNegative("Read timeout").toNanosecondGranularity()
}
}
/**
* Write operation time limit or `None` for infinite read attempts.
*
* The value specified here is actually the minimal amount of time before a write operation cancelled.
* The actual time is not guaranteed but it will be never cancelled earlier than the specified timeout value.
* If the duration is too big than it can be bumped to the infinite. When it's too small then if will be bumped to the minimal clock granularity.
*
* The default value is None.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override mut prop writeTimeout: ?Duration {
get() {
impl.writeTimeout
}
set(timeout) {
impl.writeTimeout = timeout?.throwIfNegative("Write timeout").toNanosecondGranularity()
}
}
/**
* SO_SNDBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired outgoing buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop sendBufferSize: Int64 {
get() { impl.getSendBufferSize() }
set(newSize) { impl.setSendBufferSize(newSize) }
}
/**
* SO_RCVBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired receive buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop receiveBufferSize: Int64 {
get() { impl.getReceiveBufferSize() }
set(newSize) { impl.setReceiveBufferSize(newSize) }
}
public override func read(buffer: Array<Byte>): Int64 {
impl.read(buffer)
}
public override func write(buffer: Array<Byte>): Unit {
impl.write(buffer)
}
/**
* Connects to the remote peer within the specified timeout.
* If the timeout is `None`, then connection attempts will continue without time limit.
* Please note that this function doesn't do retry so if the server peer does reject connection, we get error despite the timeout duration.
*
* This function also does bind first before doing connect so there is no need to invoke bind
*
* @throws SocketException if the connection cannot be established.
* @throws SocketTimeoutException if the waiting time has expired.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public func connect(timeout!: ?Duration = None): Unit {
impl.connect(timeout?.throwIfNegative("Timeout"))
}
/**
* Read the specified socket option writing the result to value buffer
* of the specified valueLength (in bytes).
* Before invoking this function valueLength should be initialized with the buffer size
* After invoking this function valueLength will contain the actual result
* size in bytes.
*
* Throws an exception if failed (when getsockopt returns -1).
*/
public func getSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: CPointer<UIntNative>): Unit {
unsafe { impl.getSocketOption(level, option, value, valueLength) }
}
/**
* Write the specified socket option from value buffer having valueLength
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1).
*/
public func setSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: UIntNative): Unit {
unsafe { impl.setSocketOption(level, option, value, valueLength) }
}
/**
* Read the specified socket option returning it's value as IntNative result.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionIntNative(level: Int32, option: Int32): IntNative {
impl.getSocketOptionIntNative(level, option)
}
/**
* Write a numeric IntNative value to the specified socket option.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionIntNative(level: Int32, option: Int32, value: IntNative): Unit {
impl.setSocketOptionIntNative(level, option, value)
}
/**
* Read the specified socket option returning it's value as a boolean value
* converting it from an IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as 0 => false, other values => true.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionBool(level: Int32, option: Int32): Bool {
impl.getSocketOptionBool(level, option)
}
/**
* Write a boolean value to the specified socket option converting it to IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as false => 0, true => 1
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionBool(level: Int32, option: Int32, value: Bool): Unit {
impl.setSocketOptionBool(level, option, value)
}
/**
* Close the socket releasing all resources. All operations except for close() and isClose() are no longer available.
* This function is reentrant.
**/
public func close(): Unit {
impl.close()
}
/**
* Checks whether this socket has been explicitly closed via close()
**/
public func isClosed(): Bool {
impl.isClosed()
}
public override func toString(): String {
"UnixSocket(${impl.toString()})"
}
}
@When[os == "Windows"]
@Deprecated
public class UnixSocket <: StreamingSocket {
private let impl: SocketCommon<ActualPlatformSocket>
private func setLocalAddress(address: SocketAddress) {
checkUnixSocketAddress(address, "localAddress")
impl.localAddress = address
}
/**
* Create an unconnected Unix domain socket ready to connect to the specified socket path
*
* @param path to connect to
*/
public init(path: String, localPath!: ?String = None) {
this(UnixSocketAddress(path))
if (let Some(legacyLocalPath) <- localPath) {
setLocalAddress(UnixSocketAddress(legacyLocalPath))
}
}
/**
* Create an unconnected Unix domain socket ready to connect to the specified socket path
* @param address to connect to
*/
public init(address: SocketAddress, localAddress!: ?SocketAddress = None) {
checkUnixSocketAddress(address, "address")
this.impl = SocketCommon(SocketNet.UNIX, AddressFamily.UNIX, StreamingMode)
this.impl.remoteAddress = address
if (let Some(legacyLocalAddress) <- localAddress) {
setLocalAddress(legacyLocalAddress)
}
}
/**
* Creates an internally precreated socket. See UnixServerSocket.accept.
*/
init(impl: SocketCommon<ActualPlatformSocket>) {
this.impl = impl
}
/**
* Remote address the socket will be or is currently connected to.
*
* @throws SocketException is the socket is already closed.
*/
public override prop remoteAddress: SocketAddress {
get() {
this.impl.remoteAddress ?? SocketException.notYetConnected()
}
}
/**
* Local address the socket will be or currently is bound at.
*
* @throws SocketException is the socket is already closed
* or no local address is available (local address was not provided during creation and the socket is not connected).
*/
public override prop localAddress: SocketAddress {
get() {
this.impl.localAddress ?? SocketException.notYetConnected()
}
}
/**
* Read operation time limit or `None` for infinite read attempts.
* The value specified here is actually the minimal amount of time before a read operation cancelled.
* The actual time is not guaranteed but it will be never cancelled earlier than the specified timeout value.
* If the duration is too big than it can be bumped to the infinite. When it's too small then if will be bumped to the minimal clock granularity.
*
* The default value is None.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override mut prop readTimeout: ?Duration {
get() {
this.impl.readTimeout
}
set(timeout) {
this.impl.readTimeout = timeout?.throwIfNegative("Read timeout").toNanosecondGranularity()
}
}
/**
* Write operation time limit or `None` for infinite read attempts.
*
* The value specified here is actually the minimal amount of time before a write operation cancelled.
* The actual time is not guaranteed but it will be never cancelled earlier than the specified timeout value.
* If the duration is too big than it can be bumped to the infinite. When it's too small then if will be bumped to the minimal clock granularity.
*
* The default value is None.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override mut prop writeTimeout: ?Duration {
get() {
this.impl.writeTimeout
}
set(timeout) {
this.impl.writeTimeout = timeout?.throwIfNegative("Write timeout").toNanosecondGranularity()
}
}
/**
* SO_SNDBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired outgoing buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop sendBufferSize: Int64 {
get() { this.impl.getSendBufferSize() }
set(newSize) { this.impl.setSendBufferSize(newSize) }
}
/**
* SO_RCVBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired receive buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop receiveBufferSize: Int64 {
get() { this.impl.getReceiveBufferSize() }
set(newSize) { this.impl.setReceiveBufferSize(newSize) }
}
public override func read(buffer: Array<Byte>): Int64 {
this.impl.read(buffer)
}
public override func write(buffer: Array<Byte>): Unit {
this.impl.write(buffer)
}
/**
* Connects to the remote peer within the specified timeout.
* If the timeout is `None`, then connection attempts will continue without time limit.
* Please note that this function doesn't do retry so if the server peer does reject connection, we get error despite the timeout duration.
*
* This function also does bind first before doing connect so there is no need to invoke bind
*
* @throws SocketException if the connection cannot be established.
* @throws SocketTimeoutException if the waiting time has expired.
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public func connect(timeout!: ?Duration = None): Unit {
this.impl.connect(timeout?.throwIfNegative("Timeout"))
}
public func close(): Unit {
this.impl.close()
}
public func isClosed(): Bool {
this.impl.isClosed()
}
public override func toString(): String {
"UnixSocket(${this.impl.toString()})"
}
public func setSocketOptionBool(level: Int32, option: Int32, value: Bool): Unit {
this.impl.setSocketOptionBool(level, option, value)
}
public func getSocketOptionBool(level: Int32, option: Int32): Bool {
this.impl.getSocketOptionBool(level, option)
}
/**
* Read the specified socket option writing the result to value buffer
* of the specified valueLength (in bytes).
* Before invoking this function valueLength should be initialized with the buffer size
* After invoking this function valueLength will contain the actual result
* size in bytes.
*
* Throws an exception if failed (when getsockopt returns -1).
*/
public func getSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: CPointer<UIntNative>): Unit {
unsafe { this.impl.getSocketOption(level, option, value, valueLength) }
}
/**
* Write the specified socket option from value buffer having valueLength
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1).
*/
public func setSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: UIntNative): Unit {
unsafe { this.impl.setSocketOption(level, option, value, valueLength) }
}
/**
* Read the specified socket option returning it's value as IntNative result.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionIntNative(level: Int32, option: Int32): IntNative {
this.impl.getSocketOptionIntNative(level, option)
}
/**
* Write a numeric IntNative value to the specified socket option.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionIntNative(level: Int32, option: Int32, value: IntNative): Unit {
this.impl.setSocketOptionIntNative(level, option, value)
}
}
/**
* Unix Domain server socket providing a way to listen for incoming connections.
*
* Once created, could be configured via corresponding properties (e.g. reusePort) or setSocketOptionXX functions.
*
* To start listening, use bind() function that does bind socket on a local path and start listening for connections.
* The local path to bind at should be a non-existing path otherwise bind() will fail.
*
* Receiving an incoming connection is provided via accept() function that does wait for the next connection or returns immediately
* if there is already pending connection.
*
* Instances of this type should be explicitly closed even when the bind() hasn't been invoked.
*/
@When[os != "Windows"]
public class UnixServerSocket <: ServerSocket {
private let impl: SocketCommon<ActualPlatformSocket>
private var backlogSize_: Int32 = SOCKET_DEFAULT_BACKLOG
/**
* Local address the socket will be or is currently bound at.
*
* @throws SocketException is the socket is already closed.
*/
public override prop localAddress: SocketAddress {
get() {
this.impl.localAddress ?? SocketException.notYetBound()
}
}
/**
* Creates an anbound Unix server streaming socket configured to bind at the specified path
* @param bindAt path for the unix server socket
**/
public init(bindAt!: String) {
this(bindAt: UnixSocketAddress(bindAt))
}
/**
* Creates an anbound Unix server streaming socket configured to bind at the specified path
* @param bindAt path for the unix server socket
**/
public init(bindAt!: SocketAddress) {
checkUnixSocketAddress(bindAt, "bindAt")
let socketImpl = SocketCommon<ActualPlatformSocket>(UNIX, AddressFamily.UNIX, SocketMode.StreamingMode)
socketImpl.localAddress = bindAt
this.impl = socketImpl
}
/**
* SO_SNDBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired outgoing buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop sendBufferSize: Int64 {
get() { this.impl.getSendBufferSize() }
set(newSize) { this.impl.setSendBufferSize(newSize) }
}
/**
* SO_RCVBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired receive buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop receiveBufferSize: Int64 {
get() { this.impl.getReceiveBufferSize() }
set(newSize) { this.impl.setReceiveBufferSize(newSize) }
}
/**
* Configure incoming connections backlog size. This only works before binding socket.
* Changing this value is not guaranteed to be actually applied since the operating system may decide to
* change or bump it, or simply ignore.
**/
public mut prop backlogSize: Int64 {
get() {
Int64(backlogSize_)
}
set(newSize) {
this.impl.checkNotBound()
this.impl.checkNotClosed()
backlogSize_ = match {
case newSize <= 0 => throw IllegalArgumentException("BacklogSize should be positive: ${newSize}.")
case newSize >= Int64(Int32.Max) => Int32.Max - 1
case _ => Int32(newSize)
}
}
}
/**
* Bind a streaming UNIX domain socket.
*
* This function also does listen just after binding creating an incoming connections queue that could be accessed via "accept()" function.
*
* This operation does atomically create a socket file at the local path.
* If the path is already existing then bind() fails with SocketException.
*/
public override func bind(): Unit {
this.impl.bind(backlogSize_)
}
/**
* Accept a client socket, waiting for one if there are no pending connection requests.
*
* The OS implementation usually provides an incoming connection requests queue,
* so calling accept() does takes a candidate from the queue
* or wait until we get some request if the queue is empty.
*
* @throws SocketTimeoutException if the spcified timeout allapsed before got pending connection request
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override func accept(timeout!: ?Duration): UnixSocket {
let acceptedSocket = this.impl.accept(timeout) ?? SocketException.throwClosedException()
return UnixSocket(acceptedSocket)
}
/**
* Accept a client socket, waiting for one if there are no pending connection requests.
*
* The OS implementation usually provides an incoming connection requests queue,
* so calling accept() does takes a candidate from the queue
* or wait until we get some request if the queue is empty.
*/
public override func accept(): UnixSocket {
accept(timeout: None)
}
/**
* Close the socket releasing all resources. All operations except for close() and isClose() are no longer available.
* This function is reentrant.
**/
public override func close(): Unit {
this.impl.close()
}
/**
* Checks whether this socket has been explicitly closed via close()
**/
public override func isClosed(): Bool {
this.impl.isClosed()
}
public func getSocketOptionIntNative(level: Int32, option: Int32): IntNative {
this.impl.getSocketOptionIntNative(level, option)
}
public func setSocketOptionIntNative(level: Int32, option: Int32, value: IntNative): Unit {
this.impl.setSocketOptionIntNative(level, option, value)
}
/**
* Read the specified socket option writing the result to value buffer
* of the specified valueLength (in bytes).
* Before invoking this function valueLength should be initialized with the buffer size
* After invoking this function valueLength will contain the actual result
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when getsockopt returns -1).
*/
public func getSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: CPointer<UIntNative>): Unit {
unsafe { this.impl.getSocketOption(level, option, value, valueLength) }
}
/**
* Write the specified socket option from value buffer having valueLength
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1).
*/
public func setSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: UIntNative): Unit {
unsafe { this.impl.setSocketOption(level, option, value, valueLength) }
}
/**
* Read the specified socket option returning it's value as a boolean value
* converting it from an IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as 0 => false, other values => true.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionBool(level: Int32, option: Int32): Bool {
this.impl.getSocketOptionBool(level, option)
}
/**
* Write a boolean value to the specified socket option converting it to IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as false => 0, true => 1
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionBool(level: Int32, option: Int32, value: Bool): Unit {
this.impl.setSocketOptionBool(level, option, value)
}
public override func toString(): String {
"UnixServerSocket(${this.impl.toString()})"
}
}
@When[os == "Windows"]
@Deprecated
public class UnixServerSocket <: ServerSocket {
private let impl: SocketCommon<ActualPlatformSocket>
private var backlogSize_: Int32 = SOCKET_DEFAULT_BACKLOG
/**
* Local address the socket will be or is currently bound at.
*
* @throws SocketException is the socket is already closed.
*/
public override prop localAddress: SocketAddress {
get() {
this.impl.localAddress ?? SocketException.notYetBound()
}
}
/**
* Creates an anbound Unix server streaming socket configured to bind at the specified path
* @param bindAt path for the unix server socket
**/
public init(bindAt!: String) {
this(bindAt: UnixSocketAddress(bindAt))
}
/**
* Creates an anbound Unix server streaming socket configured to bind at the specified path
* @param bindAt path for the unix server socket
**/
public init(bindAt!: SocketAddress) {
checkUnixSocketAddress(bindAt, "bindAt")
let impl = SocketCommon<ActualPlatformSocket>(UNIX, AddressFamily.UNIX, SocketMode.StreamingMode)
impl.localAddress = bindAt
this.impl = impl
}
/**
* SO_SNDBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired outgoing buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop sendBufferSize: Int64 {
get() { this.impl.getSendBufferSize() }
set(newSize) { this.impl.setSendBufferSize(newSize) }
}
/**
* SO_RCVBUF option, providing a way to specify hint for the underlying
* native socket implementation about the desired receive buffer size.
*
* Changing this option is not guaranteed to have any effect since it's
* completely up to the operating system.
*
* Reading this property could also provide non-realistic values on some systems in
* some cases so no logic should strictly rely on this value.
*
* @throws IllegalArgumentException if the specified buffer size is negative or 0.
*/
public mut prop receiveBufferSize: Int64 {
get() { this.impl.getReceiveBufferSize() }
set(newSize) { this.impl.setReceiveBufferSize(newSize) }
}
/**
* Configure incoming connections backlog size. This only works before binding socket.
* Changing this value is not guaranteed to be actually applied since the operating system may decide to
* change or bump it, or simply ignore.
**/
public mut prop backlogSize: Int64 {
get() {
Int64(backlogSize_)
}
set(newSize) {
this.impl.checkNotBound()
this.impl.checkNotClosed()
backlogSize_ = match {
case newSize <= 0 => throw IllegalArgumentException("BacklogSize should be positive: ${newSize}.")
case newSize >= Int64(Int32.Max) => Int32.Max - 1
case _ => Int32(newSize)
}
}
}
/**
* Bind a streaming UNIX domain socket.
*
* This function also does listen just after binding creating an incoming connections queue that could be accessed via "accept()" function.
*
* This operation does atomically create a socket file at the local path.
* If the path is already existing then bind() fails with SocketException.
*/
public override func bind(): Unit {
this.impl.bind(backlogSize_)
}
/**
* Accept a client socket, waiting for one if there are no pending connection requests.
*
* The OS implementation usually provides an incoming connection requests queue,
* so calling accept() does takes a candidate from the queue
* or wait until we get some request if the queue is empty.
*
* @throws SocketTimeoutException if the spcified timeout allapsed before got pending connection request
* @throws IllegalArgumentException if the specified timeout duration is negative.
*/
public override func accept(timeout!: ?Duration): UnixSocket {
let accepted = this.impl.accept(timeout) ?? SocketException.throwClosedException()
return UnixSocket(accepted)
}
/**
* Accept a client socket, waiting for one if there are no pending connection requests.
*
* The OS implementation usually provides an incoming connection requests queue,
* so calling accept() does takes a candidate from the queue
* or wait until we get some request if the queue is empty.
*/
public override func accept(): UnixSocket {
accept(timeout: None)
}
/**
* Close the socket releasing all resources. All operations except for close() and isClose() are no longer available.
* This function is reentrant.
**/
public override func close(): Unit {
this.impl.close()
}
/**
* Checks whether this socket has been explicitly closed via close()
**/
public override func isClosed(): Bool {
this.impl.isClosed()
}
/**
* Read the specified socket option writing the result to value buffer
* of the specified valueLength (in bytes).
* Before invoking this function valueLength should be initialized with the buffer size
* After invoking this function valueLength will contain the actual result
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when getsockopt returns -1).
*/
public func getSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: CPointer<UIntNative>): Unit {
unsafe { this.impl.getSocketOption(level, option, value, valueLength) }
}
/**
* Write the specified socket option from value buffer having valueLength
* size in bytes.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1).
*/
public func setSocketOption(level: Int32, option: Int32, value: CPointer<Unit>, valueLength: UIntNative): Unit {
unsafe { this.impl.setSocketOption(level, option, value, valueLength) }
}
/**
* Read the specified socket option returning it's value as IntNative result.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionIntNative(level: Int32, option: Int32): IntNative {
this.impl.getSocketOptionIntNative(level, option)
}
/**
* Write a numeric IntNative value to the specified socket option.
*
* See SocketOptions for popular option constants.
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionIntNative(level: Int32, option: Int32, value: IntNative): Unit {
this.impl.setSocketOptionIntNative(level, option, value)
}
/**
* Read the specified socket option returning it's value as a boolean value
* converting it from an IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as 0 => false, other values => true.
*
* Throws an exception if failed (when getsockopt returns -1) or if the result
* has size different from IntNative.
*/
public func getSocketOptionBool(level: Int32, option: Int32): Bool {
this.impl.getSocketOptionBool(level, option)
}
/**
* Write a boolean value to the specified socket option converting it to IntNative.
*
* See SocketOptions for popular option constants.
*
* The conversion is defined as false => 0, true => 1
*
* Throws an exception if failed (when setsockopt returns -1), for example
* when the option size is different from IntNative.
*/
public func setSocketOptionBool(level: Int32, option: Int32, value: Bool): Unit {
this.impl.setSocketOptionBool(level, option, value)
}
public override func toString(): String {
"UnixServerSocket(${this.impl.toString()})"
}
}