0

I'm trying to implement a simple TCP socket server in Swift. This code should be fairly similar to a C implementation but with extra Swift-isms.

I'm trying to connect using curl http://localhost:8080 which should at least trigger an "accept" even if there is no HTTP logic in the server. The response from curl is Connection refused

Here is the code I am using. It outputs 2 "Listening on descriptor" lines, but no "Accepting…" lines

import LibC
import Dispatch

let port = 8080
let listenBacklogLen = 16

// Setup Sockets
let socketDescriptor = (
    ipv4: socket(PF_INET,  SOCK_STREAM, IPPROTO_TCP),
    ipv6: socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)
)
let descriptors = [socketDescriptor.ipv4, socketDescriptor.ipv6]

var address = (
    ipv4: sockaddr_in(),
    ipv6: sockaddr_in6()
)

address.ipv4.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
address.ipv4.sin_family = sa_family_t(AF_INET)
address.ipv4.sin_port = in_port_t(port)
address.ipv4.sin_addr.s_addr = INADDR_ANY

address.ipv6.sin6_len = UInt8(MemoryLayout<sockaddr_in>.size)
address.ipv6.sin6_family = sa_family_t(AF_INET6)
address.ipv6.sin6_port = in_port_t(port)
address.ipv6.sin6_addr = in6addr_any

var reuseAddress: Int = 1
let reuseAddressLen = socklen_t(MemoryLayout.size(ofValue: reuseAddress))
withUnsafePointer(to: &reuseAddress) { ref in
    for descriptor in descriptors {
        assert(setsockopt(descriptor, SOL_SOCKET, SO_REUSEADDR, ref, reuseAddressLen) == 0)
    }
}

withUnsafePointer(to: &address.ipv4) { ref in
    ref.withMemoryRebound(to: sockaddr.self, capacity: 1) { reboundRef in
        assert(bind(socketDescriptor.ipv4, reboundRef, socklen_t(MemoryLayout.size(ofValue: ref.pointee))) == 0)
    }
}
withUnsafePointer(to: &address.ipv6) { ref in
    ref.withMemoryRebound(to: sockaddr.self, capacity: 1) { reboundRef in
        assert(bind(socketDescriptor.ipv6, reboundRef, socklen_t(MemoryLayout.size(ofValue: ref.pointee))) == 0)
    }
}

var acceptSources: [DispatchSourceRead] = []
var requestSources: [DispatchSourceRead] = []
for descriptor in descriptors {
    assert(listen(descriptor, Int32(listenBacklogLen)) == 0);

    let source = DispatchSource.makeReadSource(fileDescriptor: descriptor, queue: .global(qos: .userInitiated))
    source.setEventHandler {
        print("Accepting…")
        var address = sockaddr()
        var addressLen: socklen_t = socklen_t(MemoryLayout.size(ofValue: address))
        let requestSocketDescriptor = accept(descriptor, &address, &addressLen)
        assert(requestSocketDescriptor >= 0)

        let source = DispatchSource.makeReadSource(fileDescriptor: requestSocketDescriptor, queue: .global(qos: .userInitiated))
        source.setEventHandler { [unowned source] in
            var char: CChar = 0
            let bytesRead = read(requestSocketDescriptor, &char, 1)
            switch bytesRead {
            case -1:
                if ![EAGAIN, EINTR].contains(errno) {
                    print("Read returned error (\(errno)): \(strerror(errno))")
                    fallthrough
                }
            case 0:
                print("Done")
                source.cancel()
            default:
                print("C: \(char)")
            }
        }
        requestSources.append(source)
        source.resume()
    }
    acceptSources.append(source)

    print("Listening on descriptor: \(descriptor)")
    source.resume()
}

dispatchMain()

BTW, LibC is a simple module which unifies glibc and Darwin:

#if os(Linux)
    @_exported import Glibc
#else
    @_exported import Darwin.C
#endif

1 Answer 1

0

Aha! The port must be big-endian: address.ipv4.sin_port = in_port_t(port).bigEndian address.ipv6.sin_port = in_port_t(port).bigEndian

Figured this out with help from: Socket Server Example with Swift

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.