Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

Overview

APIDoc Build Status - Master macOS iOS Linux Apache 2 Slack Status

BlueSocket

Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

Prerequisites

Swift

  • Swift Open Source swift-5.1-RELEASE toolchain (Minimum REQUIRED for latest release)
  • Swift Open Source swift-5.4-RELEASE toolchain (Recommended)
  • Swift toolchain included in Xcode Version 12.5 (12E262) or higher.

macOS

  • macOS 10.11.6 (El Capitan) or higher.
  • Xcode Version 11 or higher using one of the above toolchains.
  • Xcode Version 12 or higher using the included toolchain (Recommended).

iOS

  • iOS 10.0 or higher
  • Xcode Version 11 or higher using one of the above toolchains.
  • Xcode Version 12 or higher using the included toolchain (Recommended).

Note:

If creating a UDP server on iOS, you may need to follow a few steps:

Linux

  • Ubuntu 16.04 or 18.04
  • One of the Swift Open Source toolchains listed above.

Other Platforms

  • BlueSocket is NOT supported on watchOS since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
  • BlueSocket should work on tvOS but has NOT been tested.

Add-ins

  • BlueSSLService can be used to add SSL/TLS support.
    • If using this package, please note that the libssl-dev package is required to be installed when building on Linux.

Build

To build Socket from the command line:

% cd <path-to-clone>
% swift build

Testing

To run the supplied unit tests for Socket from the command line:

% cd <path-to-clone>
% swift build
% swift test

Using BlueSocket

Including in your project

Swift Package Manager

To include BlueSocket into a Swift Package Manager package, add it to the dependencies attribute defined in your Package.swift file. You can select the version using the majorVersion and minor parameters. For example:

	dependencies: [
		.Package(url: "https://github.com/Kitura/BlueSocket.git", majorVersion: <majorVersion>, minor: <minor>)
	]

Carthage

To include BlueSocket in a project using Carthage, add a line to your Cartfile with the GitHub organization and project names and version. For example:

	github "Kitura/BlueSocket" ~> <majorVersion>.<minor>

CocoaPods

To include BlueSocket in a project using CocoaPods, you just add BlueSocket to your Podfile, for example:

    platform :ios, '10.0'

    target 'MyApp' do
        use_frameworks!
        pod 'BlueSocket'
    end

Before starting

The first thing you need to do is import the Socket framework. This is done by the following:

import Socket

Family, Type and Protocol Support

BlueSocket supports the following families, types and protocols:

  • Families:
    • IPV4: Socket.ProtocolFamily.inet
    • IPV6: Socket.ProtocolFamily.inet6
    • UNIX: Socket.ProtocolFamily.unix
  • Types:
    • Stream: Socket.SocketType.stream
    • Datagram: Socket.SocketType.datagram
  • Protocols:
    • TCP: Socket.SocketProtocol.tcp
    • UDP: Socket.SocketProtocol.udp
    • UNIX: Socket.SocketProtocol.unix

Creating a socket.

BlueSocket provides four different factory methods that are used to create an instance. These are:

  • create() - This creates a fully configured default socket. A default socket is created with family: .inet, type: .stream, and proto: .tcp.
  • create(family family: ProtocolFamily, type: SocketType, proto: SocketProtocol) - This API allows you to create a configured Socket instance customized for your needs. You can customize the protocol family, socket type and socket protocol.
  • create(connectedUsing signature: Signature) - This API will allow you create a Socket instance and have it attempt to connect to a server based on the information you pass in the Socket.Signature.
  • create(fromNativeHandle nativeHandle: Int32, address: Address?) - This API lets you wrap a native file descriptor describing an existing socket in a new instance of Socket.

Setting the read buffer size.

BlueSocket allows you to set the size of the read buffer that it will use. Then, depending on the needs of the application, you can change it to a higher or lower value. The default is set to Socket.SOCKET_DEFAULT_READ_BUFFER_SIZE which has a value of 4096. The minimum read buffer size is Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE which is set to 1024. Below illustrates how to change the read buffer size (exception handling omitted for brevity):

let mySocket = try Socket.create()
mySocket.readBufferSize = 32768

The example above sets the default read buffer size to 32768. This setting should be done prior to using the Socket instance for the first time.

Closing a socket.

To close the socket of an open instance, the following function is provided:

  • close() - This function will perform the necessary tasks in order to cleanly close an open socket.

Listen on a socket (TCP/UNIX).

To use BlueSocket to listen for a connection on a socket the following API is provided:

  • listen(on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG, allowPortReuse: Bool = true, node: String? = nil) The first parameter port, is the port to be used to listen on. The second parameter, maxBacklogSize allows you to set the size of the queue holding pending connections. The function will determine the appropriate socket configuration based on the port specified. For convenience on macOS, the constant Socket.SOCKET_MAX_DARWIN_BACKLOG can be set to use the maximum allowed backlog size. The default value for all platforms is Socket.SOCKET_DEFAULT_MAX_BACKLOG, currently set to 50. For server use, it may be necessary to increase this value. To allow the reuse of the listening port, set allowPortReuse to true. If set to false, a error will occur if you attempt to listen on a port already in use. The DEFAULT behavior is to allow port reuse. The last parameter, node, can be used to listen on a specific address. The value passed is an optional String containing the numerical network address (for IPv4, numbers and dots notation, for iPv6, hexidecimal strting). The DEFAULT behavior is to search for an appropriate interface. If node is improperly formatted a SOCKET_ERR_GETADDRINFO_FAILED error will be returned. If node is properly formatted but the address specified is not available, a SOCKET_ERR_BIND_FAILED will be returned.
  • listen(on path: String, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) This API can only be used with the .unix protocol family. The first parameter path, is the path to be used to listen on. The second parameter, maxBacklogSize allows you to set the size of the queue holding pending connections. The function will determine the appropriate socket configuration based on the port specified. For convenience on macOS, the constant Socket.SOCKET_MAX_DARWIN_BACKLOG can be set to use the maximum allowed backlog size. The default value for all platforms is Socket.SOCKET_DEFAULT_MAX_BACKLOG, currently set to 50. For server use, it may be necessary to increase this value.

Example:

The following example creates a default Socket instance and then immediately starts listening on port 1337. Note: Exception handling omitted for brevity, see the complete example below for an example of exception handling.

var socket = try Socket.create()
try socket.listen(on: 1337)

Accepting a connection from a listening socket (TCP/UNIX).

When a listening socket detects an incoming connection request, control is returned to your program. You can then either accept the connection or continue listening or both if your application is multi-threaded. BlueSocket supports two distinct ways of accepting an incoming connection. They are:

  • acceptClientConnection(invokeDelegate: Bool = true) - This function accepts the connection and returns a new Socket instance based on the newly connected socket. The instance that was listening in unaffected. If invokeDelegate is false and the Socket has an SSLService delegate attached, you MUST call the invokeDelegateOnAccept method using the Socket instance that is returned by this function.
  • invokeDelegateOnAccept(for newSocket: Socket) - If the Socket instance has a SSLService delegate, this will invoke the delegates accept function to perform SSL negotiation. It should be called with the Socket instance returned by acceptClientConnection. This function will throw an exception if called with the wrong Socket instance, called multiple times, or if the Socket instance does NOT have a SSLService delegate.
  • acceptConnection() - This function accepts the incoming connection, replacing and closing the existing listening socket. The properties that were formerly associated with the listening socket are replaced by the properties that are relevant to the newly connected socket.

Connecting a socket to a server (TCP/UNIX).

In addition to the create(connectedUsing:) factory method described above, BlueSocket supports three additional instance functions for connecting a Socket instance to a server. They are:

  • connect(to host: String, port: Int32, timeout: UInt = 0) - This API allows you to connect to a server based on the hostname and port you provide. Note: an exception will be thrown by this function if the value of port is not in the range 1-65535. Optionally, you can set timeout to the number of milliseconds to wait for the connect. Note: If the socket is in blocking mode it will be changed to non-blocking mode temporarily if a timeout greater than zero (0) is provided. The returned socket will be set back to its original setting (blocking or non-blocking). If the socket is set to non-blocking and no timeout value is provided, an exception will be thrown. Alternatively, you can set the socket to non-blocking after successfully connecting.
  • connect(to path: String) - This API can only be used with the .unix protocol family. It allows you to connect to a server based on the path you provide.
  • connect(using signature: Signature) - This API allows you specify the connection information by providing a Socket.Signature instance containing the information. Refer to Socket.Signature in Socket.swift for more information.

Reading data from a socket (TCP/UNIX).

BlueSocket supports four different ways to read data from a socket. These are (in recommended use order):

  • read(into data: inout Data) - This function reads all the data available on a socket and returns it in the Data object that was passed.
  • read(into data: NSMutableData) - This function reads all the data available on a socket and returns it in the NSMutableData object that was passed.
  • readString() - This function reads all the data available on a socket and returns it as an String. A nil is returned if no data is available for reading.
  • read(into buffer: UnsafeMutablePointer<CChar>, bufSize: Int, truncate: Bool = false) - This function allows you to read data into a buffer of a specified size by providing an unsafe pointer to that buffer and an integer the denotes the size of that buffer. This API (in addition to other types of exceptions) will throw a Socket.SOCKET_ERR_RECV_BUFFER_TOO_SMALL if the buffer provided is too small, unless truncate = true in which case the socket will act as if only bufSize bytes were read (unretrieved bytes will be returned in the next call). If truncate = false, you will need to call again with proper buffer size (see Error.bufferSizeNeededin Socket.swift for more information).
  • Note: All of the read APIs above except readString() can return zero (0). This can indicate that the remote connection was closed or it could indicate that the socket would block (assuming you've turned off blocking). To differentiate between the two, the property remoteConnectionClosed can be checked. If true, the socket remote partner has closed the connection and this Socket instance should be closed.

Writing data to a Socket (TCP/UNIX).

In addition to reading from a socket, BlueSocket also supplies four methods for writing data to a socket. These are (in recommended use order):

  • write(from data: Data) - This function writes the data contained within the Data object to the socket.
  • write(from data: NSData) - This function writes the data contained within the NSData object to the socket.
  • write(from string: String) - This function writes the data contained in the String provided to the socket.
  • write(from buffer: UnsafeRawPointer, bufSize: Int) - This function writes the data contained within the buffer of the specified size by providing an unsafe pointer to that buffer and an integer that denotes the size of that buffer.

Listening for a datagram message (UDP).

BlueSocket supports three different ways to listen for incoming datagrams. These are (in recommended use order):

  • listen(forMessage data: inout Data, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - This function listens for an incoming datagram, reads it and returns it in the passed Data object. It returns a tuple containing the number of bytes read and the Address of where the data originated.
  • listen(forMessage data: NSMutableData, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - This function listens for an incoming datagram, reads it and returns it in the passed NSMutableData object. It returns a tuple containing the number of bytes read and the Address of where the data originated.
  • listen(forMessage buffer: UnsafeMutablePointer<CChar>, bufSize: Int, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) - This function listens for an incoming datagram, reads it and returns it in the passed Data object. It returns a tuple containing the number of bytes read and the Address of where the data originated.
  • Note 1: These functions will determine the appropriate socket configuration based on the port specified. Setting the value of port to zero (0) will cause the function to determine a suitable free port.
  • Note 2: The parameter, maxBacklogSize allows you to set the size of the queue holding pending connections. The function will determine the appropriate socket configuration based on the port specified. For convenience on macOS, the constant Socket.SOCKET_MAX_DARWIN_BACKLOG can be set to use the maximum allowed backlog size. The default value for all platforms is Socket.SOCKET_DEFAULT_MAX_BACKLOG, currently set to 50. For server use, it may be necessary to increase this value.

Reading a datagram (UDP).

BlueSocket supports three different ways to read incoming datagrams. These are (in recommended use order):

  • readDatagram(into data: inout Data) - This function reads an incoming datagram and returns it in the passed Data object. It returns a tuple containing the number of bytes read and the Address of where the data originated.
  • readDatagram(into data: NSMutableData) - This function reads an incoming datagram and returns it in the passed NSMutableData object. It returns a tuple containing the number of bytes read and the Address of where the data originated.
  • readDatagram(into buffer: UnsafeMutablePointer<CChar>, bufSize: Int) - This function reads an incoming datagram and returns it in the passed Data object. It returns a tuple containing the number of bytes read and the Address of where the data originated. If the amount of data read is more than bufSize only bufSize will be returned. The remainder of the data read will be discarded.

Writing a datagram (UDP).

BlueSocket also supplies four methods for writing datagrams to a socket. These are (in recommended use order):

  • write(from data: Data, to address: Address) - This function writes the datagram contained within the Data object to the socket.
  • write(from data: NSData, to address: Address) - This function writes the datagram contained within the NSData object to the socket.
  • write(from string: String, to address: Address) - This function writes the datagram contained in the String provided to the socket.
  • write(from buffer: UnsafeRawPointer, bufSize: Int, to address: Address) - This function writes the data contained within the buffer of the specified size by providing an unsafe pointer to that buffer and an integer that denotes the size of that buffer.
  • Note: In all four of the APIs above, the address parameter represents the address for the destination you are sending the datagram to.

IMPORTANT NOTE about NSData and NSMutableData

The read and write APIs above that use either NSData or NSMutableData will probably be deprecated in the not so distant future.

Miscellaneous Utility Functions

  • hostnameAndPort(from address: Address) - This class function provides a means to extract the hostname and port from a given Socket.Address. On successful completion, a tuple containing the hostname and port are returned.
  • checkStatus(for sockets: [Socket]) - This class function allows you to check status of an array of Socket instances. Upon completion, a tuple containing two Socket arrays is returned. The first array contains the Socket instances are that have data available to be read and the second array contains Socket instances that can be written to. This API does not block. It will check the status of each Socket instance and then return the results.
  • wait(for sockets: [Socket], timeout: UInt, waitForever: Bool = false) - This class function allows for monitoring an array of Socket instances, waiting for either a timeout to occur or data to be readable at one of the monitored Socket instances. If a timeout of zero (0) is specified, this API will check each socket and return immediately. Otherwise, it will wait until either the timeout expires or data is readable from one or more of the monitored Socket instances. If a timeout occurs, this API will return nil. If data is available on one or more of the monitored Socket instances, those instances will be returned in an array. If the waitForever flag is set to true, the function will wait indefinitely for data to become available regardless of the timeout value specified.
  • createAddress(host: String, port: Int32) - This class function allows for the creation of Address enum given a host and port. On success, this function returns an Address or nil if the host specified doesn't exist.
  • isReadableOrWritable(waitForever: Bool = false, timeout: UInt = 0) - This instance function allows to determine whether a Socket instance is readable and/or writable. A tuple is returned containing two Bool values. The first, if true, indicates the Socket instance has data to read, the second, if true, indicates that the Socket instance can be written to. waitForever if true, causes this routine to wait until the Socket is either readable or writable or an error occurs. If false, the timeout parameter specifies how long to wait. If a value of zero (0) is specified for the timeout value, this function will check the current status and immediately return. This function returns a tuple containing two booleans, the first readable and the second, writable. They are set to true if the Socket is either readable or writable repsectively. If neither is set to true, a timeout has occurred. Note: If you're attempting to write to a newly connected Socket, you should ensure that it's writable before attempting the operation.
  • setBlocking(shouldBlock: Bool) - This instance function allows you control whether or not this Socket instance should be placed in blocking mode or not. Note: All Socket instances are, by default, created in blocking mode.
  • setReadTimeout(value: UInt = 0) - This instance function allows you to set a timeout for read operations. value is a UInt the specifies the time for the read operation to wait before returning. In the event of a timeout, the read operation will return 0 bytes read and errno will be set to EAGAIN.
  • setWriteTimeout(value: UInt = 0) - This instance function allows you to set a timeout for write operations. value is a UInt the specifies the time for the write operation to wait before returning. In the event of a timeout, the write operation will return 0 bytes written and errno will be set to EAGAIN for TCP and UNIX sockets, for UDP, the write operation will succeed regardless of the timeout value.
  • udpBroadcast(enable: Bool) - This instance function is used to enable broadcast mode on a UDP socket. Pass true to enable broadcast, false to disable. This function will throw an exception if the Socket instance is not a UDP socket.

Complete Example

The following example shows how to create a relatively simple multi-threaded echo server using the new GCD based Dispatch API. What follows is code for a simple echo server that once running, can be accessed via telnet ::1 1337.

import Foundation
import Socket
import Dispatch

class EchoServer {
	
	static let quitCommand: String = "QUIT"
	static let shutdownCommand: String = "SHUTDOWN"
	static let bufferSize = 4096
	
	let port: Int
	var listenSocket: Socket? = nil
	var continueRunningValue = true
	var connectedSockets = [Int32: Socket]()
	let socketLockQueue = DispatchQueue(label: "com.kitura.serverSwift.socketLockQueue")
	var continueRunning: Bool {
		set(newValue) {
			socketLockQueue.sync {
				self.continueRunningValue = newValue
			}
		}
		get {
			return socketLockQueue.sync {
				self.continueRunningValue
			}
		}
	}

	init(port: Int) {
		self.port = port
	}
	
	deinit {
		// Close all open sockets...
		for socket in connectedSockets.values {
			socket.close()
		}
		self.listenSocket?.close()
	}
	
	func run() {
		
		let queue = DispatchQueue.global(qos: .userInteractive)
		
		queue.async { [unowned self] in
			
			do {
				// Create an IPV6 socket...
				try self.listenSocket = Socket.create(family: .inet6)
				
				guard let socket = self.listenSocket else {
					
					print("Unable to unwrap socket...")
					return
				}
				
				try socket.listen(on: self.port)
				
				print("Listening on port: \(socket.listeningPort)")
				
				repeat {
					let newSocket = try socket.acceptClientConnection()
					
					print("Accepted connection from: \(newSocket.remoteHostname) on port \(newSocket.remotePort)")
					print("Socket Signature: \(String(describing: newSocket.signature?.description))")
					
					self.addNewConnection(socket: newSocket)
					
				} while self.continueRunning
				
			}
			catch let error {
				guard let socketError = error as? Socket.Error else {
					print("Unexpected error...")
					return
				}
				
				if self.continueRunning {
					
					print("Error reported:\n \(socketError.description)")
					
				}
			}
		}
		dispatchMain()
	}
	
	func addNewConnection(socket: Socket) {
		
		// Add the new socket to the list of connected sockets...
		socketLockQueue.sync { [unowned self, socket] in
			self.connectedSockets[socket.socketfd] = socket
		}
		
		// Get the global concurrent queue...
		let queue = DispatchQueue.global(qos: .default)
		
		// Create the run loop work item and dispatch to the default priority global queue...
		queue.async { [unowned self, socket] in
			
			var shouldKeepRunning = true
			
			var readData = Data(capacity: EchoServer.bufferSize)
			
			do {
				// Write the welcome string...
				try socket.write(from: "Hello, type 'QUIT' to end session\nor 'SHUTDOWN' to stop server.\n")
				
				repeat {
					let bytesRead = try socket.read(into: &readData)
					
					if bytesRead > 0 {
						guard let response = String(data: readData, encoding: .utf8) else {
							
							print("Error decoding response...")
							readData.count = 0
							break
						}
						if response.hasPrefix(EchoServer.shutdownCommand) {
							
							print("Shutdown requested by connection at \(socket.remoteHostname):\(socket.remotePort)")
							
							// Shut things down...
							self.shutdownServer()
							
							return
						}
						print("Server received from connection at \(socket.remoteHostname):\(socket.remotePort): \(response) ")
						let reply = "Server response: \n\(response)\n"
						try socket.write(from: reply)
						
						if (response.uppercased().hasPrefix(EchoServer.quitCommand) || response.uppercased().hasPrefix(EchoServer.shutdownCommand)) &&
							(!response.hasPrefix(EchoServer.quitCommand) && !response.hasPrefix(EchoServer.shutdownCommand)) {
							
							try socket.write(from: "If you want to QUIT or SHUTDOWN, please type the name in all caps. 😃\n")
						}
						
						if response.hasPrefix(EchoServer.quitCommand) || response.hasSuffix(EchoServer.quitCommand) {
							
							shouldKeepRunning = false
						}
					}
					
					if bytesRead == 0 {
						
						shouldKeepRunning = false
						break
					}
					
					readData.count = 0
					
				} while shouldKeepRunning
				
				print("Socket: \(socket.remoteHostname):\(socket.remotePort) closed...")
				socket.close()
				
				self.socketLockQueue.sync { [unowned self, socket] in
					self.connectedSockets[socket.socketfd] = nil
				}
				
			}
			catch let error {
				guard let socketError = error as? Socket.Error else {
					print("Unexpected error by connection at \(socket.remoteHostname):\(socket.remotePort)...")
					return
				}
				if self.continueRunning {
					print("Error reported by connection at \(socket.remoteHostname):\(socket.remotePort):\n \(socketError.description)")
				}
			}
		}
	}
	
	func shutdownServer() {
		print("\nShutdown in progress...")

		self.continueRunning = false
		
		// Close all open sockets...
		for socket in connectedSockets.values {
			
			self.socketLockQueue.sync { [unowned self, socket] in
				self.connectedSockets[socket.socketfd] = nil
				socket.close()
			}
		}
		
		DispatchQueue.main.sync {
			exit(0)
		}
	}
}

let port = 1337
let server = EchoServer(port: port)
print("Swift Echo Server Sample")
print("Connect with a command line window by entering 'telnet ::1 \(port)'")

server.run()

This server can be built by specifying the following Package.swift file using Swift 4.

import PackageDescription

let package = Package(
	name: "EchoServer",
	dependencies: [
		.package(url: "https://github.com/Kitura/BlueSocket.git", from:"1.0.8"),
	],
	targets: [
	.target(
		name: "EchoServer",
		dependencies: [
			"Socket"
		]),
	]
)

Or if you are still using Swift 3, by specifying the following Package.swift file.

import PackageDescription

let package = Package(
	name: "EchoServer",
	dependencies: [
	.Package(url: "https://github.com/Kitura/BlueSocket.git", majorVersion: 1, minor: 0),
	],
	exclude: ["EchoServer.xcodeproj"]
)

The following command sequence will build and run the echo server on Linux. If running on macOS or with any toolchain NEWER than the 8/18 toolchain, you can omit the -Xcc -fblocks switch as it's no longer needed.

$ swift build -Xcc -fblocks
$ .build/debug/EchoServer
Swift Echo Server Sample
Connect with a command line window by entering 'telnet ::1 1337'
Listening on port: 1337

Community

We love to talk server-side Swift and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

Comments
  • Remove unsafe access to Socket.Address

    Remove unsafe access to Socket.Address

    Description

    asAddr funcs were passing unsafe pointers outside of the callbacks in which try should be used Using callback to make all the access within these callbacks

    Motivation and Context

    Fixes bug where IPv6 address was 'cast' to sockaddr but actually was zero'd beyond the length of sockaddr_in and packets written to the wrong address

    Checklist:

    • [x] I have submitted a CLA form
    • [N/A] If applicable, I have updated the documentation accordingly.
    • [N/A] If applicable, I have added tests to cover my changes.
    opened by mcfedr 16
  • EXC_BAD_ACCESS when connect to unix domain socket

    EXC_BAD_ACCESS when connect to unix domain socket

    I have a unix domain socket created by tokio-uds, and I can make connection with it normally by net.socket of node.js.

    But when I connect to this socket via BlueSocket:

    let socket = try! Socket.create(family: .unix)
    try! socket.connect(to: "/Users/Plutonist/Downloads/hello.socket")
    

    would cause crash at Socket.swift:1927:

    1926    // Create the signature...
    1927*   self.signature = try Signature(socketType: .stream, proto: .unix, path: path)
    1928    guard let signature = self.signature else {
    

    If I use it this way:

    let socket = try! Socket.create()
    try! socket.connect(to: "/Users/Plutonist/Downloads/hello.socket")
    

    Will throw an exception:

    Thread 1: Fatal error: 'try!' expression unexpectedly raised an error:
    Error code: -9973(0x-26F5), Socket has the wrong protocol, it must be UNIX socket
    

    This problem is very weird, and I have confirmed that the cocoa's sandbox mechanism is turned off and that FileManager can also obtain socket file stats.

    opened by wspl 15
  • Mem read 0x0 on 0.12.85

    Mem read 0x0 on 0.12.85

    Hi,

    When I do a isReadableOrWritable() with a default TCP socket creation, I get a error: memory read failed for 0x0.

    I can confirm this issue does not exist in 0.12.82.

    opened by qhua948 13
  • How to read long strings

    How to read long strings

    Hey all,

    I'm using this library (version 0.12.78) to send and receive some JSON Strings of 3000+ characters including escaped quotations ( " ) and escaped backslashes ( \ ). I won't post my schema but I can probably generate another sample String if needed.

    When I call socket.write(from: String) with a TCP ipv4 socket on one of these longer JSON Strings and read it on the other end, the received result is always incorrectly truncated before the end of the string. Using socket.write(from: Data), however, with stringvar.data(using: String.Encoding.utf8) works like a charm.

    Any idea what's going on here? Looks like the culprit is string.utf8CString.withUnsafeBufferPointer() on line 3011 of Socket.swift in this version. Could be a Swift 4 bug? I'm seeing Swift 4 documentation using string.utf8 instead of utf8CString?

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html

    opened by andybiar 12
  • connect not using right family when resolving Hostname

    connect not using right family when resolving Hostname

    Hi,

    I've two iOS devices which are communicating via BlueSocket. The client is finding the server via Bonjour and thus uses the hostname of the server to connect to it (something like "yourIpad.local."). If the devices are on a "normal" WiFi, everything works. The sockets are created with Socket.create(family: .inet, type: .stream, proto: .tcp)

    If I now enable the personal hotspot on one device and join this WiFi with the other device, the client has troubles connecting to the server. I traced it down to the following:

    The connect(to host: String, port: Int32, timeout: UInt = 0) method is looking up the hostname via: getaddrinfo(host, String(port), &hints, &targetInfo) After that, it iterates through the addresses and tries to connect. For some reason, when using the personal hotspot, the first addrInfo from the OS is an IPv6 entry ( info!.pointee.ai_family == 30). The client tries to connect to the IPv6 address which results in a timeout since the server is only listening for IPv4. After the timeout, it uses the second addrInfo record (it's a while loop) and can connect to the server.

    From my point of view, the "hints" variable for the getaddrinfo-call needs to specify the family of the socket to pass it to the getaddrinfo call - currently it passes "AF_UNSPEC" as ai_family parameter. If I change the hint-variable to

    			var hints = addrinfo(
    				ai_flags: AI_PASSIVE,
    				ai_family: signature?.protocolFamily.value ?? AF_UNSPEC,
    				ai_socktype: socketType.value,
    				ai_protocol: 0,
    				ai_addrlen: 0,
    				ai_canonname: nil,
    				ai_addr: nil,
    				ai_next: nil)
    

    Everything works as expected.

    What do you think of it?

    opened by ghost 10
  • Incompatible with swift-argument-parser v1.0.0+

    Incompatible with swift-argument-parser v1.0.0+

    BlueSocket currently has a dependency on swift-argument-parser version 0.4.1..<1.0. This prevents use of the current v1.1.3 release of swift-argument-parser. (swift-argument-parser version 1.0 was released 2021-09-10.)

    Could BlueSocket be made compatible with the current release of swift-argument-parser and this version constraint relaxed in Package.swift?

    Background: This issue surfaced in PostgresClientKit (which I maintain); see Issue #41. The person reporting the issue wondered why BlueSocket has a dependency on swift-argument-parser. Could you please comment on that? This dependency appears to have been introduced last year by @dannys42 in commit 4dd6c81. Is this dependency required only for testing?

    Thanks!

    opened by pitfield 9
  • Performance issues

    Performance issues

    I've tried to use BlueSocket in MongoKitten which is a swift driver for MongoDB.

    After replacing Vapor Socket by BlueSocket, I ran some performance tests. The results showed an important difference between the two implementations on MacOS and a huge one on Linux.

    To run the test you can clone this repo. Master branch uses the Vapor Socket and bluesocket branch uses the BlueSocket.

    The bluesocket code is all in the Socket.swift file. Maybe I did something wrong in my implementation ?

    Tests Results

    All Tests are done in Release mode.

    Here the results from performance tests on Linux :

    Linux 16.04 - 4.4.0-59-generic Intel(R) Xeon(R) CPU E3-1245 V2 @ 3.40GHz - 32GiB Swift version 3.0.2 (swift-3.0.2-RELEASE)

    BlueSocket

    • Max : 5.32257395982742
    • Min : 3.25634396076202
    • Average : 3.61253277897835
    • Median : 3.46378147602081
    • Execution Time : 361.478877007961
    • Rounds : 100

    VaporSocket

    • Max : 0.695515990257263
    • Min : 0.433806002140045
    • Average : 0.532387097477913
    • Median : 0.514575988054276
    • Execution Time : 53.2749119997025
    • Rounds : 100

    And on MacOS: Darwin Kernel Version 16.4.0 Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)

    swift build -c release .build/release/SwiftPerformance

    • Max : 0.963047981262207
    • Min : 0.830860018730164
    • Average : 0.873546527028084
    • Median : 0.872366487979889
    • Execution Time : 87.3994210362434
    • Rounds : 100

    VaporSocket

    • Max : 0.877934038639069
    • Min : 0.666562974452972
    • Average : 0.719885479807854
    • Median : 0.714864492416382
    • Execution Time : 72.033077955246
    • Rounds : 100
    opened by lgaches 9
  • Problem compiling ZERO function on Linux. _fds_bits should set 32 bits.

    Problem compiling ZERO function on Linux. _fds_bits should set 32 bits.

    Hi,

    First let me say thank you. This is a really great project and love that it's already been updated to the latest Swift snapshot.

    I'm trying to compile the latest release 0.7.1 on Debian Linux Jessie on armv7l using the latest Swift snapshot but compile fails with:

    Socket-0.7.1/Sources/SocketUtils.swift:121:20: error: cannot assign value of type '(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)' to type '(__fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask, __fd_mask)' (aka '(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)') set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

    Since _fd_mask is defined in sys/select.h as a long it should be 32 bits and sure enough replacing set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) with set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) solved the problem and everything compiled.

    I'm not sure why it's currently set to only 16 bits on Linux inside the #if os(Linux) block?

    SET, CLR and ISSET need to be updated too and be very similar to the macOS version, minus the fd_set and __fd_set difference (perhaps there's a way to map that? my Swift/C integration-fu is not quite there yet)

    opened by jmarcelino 9
  • listen(forMessage data: inout Data, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG)

    listen(forMessage data: inout Data, on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG)

    hello, i am trying to send a receive data over udp. And i am able to send just fine using the write function. But when i try to use the listen function above i keep getting "invalid argument". If its not too much trouble could someone give me an example of using this listen function, and the init of all of the arguments. I think im creating my Data object wrong or something

    opened by cloeffler 8
  • Add Xcode9 and 6-29 snapshot to Travis IBM-Swift/Kitura#1121

    Add Xcode9 and 6-29 snapshot to Travis IBM-Swift/Kitura#1121

    Description

    Motivation and Context

    How Has This Been Tested?

    Checklist:

    • [ ] I have submitted a CLA form
    • [ ] If applicable, I have updated the documentation accordingly.
    • [ ] If applicable, I have added tests to cover my changes.
    opened by quanvo87 8
  • Trouble keeping a reference to a Socket

    Trouble keeping a reference to a Socket

    It is unlikely this issue is specifically related to BlueSocket but I thought I would reach out anyway to see if I'm missing something about how sockets live.

    My code is based on the sample. A reference to the EchoServer class is maintained by a class instance (Device) that instantiates it and calls the run method. Subsequent to a connection having been made, Device calls a method in the EchoServer class that tries to make use of the socket, a reference to which is help in an EchoServer var. But whenever I make that subsequent class, the reference to the socket is nil.

    What do I need to do to make sure my EchoServer class maintains the reference to the socket?

    Any help would be most appreciated!

    opened by robreuss 7
  • Unable to detect closed socket

    Unable to detect closed socket

    I'm not reciving zero bytes when the socket loses connection. Could something have changed regarding this?

    It used to return bytesRead = 0 when the connection was closed.

                socketQueue.async { [weak self] in
                    var readData = Data()
                    var shouldKeepRunning = true
                    do {
                        repeat {
                            let bytesRead = try socket.read(into: &readData)
                            if bytesRead > 0 {
                                let readString = String(data: readData, encoding: .utf8) ?? ""
                                self?.gotInput(string: readString)
                                readData = Data()
                            } else {
                                shouldKeepRunning = false
                                break
                            }
                        } while shouldKeepRunning
    
                        // close socket when bytesRead is zero
                        socket.close()
                        self?.connectionClosed()
                    } catch {
                        self?.status = .error(message: error.localizedDescription)
                        log.error("Read error: \(error). Read data: \(readData)")
                    }
                }
    
    opened by Joebayld 3
  • Tcp Incomplete receiving data

    Tcp Incomplete receiving data

    After connecting to TCP, I waited to receive data after sending data, and found that only half of the received data was received. How to solve the problem of not receiving half of the data received 截屏2022-05-18 15 40 54

    opened by ShineYangGod 1
  • Can not receive tcp packets in hotspot

    Can not receive tcp packets in hotspot

    Hi, Thanks for your awesome library. My problem is that I can't receive TCP packets through the hotspot, but I can get them in a regular network by your sample code. Are there any restrictions in the hotspot network?

    opened by arashetm 1
  • Get local IP address

    Get local IP address

    Is is somehow possible with this library to get the local IP address to which the socket is currently bound? E.g. I have following Android Java code which I need to translate to Swift

    private static InetAddress getOutboundAddress(SocketAddress remoteAddress) {
            InetAddress localAddress = null;
            try {
                DatagramSocket sock = new DatagramSocket();
                // connect is needed to bind the socket and retrieve the local address later (it would return 0.0.0.0 otherwise)
                sock.connect(remoteAddress);
                localAddress = sock.getLocalAddress();
    
                sock.disconnect();
                sock.close();
            } catch (Exception e) {
                // ignore
            }
    
            return localAddress;
    }
    

    is there a way which is similar to localAddress = sock.getLocalAddress();?

    opened by grill2010 1
  • Error code: -9993(0x-2709), Invalid argument

    Error code: -9993(0x-2709), Invalid argument

    I'm having an odd issue that I can't seem to be able to solve.

    In my program I have a main unix socket that accept message and within the same program I have cli that create a socket and write to the main socket. The connection to main has no issues, it's when I write, the main socket error out with Error code: -9993(0x-2709), Invalid argument

    Main Socket:

      func attach() async {
        do {
          try socket.listen(on: socketPath)
          log.info("Listening on \(socketPath)")
          while true {
            let socket = try Socket.create(family: .unix, type: .stream, proto: .unix) 
            let conn = try socket.acceptClientConnection()
            let msg = try conn.readString()?.trimmingCharacters(in: .whitespacesAndNewlines)
            conn.close()
           // await .......
          }
        } catch { log.error("Socket error: \(error)")  }
      }
    

    CLI socket write:

    
    do {
      let socket = try Socket.create(family: .unix, type: .stream, proto: .unix)
      try socket.connect(to: socketPath)
      try socket.write(from: "-d restart")
      return
    } catch { ... }
    
    opened by kkharji 6
Releases(2.0.2)
  • 2.0.0(Jun 19, 2021)

  • 1.0.52(Nov 23, 2019)

    Version 1.0

    Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

    Prerequisites

    Swift

    • Swift Open Source swift-4.0.0-RELEASE toolchain (Minimum REQUIRED for latest release)
    • Swift Open Source swift-5.0-RELEASE toolchain (Recommended)
    • Swift toolchain included in Xcode Version 10.2 (10E125) or higher.

    macOS

    • macOS 10.11.6 (El Capitan) or higher.
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.2 (10E125) or higher using the included toolchain (Recommended).

    iOS

    • iOS 10.0 or higher
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.2 (10E125) or higher using the included toolchain (Recommended).

    Linux

    • Ubuntu 16.04 (or 16.10 but only tested on 16.04 and 18.04).
    • One of the Swift Open Source toolchains listed above.

    Other Platforms

    • BlueSocket is NOT supported on watchOS since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
    • BlueSocket should work on tvOS but has NOT been tested.

    Add-ins

    • BlueSSLService can be used to add SSL/TLS support.
      • If using this package, please note that the libssl-dev package is required to be installed when building on Linux.

    Changes since 1.0.0

    • When calling getaddrinfo(), the hints variable should reflect the protocol family of the socket.
    • Added new parameter to connect() to allow the caller to force the connection to the specific family of the Socket instance making call. The default behavior is to allow connection to any socket family.
    • Big endian fixes. PR #130.
    • Update to Swift 4.1.
    • Fixed connect() for UDP sockets. PR #137.
    • Added CI support for Swift 4.2 builds. PR #138.
    • Improve using Signature to connect to socket. PR #147.
    • Update to use Swift 4.2 as default. PR #151.
    • Resolve Swift 5 compilation warnings. Drop Swift 3 support. PR #154.
    • Added new parameter to TCP version of listen API to allow caller to specify a particular address to listen on. This new parameter is defaulted to nil and therefore should NOT affect current callers.
    • Update the example in the README to correct a data race condition. Issue #115.
    • Update CI support to use Swift 4.2.3. PR #169
    • Update for Swift 5.0. PR #170.
    • Add CI support for Xcode 11.
    • Fixed problem with endianess on big iron. PR #177.
    • Update to use Swift 5.1 as default.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Feb 27, 2018)

    Version 1.0

    Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

    Prerequisites

    Swift

    • Swift Open Source swift-4.0.0-RELEASE toolchain (Minimum REQUIRED for latest release)
    • Swift Open Source swift-4.2-RELEASE toolchain (Recommended)
    • Swift toolchain included in Xcode Version 10.0 (10A255) or higher.

    macOS

    • macOS 10.11.6 (El Capitan) or higher.
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.0 (10A255) or higher using the included toolchain (Recommended).

    iOS

    • iOS 10.0 or higher
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.0 (10A255) or higher using the included toolchain (Recommended).

    Linux

    • Ubuntu 16.04 (or 16.10 but only tested on 16.04).
    • One of the Swift Open Source toolchain listed above.

    Other Platforms

    • BlueSocket is NOT supported on watchOS since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
    • BlueSocket should work on tvOS but has NOT been tested.

    Add-ins

    Changes since 1.0.0

    • When calling getaddrinfo(), the hints variable should reflect the protocol family of the socket. See issue #128.
    • Added new parameter to connect() to allow the caller to force the connection to the specific family of the Socket instance making call. The default behavior is to allow connection to any socket family. See issues #129 and #128.
    • Added support for big endian devices. PR #130.
    • Added descriptive error messages for internal errors. PR #131.
    • Update for Swift 4.1.
    • Fixed minor warnings on Linux.
    • Fixed problem with connect() when using UDP sockets. PR #137.
    • Update to include Swift 4.2 in CI builds.
    • Added prerequisite that the libssl-dev package is required to be installed when building on Linux if using the BlueSSLService add-in.
    • Minor license update.
    • Performance fix for debug mode. PR #144.
    • Added test for issue #139.
    • connect using signature changes. PR #147.
    • Updates for Xcode 10 to project.
    • Swift 4.2 support.
    • Fixed buffer overflow problem that only showed up in optimized code. Issue #139.
    • Make Swift 4.2 the default compiler in project.
    • Update for Swift 4.2 (PR #151) and Xcode 10.
    • Added CI support for building with Swift 5. PR #154.
    • Added new parameter to TCP version of listen API to allow caller to specify a particular address to listen on. This new parameter is defaulted to nil and therefore should affect current callers.
    Source code(tar.gz)
    Source code(zip)
  • 0.12.94(Nov 29, 2016)

    This release minimally requires use of the swift-3.1.1-RELEASE toolchain or the swift-4.0.0-RELEASE toolchain which is recommended.

    • Compatible with Xcode 9.0 (9A235) General Release or higher using one of the above toolchains.
    • Added support for arm architecture for FD utilities.
    • Added nine (9) new tests to test suite including a full test server helper function that uses Dispatch.
    • Added read(into data: inout Data) - This function reads all the data available on a socket and returns it in the Data object that was passed. This function has been added to the SocketReader protocol.
    • Added write(from data: Data) - This function writes the data contained within the Data object to the socket. This method has been added to the SocketWriter protocol.
    • Merged in support for non-blocking writes to TCP sockets per PR#15 submitted against the legacy-0.7 branch. Also available at tag 0.7.6 for use with the 7/25 toolchain.
    • See README.md for more information about the new API.
    • Added new property, remoteConnectionClosed, to enable differentiation between a socket that is no longer connected to its' remote partner and one that would block. If this property returns true, the remote connection has been closed and the socket should be closed.
    • APIs based on NSData and NSMutable data will be deprecated in a future release.
    • Removed verifyConnection() function from SSLServiceDelegate protocol. Now handled internally by SSLService itself.
    • Minor change to initialize delegate function of SSLServiceDelegate. SSLService.inititalize(isServer:) became SSLService.initialize(asServer:).
    • Updated example in README.md to use multi-threaded Dispatch based API.
    • Added continuous integration (PR#16) include build badge in README.md.
    • Allow use on iOS, tvOS and watchOS as well as macOS.
    • Added endianness check for host before byte swapping (PR#20).
    • Added fix for issue #22. When requesting to listen on port 0, the port assigned by the OS was not being returned in the Signature. Hence, the caller would not know what port was assigned and is being listened to. Added two additional unit tests to test this condition. Also, related to this, passing of a zero (0) for port when attempting to connect is invalid and will now be cause for an exception being thrown.
    • Added support for using UNIX Domain Sockets. See the README.md for more information.
    • Read and write function can now throw a SOCKET_ERR_CONNECTION_RESET exception in the event the connection was reset by the peer.
    • Added new computed property, isSecure, at the Socket level to resolve the optional signature property and returns true if the socket is secure and false otherwise.
    • Updated tests to account for serverHelper launch and take down.
    • Added UDP support. See the README.md for more information.
    • Fixed issue #46.
    • Fixed issue #959 from Kitura.
    • Fixed a crash bug revealed in BlueSSLService issue #10.
    • Fixed issue #49. File representing a UNIX socket should not be deleted when a client socket is closed. Only the listening socket should delete the file.
    • Fixed issue #50.
    • Added documentation (as a result of issue #53) that documents how to set the socket read buffer size.
    • Changed how certain flags were being reset during the close of a socket. Related to issue #53. Also removed old debug statement and redundant memory clearing calls.
    • Merged PR #54 to correct warnings under Swift 3.1.
    • Merged PR #55 to correct memory leaks related to getAddrInfo.
    • In response to issue #56, added two new functions that allow the setting of a read and/or write timeout. See the README.md for more information.
    • Merged PR #57 to add CocoaPod support.
    • Added usage information for CocoaPods.
    • Merged PR #60 which now allows port sharing between IPV6 and IPV4 sockets.
    • When the SSLServiceDelegate is set to a non-nil value, increase the read buffer size to accommodate the TLS packet size. Related to issue #22 in BlueSSLService.
    • Added code to validate the port values passed to connect(to:port:) function and ensure they fall within the proper range.
    • Merged PR #61: Set SO_REUSEPORT for port sharing on macOS.
    • Merged PR #62.
    • Corrected buffer overflow problem when doing certain TCP reads the use the truncate parameter. See issue #66.
    • Changed podpsec Swift version to 3.1.1.
    • Update podspec to include watchOS and tvOS. PR #70
    • Support of Xcode 9 Beta.
    • Support for ALPN in SSLServiceDelegate. PR #67
    • Merge PR #72 to fix problem reported by issue #68.
    • Fixed issue #81, If the attempt to set the SO_REUSEPORT socket option fails, check errno for ENOPROTOOPT and if set, silently ignore the error. This can happen when using WSL (Windows Subsystem for Linux).
    • Added new utility function, udpBroadcast, to allow enablement and disablement of broadcast mode for UDP sockets. This fixes issue #80.
    • Fixed bug in new utility function, udpBroadcast, that was causing the inverse of what it was supposed to do.
    • Added enhancement to connect API to allow for a connection timeout (issue #65). See the documentation in the README.md for how to use the new API.
    • Swift 4 Support.
    • Merged PR #85 to allow deferral of SSL accept. This fixes BlueSSLService issue #40. For more details and discussion refer to that issue.
    • Fixed bug related to PR #85.
    • Removed watchOS support. See issue #87 for more info.
    • Fixed problem on macOS when using connect API. See issue #88 for more info.
    • Update FD* functions to consistently used Int32 where appropriate.
    • Allow wait() function to be called on UDP sockets that are bound.
    • Add new parameter for listen() API that allows the caller to decide whether to reuse the listening port or not. Default behavior is to reuse the port. Resolves issue #94.
    • Removed unsafe access to Socket.Address, PR #93.
    • Corrected some outdated documentation in README.md, issue #96.
    • Added tvOS target to Xcode project, issue #100.
    • Minor project changes for tvOS.
    • Remove build on Xcode 8.3.
    • CI updates.
    • Clarify use of the isReadableOrWritable() function when attempting to write to a newly connected socket. Issue #105.
    • Cleanup and minor bug fix. PR #107.
    • Rolled back fd_set extension from PR #107 to fix crash bug. Added additional tests to ensure this kind of crash bug doesn't get through again.
    • Added back the now fixed fd_set extension. PR #111.
    • The connect(to:port:timeout:) API will now throw an exception if called on a non-blocking socket without the optional timeout being passed with a value greater than zero. Updated documentation to reflect this.
    • Changes to adapt to Swift 4.1. Encompasses PR #121 and other related changes.
    • Fixed a bit-addressing error in fd_set implementation. Make sure that the temporary socket opened in Socket.connect(to:port:timeout:) is closed in the event of an error being thrown. See PR #126 for more information. This fixes the following issues: #120, #123 and #125.
    Source code(tar.gz)
    Source code(zip)
  • 0.9.1(Aug 16, 2016)

    This release requires use of the swift-DEVELOPMENT-SNAPSHOT-2016-08-15-a toolchain.

    • Compatible with Xcode 8 Beta 6 using the above toolchain.
    • Added support for arm architecture for FD utilities.
    • Added nine (9) new tests to test suite including a full test server helper function that uses Dispatch.
    • IMPORTANT NOTE Testing requires a working Dispatch module in the toolchain. See the README.md for more information.
    • Added read(into data: inout Data) - This function reads all the data available on a socket and returns it in the Data object that was passed. This function has been added to the SocketReader protocol.
    • Added write(from data: Data) - This function writes the data contained within the Data object to the socket. This method has been added to the SocketWriter protocol.
    • Merged in support for non-blocking writes to TCP sockets per PR#15 submitted against the legacy-0.7 branch. Also available at tag 0.7.6 for use with the 7/25 toolchain.
    • See README.md for more information about the new API.
    • NSData and NSMutable data will be deprecated in a future release.
    • Removed verifyConnection() function from SSLServiceDelegate protocol. Now handled internally by SSLService itself.
    • Minor change to initialize delegate function of SSLServiceDelegate. SSLService.inititalize(isServer:) became SSLService.initialize(asServer:).
    • Updated example in README.md to use multi-threaded Dispatch based API.
    • Added instructions for building and installing Dispatch into the 8/15 Linux toolchain.
    Source code(tar.gz)
    Source code(zip)
  • 0.8.11(Aug 10, 2016)

    This release requires use of the swift-DEVELOPMENT-SNAPSHOT-2016-08-04-a toolchain or the new swift-DEVELOPMENT-SNAPSHOT-2016-08-07-a toolchain. The use of the 8/7 toolchain is recommended.

    • Added support for arm architecture for FD utilities.
    • Added nine (9) new tests to test suite including a full test server helper function that uses Dispatch.
    • IMPORTANT NOTE Testing requires a working Dispatch module in the toolchain. See the README.md for more information.
    • Added read(into data: inout Data) - This function reads all the data available on a socket and returns it in the Data object that was passed. This function has been added to the SocketReader protocol.
    • Added write(from data: Data) - This function writes the data contained within the Data object to the socket. This method has been added to the SocketWriter protocol.
    • Merged in support for non-blocking writes to TCP sockets per PR#15 submitted against the legacy-0.7 branch. Also available at tag 0.7.6 for use with the 7/25 toolchain.
    • NSData and NSMutable data will be deprecated in a future release.
    • Removed verifyConnection() function from SSLServiceDelegate protocol. Now handled internally by SSLService itself.
    • See README.md for more information about the new API.
    • Works with Xcode 8 Beta 4 using the above toolchain.
    • Updated example in README.md to use multi-threaded Dispatch based API.
    • Added instructions for building and installing Dispatch into the 8/4 or 8/7 Linux toolchain.
    Source code(tar.gz)
    Source code(zip)
  • 0.7.6(Jul 26, 2016)

    This release requires use of the new swift-DEVELOPMENT-SNAPSHOT-2016-07-25-a toolchain.

    • Added support for arm architecture for FD utilities.
    • Added beginnings of a test suite.
    • Added read(into data: inout Data) - This function reads all the data available on a socket and returns it in the Data object that was passed.
    • Added write(from data: Data) - This function writes the data contained within the Data object to the socket.
    • See README.md for more information about the new API.
    • Works with Xcode 8 Beta 4 Default Toolchain.
    Source code(tar.gz)
    Source code(zip)
  • 0.6.2(Jul 6, 2016)

    This release requires use of the new swift-DEVELOPMENT-SNAPSHOT-2016-06-20-a toolchain.

    • Changes in response to Issue #6. Socket.wait() now supports a timed wait based on a passed timer value, an immediate return (i.e. quick check) and an indefinite wait.
    • Changed SOCKET_DEFAULT_MAX_CONNECTIONS to SOCKET_DEFAULT_MAX_BACKLOG and changed the default from 5 to 50.
    • Added SOCKET_MAX_DARWIN_BACKLOG for macOS.
    • Changed the signature of listen(on port: Int, maxPendingConnections: Int) to listen(on port: Int, maxBacklogSize: Int = Socket.SOCKET_DEFAULT_MAX_BACKLOG) and removed the listen(on port: Int) API since the same can be accomplished using defaults.
    • Updated documentation in README.md to reflect changes.
    Source code(tar.gz)
    Source code(zip)
  • 0.5.20(Apr 13, 2016)

    • Important: This release requires use of the 5/03, 5/31 or 6/06 DEVELOPMENT release of the toolchain.
    • Replaced make*() API's with create() (various forms depending on what you're creating). To create a socket using default parameters, use create().
    • Changed Error from class to struct.
    • Improved error handling when determining protocol family of newly connected or listening sockets.
    • Wrappered socket fd functions into FD class and changed names to look more familiar with their 'C' counterparts. i.e. FD_SET in C becomes FD.SET in Swift.
    • Check for interrupt during accept call and re-issue call if interrupted. This allows setting of breakpoints while listening for a connection.
    • Enums have been lowerCamelCased in accordance with Swift 3.0 API guidelines.
    • Added new wait() API to monitor an array of sockets, returning when data is available or timeout occurs.
    • Added hooks for using SSLService plugin (when available).
    • Added boolean value to the Signature to indicate whether the Socket instance is secure or not.
    Source code(tar.gz)
    Source code(zip)
  • 0.3.5(Mar 24, 2016)

    • Important: This release requires use of the 3/16 DEVELOPMENT release of the toolchain.
    • While the project name, BlueSocket remains the same, the actual framework name is now just Socket. For importing in your programs, where you used to use:
    import BlueSocket
    

    you should now use:

     import Socket
    
    • In keeping with this, all references to BlueSocket have been changed to Socket including the reader and writer protocols.
    • Some of the public properties and a lot of the public functions within Socket and its structs/enums have been refactored and had their signatures changed. This was done in an effort to conform to Swift 3.0 API guidelines. The following table lists these changes:

    | Parent | Old Property/Function Signature | New Property/Function Signature | | --- | --- | --- | | SocketReader | readData(data: NSMutableData) throws -> Int | read(into data: NSMutableData) throws -> Int | | | | | | SocketWriter | writeData(data: NSData) throws | write(from data: NSData) throws | | SocketWriter | writeString(string: String) throws | write(from string: String) throws | | | | | | Socket.Address | Not available | var size: Int | | Socket.Address | func toAddr() -> sockaddr | var addr: sockaddr | | | | | | Socket.Signature | public var addrSize: Int | Removed now part of Socket.Address. | | | | | | Socket.Error | Conforms to ErrorType | Conforms to ErrorProtocol | | | | | | Socket | var connected: Bool | var isConnected: Bool | | Socket | var listening: Bool | var isListening: Bool | | Socket | var remoteHostName: String? | var remoteHostname: String | | Socket | var remotePort: Int | var remotePort: Int32 | | Socket | N/A | var isServer: Bool | | Socket | N/A | var listeningPort: Int32 | | Socket | class func defaultConfigured() throws -> BlueSocket | class func makeDefault() throws -> Socket | | Socket | class func customConfigured(family: ProtocolFamily, type: SocketType, proto: SocketProtocol) throws -> BlueSocket | class func makeConfigured(family family: ProtocolFamily, type: SocketType, proto: SocketProtocol) throws -> Socket | | Socket | class func createConnected(Signature signature: Signature) throws -> BlueSocket | class func makeConnected(using signature: Signature) throws -> Socket | | Socket | class func createUsing(NativeHandle socketfd: Int32, address: Address?) throws -> BlueSocket | class func makeFrom(nativeHandle nativeHandle: Int32, address: Address?) throws -> Socket | | Socket | class func ipAddressStringAndPort(fromAddress: Address) -> (hostname: String, port: Int)? | class func hostnameAndPort(from address: Address) -> (hostname: String, port: Int32)? | | Socket | class func checkStatus(sockets: [BlueSocket]) throws -> (readables: [BlueSocket], writables: [BlueSocket]) | class func checkStatus(for sockets: [Socket]) throws -> (readables: [Socket], writables: [Socket]) | | Socket | func acceptConnectionAndKeepListening() throws -> BlueSocket | func acceptClientConnection() throws -> Socket | | Socket | func connectTo(host: String, port: Int32) throws | func connect(to host: String, port: Int32) throws | | Socket | func connectUsing(Signature signature: Signature) throws | func connect(using signature: Signature) throws | | Socket | func listenOn(port: Int) throws | func listen(on port: Int) throws | | Socket | func listenOn(port: Int, maxPendingConnections: Int) throws | func listen(on port: Int, maxPendingConnections: Int) throws | | Socket | func readData(buffer: UnsafeMutablePointer, bufSize: Int) throws -> Int | func read(into buffer: UnsafeMutablePointer, bufSize: Int) throws -> Int | | Socket | func readData(data: NSMutableData) throws -> Int | func read(into data: NSMutableData) throws -> Int | | Socket | func writeData(buffer: UnsafePointer, bufSize: Int) throws | func write(from buffer: UnsafePointer, bufSize: Int) throws | | Socket | func writeData(data: NSData) throws | func write(from data: NSData) throws | | Socket | func writeString(string: String) throws | func write(from string: String) throws | | Socket | func setBlocking(shouldBlock: Bool) throws | func setBlocking(mode shouldBlock: Bool) throws |

    Source code(tar.gz)
    Source code(zip)
  • 0.2.3(Mar 17, 2016)

    Bug fixes:

    • Fixed a big bug on Linux. The use of sockaddr_storage for storage of both sockaddr_in and sockaddr_in6 structs does not work on Linux. It appears to be the way the struct is defined on Linux versus the way it's defined on OS X. The result was that the address and port number were being corrupted. This solves the problem by storing the addresses in an enum with associated values.
    • Replaced the inefficient toXXX() utility functions associated with sockaddr_storage, sockaddr_in and sockaddr_in6 with versions that do a simple cast rather than allocating new structures.
    • Fixed a problem with the port values. They were not be byte swapped when converting from network format.
    Source code(tar.gz)
    Source code(zip)
  • 0.2.1(Mar 15, 2016)

    Some major refactoring of the code internals that makes the API a bit more easier to use:

    • BlueSocket.BlueSocketSignature is now BlueSocket.Signature,
    • BlueSocketError has become BlueSocket.Error.
    • BlueSocket.BlueSocketProtocolFamily has become BlueSocket.ProtocolFamily.
    • BlueSocket.BlueSocketType has become BlueSocket.SocketType.
    • BlueSocket.BlueSocketProtocol has become BlueSocket.SocketProtocol.
    • Added domain property to BlueSocket.Error.

    Additionally, added code to allow listening sockets to avoid dying from a SIGPIPE signal for an interrupted connection.

    Source code(tar.gz)
    Source code(zip)
  • 0.1.4(Mar 6, 2016)

    What's changed in this release:

    • Updated to use the latest swift-DEVELOPMENT-SNAPSHOT-2016-03-01-a drop of the Swift toolchain. Use of this drop or higher is REQUIRED.
    • Changed library to be protocol independent. It now fully supports both IPV4 and IPV6 including listening on an IPV6 socket.
    • Removed use of gethostbyname() since it's obsolete and replaced it with the more modern getaddrinfo().
    • Added extensions for sockaddr, sockaddr_in, sockaddr_in6 and sockaddr_storage to facilitate conversions based on the protocol family.
    • Improved documentation adding missing where needed.
    • Replaced the BlueSocket.dottedIP(fromAddress:) class method with a new more robust BlueSocket.ipAddressStringAndPort(fromAddress:) that returns an optional tuple containing both the string representation of the hostname and the port based on the pass socket address info.
    • Added code to maintain signatures for all connected sockets. This can be accessed via the signature property.
    • Added new class function that allows creation of a connected socket using a BlueSocketSignature, BlueSocket.createConnected(Signature:). Accompanying that, added an instance function, connectUsing(Signature:), that allows connection to be achieved by providing a BlueSocketSignature object.
    • Added convenient method for creating a BlueSocketSignature to make it easier to use the new class function to create a connected socket all in one step.
    • Added new class function that allows creation of a BlueSocket instance using an existing raw socket fd and address.
    Source code(tar.gz)
    Source code(zip)
  • 0.0.5(Mar 1, 2016)

  • 0.0.4(Feb 16, 2016)

Owner
Kitura
Kitura - Server Side framework written in Swift
Kitura
This app is using web-socket for realtime updation of aqi for dedicated inidan cities.

CityWiseAQI This app is using web-socket for realtime updation of aqi for dedicated inidan cities. We're following MVVM architecture in this app. This

Vipul Kumar 2 Feb 7, 2022
Socket.io iOS and OSX Client compatible with v1.0 and later

SocketIO-Kit ⚠️ This project is no longer maintained. Please use the official framework Socket.IO-Client-Swift. SocketIO-Kit is a Socket.io iOS client

Ricardo Pereira 140 Mar 9, 2022
Asynchronous socket networking library for Mac and iOS

CocoaAsyncSocket CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for macOS, iOS, and tvOS. The classes are described

Robbie Hanson 12.3k Jan 8, 2023
🔌 Non-blocking TCP socket layer, with event-driven server and client.

Original authors Honza Dvorsky - http://honzadvorsky.com, @czechboy0 Matthias Kreileder - @matthiaskr1 At the request of the original authors, we ask

Vapor Community 574 Dec 7, 2022
Swift async/await based socket

Socket Swift async/await based socket library Introduction This library exposes an idiomatic Swift API for interacting with POSIX sockets via an async

null 89 Dec 29, 2022
MVVM project to show AQI of cities via web socket

Air Quality Monitoring Application Swift project with JSON parsing using codable About the application The app consists of live realtime data from the

Pran Kishore 0 Nov 27, 2021
This is my attempt to make this repo available on swift package manager

Parse LiveQuery Client for iOS/OSX PFQuery is one of the key concepts for Parse. It allows you to retrieve PFObjects by specifying some conditions, ma

Benji 0 Nov 3, 2021
Lightweight library for web server applications in Swift on macOS and Linux powered by coroutines.

Why Zewo? • Support • Community • Contributing Zewo Zewo is a lightweight library for web applications in Swift. What sets Zewo apart? Zewo is not a w

Zewo 1.9k Dec 22, 2022
Super lightweight async HTTP server library in pure Swift runs in iOS / MacOS / Linux

Embassy Super lightweight async HTTP server in pure Swift. Please read: Embedded web server for iOS UI testing. See also: Our lightweight web framewor

Envoy 540 Dec 15, 2022
A tool to build projects on MacOS and a remote linux server with one command

DualBuild DualBuild is a command line tool for building projects on MacOS and a remote Linux server. ##Setup Install the repository git clone https://

Operator Foundation 0 Dec 26, 2021
A Ruby on Rails inspired Web Framework for Swift that runs on Linux and OS X

IMPORTANT! We don't see any way how to make web development as great as Ruby on Rails or Django with a very static nature of current Swift. We hope th

Saulius Grigaitis 2k Dec 5, 2022
Swift backend / server framework (Pure Swift, Supports Linux)

NetworkObjects NetworkObjects is a #PureSwift backend. This framework compiles for OS X, iOS and Linux and serves as the foundation for building power

Alsey Coleman Miller 258 Oct 6, 2022
This package is meant to make http request of an easy way inspiren in the architecture of Moya package

NetworkAgent This package is meant to make http request of an easy way inspiren in the architecture of Moya package. This package is 100% free of depe

Angel Rada 19 Sep 8, 2022
Rayon - Yet another SSH machine manager for macOS

Rayon A server monitor tool for linux based machines using remote proc file syst

Lakr Aream 2.3k Jan 8, 2023
SwiftSoup: Pure Swift HTML Parser, with best of DOM, CSS, and jquery (Supports Linux, iOS, Mac, tvOS, watchOS)

SwiftSoup is a pure Swift library, cross-platform (macOS, iOS, tvOS, watchOS and Linux!), for working with real-world HTML. It provides a very conveni

Nabil Chatbi 3.7k Dec 28, 2022
SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN.

SwiftCANLib SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN. Th

Tim Wise 4 Oct 25, 2021
🌸 Powerful Codable API requests builder and manager for iOS.

This lib is about network requests with blackjack, roulette and craps! Using it you will be able to convert your massive API layer code into an awesom

CodyFire 251 Jan 8, 2023
SwiftyReachability is a simple and lightweight network interface manager written in Swift.

SwiftyReachability is a simple and lightweight network interface manager written in Swift. Freely inspired by https://github.com/tonymillion/Reachabil

Antonio Guerra 5 Nov 4, 2022
A modern download manager based on NSURLSession to deal with asynchronous downloading, management and persistence of multiple files.

TWRDownloadManager TWRDownloadManager A modern download manager for iOS (Objective C) based on NSURLSession to deal with asynchronous downloading, man

Michelangelo Chasseur 407 Nov 19, 2022