How to cast sockaddr_in to sockaddr in swift - swift

I'm trying to do some network code in swift and the type checking is giving me fits.
var sock: CInt = ...
var rin: sockaddr_in
var rlen = socklen_t(sizeof(sockaddr_in))
var buffer: CChar[] = CChar[](count: 128, repeatedValue: 0)
let len = recvfrom(sock, &buffer, 128, 0, &rin, &rlen)
The compiler complains (very cryptically) at the recvfrom about the fact that &rin is a pointer to sockaddr_in instead of sockaddr. I tried various ways to convert the pointer type, but I can't seem to get this right.
If I declare it to be a sockaddr I can get this to compile, but then I can't look at it as a sockaddr_in.

Update for Swift 3 and later, compare UnsafeRawPointer Migration:
var sock: CInt = 1234
var rin = sockaddr_in()
var rlen = socklen_t(MemoryLayout.size(ofValue: rin))
var buffer = [CChar](repeating: 0, count: 128)
let len = withUnsafeMutablePointer(to: &rin) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
recvfrom(sock, &buffer, buffer.count, 0, $0, &rlen)
}
}
Update: As of Swift 1.2 (Xcode 6.3 beta), initializing a C struct
has become much simpler:
var rin = sockaddr_in()
defines a sockaddr_in variable and initializes all elements to zero.
The conversion of a address of sockaddr_in to an an address of
sockaddr is done as follows:
let len = withUnsafeMutablePointer(&rin) {
recvfrom(sock, &buffer, UInt(buffer.count), 0, UnsafeMutablePointer($0), &rlen)
}
Old answer: The first problem is that the sockaddr_in variable has to be initialized before
its address can be passed to recvfrom(). Initializing complex structs in Swift
seems to be clumsy, compare
Swift: Pass Uninitialized C Structure to Imported C function.
Using the helper function from
https://stackoverflow.com/a/24335355/1187415:
func initStruct<S>() -> S {
let struct_pointer = UnsafeMutablePointer<S>.alloc(1)
let struct_memory = struct_pointer.move()
struct_pointer.dealloc(1)
return struct_memory
}
the socket address can be initialized as
var rin : sockaddr_in = initStruct()
To cast the sockaddr_in pointer to a sockaddr pointer, use reinterpretCast().
let len = recvfrom(sock, &buffer, UInt(buffer.count), 0, reinterpretCast(&rin), &rlen)

Related

Access element given structure UnsafeMutablePointer

In C, I have the following code to allocate a AudioBufferList with the appropriate size and then populate it with relevant data.
AudioObjectPropertyScope scope = mIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
AudioObjectPropertyAddress address = { kAudioDevicePropertyStreamConfiguration, scope, 0 };
UInt32 propertySize;
__Verify_noErr(
AudioObjectGetPropertyDataSize(mID, &address, 0, NULL, &propertySize)
);
AudioBufferList *bufferList = (AudioBufferList *) malloc(propertySize);
__Verify_noErr(
AudioObjectGetPropertyData(mID, &address, 0, NULL, &propertySize, bufferList)
);
Then, I can access struct element :
UInt32 result { 0 };
for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
{
result += bufferList->mBuffers[i].mNumberChannels;
}
free(bufferList)
How can I replicate this behavior in Swift, given the fact that I use the same framework, i.e. AudioToolbox?
I have tried the following but I can't access the mNumberBuffers
let scope: AudioObjectPropertyScope = scope ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress(mSelector: kAudioDevicePropertyStreamConfiguration, mScope: scope, mElement: 0)
var size: UInt32 = 0
CheckError(
AudioObjectGetPropertyDataSize(mID, &address, 0, nil, &size),
"Couldn't get stream configuration data size."
)
var bufferList = UnsafeMutableRawPointer.allocate(bytes: Int(size), alignedTo: MemoryLayout<AudioBufferList>.alignment).assumingMemoryBound(to: AudioBufferList.self)
CheckError(
AudioObjectGetPropertyData(mID, &address, 0, nil, &size, bufferList),
"Couldn't get device's stream configuration"
)
You can create an AudioBufferList like this:
import AudioUnit
import AVFoundation
var myBufferList = AudioBufferList(
mNumberBuffers: 2,
mBuffers: AudioBuffer(
mNumberChannels: UInt32(2),
mDataByteSize: 2048,
mData: nil) )
When handed a bufferList with an unknown number of buffers, you can get the number of buffers and the sample data like this:
let myBufferListPtr = UnsafeMutableAudioBufferListPointer(myBufferList)
let numBuffers = myBufferListPtr.count
if (numBuffers > 0) {
let buffer : AudioBuffer = myBufferListPtr[0]
let bufferDataPointer = UnsafeMutableRawPointer(buffer.mData)
if let dataPtr = bufferDataPointer {
dataPtr.assumingMemoryBound(to: Float.self)[ i ] = x
...
The rest of my source code example is on GitHub: https://gist.github.com/hotpaw2/ba815fc23b5d642705f2b1dedfaf0107

Pointer and malloc in Swift

I am trying to convert this into swift.
Facing issue at memory allocation logic
Byte *p[10000];
p[allocatedMB] = malloc(1048576);
memset(p[allocatedMB], 0, 1048576);
How to write this in swift?
You can use malloc from Swift, it returns a "raw pointer":
var p: [UnsafeMutableRawPointer?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0
p[allocatedMB] = malloc(1048576)
memset(p[allocatedMB], 0, 1048576)
Alternatively, use UnsafeMutablePointer and its
allocate and initialize methods:
var p: [UnsafeMutablePointer<UInt8>?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0
p[allocatedMB] = UnsafeMutablePointer.allocate(capacity: 1048576)
p[allocatedMB]?.initialize(to: 0, count: 1048576)

Cast to different C struct unsafe pointer in Swift

I want to call the Posix socket functions socket and bind from Swift. socket is pretty easy—it takes Int32s, but bind is causing a problem, because I have a sockaddr_in pointer, but it wants a sockaddr pointer. In C, this would be a cast, like:
bind(sock, (struct sockaddr *)&sockAddress, sizeof(sockAddress))
Here's an attempt in Swift:
let sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
var sockAddress = sockaddr_in()
bind(sock, &sockAddress, UInt32(MemoryLayout<sockaddr_in>.size))
The bind line fails to compile with: cannot convert value of type 'sockaddr_in' to expected argument type 'sockaddr'
How do I cast the pointer?
You can write something like this:
withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
sockaddrInPtr.withMemoryRebound(to: sockaddr.self, capacity: 1) {sockaddrPtr in
bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
}
}
Or someone suggests this may be better:
withUnsafePointer(to: &sockAddress) {sockaddrInPtr in
let sockaddrPtr = UnsafeRawPointer(sockaddrInPtr).assumingMemoryBound(to: sockaddr.self)
bind(sock, sockaddrPtr, UInt32(MemoryLayout<sockaddr_in>.stride))
}
This article may be some help.
(UPDATE)
As described in the link shown by Martin R, now MemoryLayout<T>.stride and MemoryLayout<T>.size return the same value which is consistent with C's sizeof, where T is an imported C-struct. I'll keep my stride version of answer here, but that is not something "required" in this case now.
In Swift 3 you have to "rebind" the pointer
(compare SE-0107 UnsafeRawPointer API):
let sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
var sockAddress = sockaddr_in()
let result = withUnsafePointer(to: &sockAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
bind(sock, $0, socklen_t(MemoryLayout<sockaddr_in>.stride))
}
}
Remarks:
The type annotations in let sock: Int32 and var sockAddress: sockaddr_in are not needed.
The memset() is not necessary because sockaddr_in() initializes
all struct members to zero.
The Swift equivalent of the C sizeof is stride (which includes
a possible struct padding), not size (which does not include the
struct padding). (This "problem" does not exist anymore.
For structs imported from C, stride and size have the same value.)
Swift 5 obsolete the withUnsafeBytes(UnsafePointer<sockaddr>), so below is what I'm doing with Swift 5:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
return withUnsafeBytes { (p: UnsafeRawBufferPointer) -> String? in
let addr = p.baseAddress?.assumingMemoryBound(to: sockaddr.self)
guard getnameinfo(addr, socklen_t(self.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
return nil
}
return String(cString: hostname)
}

How to cast sockaddr_in to sockaddr in swift 2.0?

I saw the question here :
cast-sockaddr-in-to-sockaddr-in-swift 1.2
But when I try to use these code in swift 2.0, I got an error:
var sa = sockaddr_in()
let s = socket(PF_INET,SOCK_STREAM,0)
let cn = connect(s,UnsafeMutablePointer( &sa ), sizeof(sa) )
Ambiguous use of 'init'
How to fix this problem?
Similarly as in the referenced Q&A, you have to use withUnsafePointer()
var sa = sockaddr_in()
let s = socket(PF_INET,SOCK_STREAM,0)
let cn = withUnsafePointer(&sa) {
connect(s, UnsafePointer($0), socklen_t(sizeofValue(sa)))
}
Note also that sizeofValue() must be used with an instance of
a type, and that the value must be converted to socklen_t
as expected by connect().
Update for Swift 3:
let cn = withUnsafeMutablePointer(to: &sa) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
connect(s, $0, socklen_t(MemoryLayout.size(ofValue: sa)))
}
}

Basic tcp/ip server in swift

I've been trying to write a simple TCP/IP server in swift but I couldn't come up with a solution. I've already tried searching on both here and the rest of the web but I couldn't find something that works for the latest swift version which I am working with:
Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Operating system:
Mac OS X 10.10.5 Yosemitte
The following code has been made and it's based on this one: Socket Server Example with Swift
import Foundation
var sock_fd: Int32
var server_addr_size: Int
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
print("Failure: creating socket")
exit(EXIT_FAILURE)
}
server_addr_size = sizeof(sockaddr_in)
var server_addr = NSMutableData(length: server_addr_size)!
memset(UnsafeMutablePointer<Void>(server_addr.mutableBytes), 0, server_addr_size)
var addr = UnsafeMutablePointer<sockaddr_in>(server_addr.mutableBytes)
addr.memory.sin_len = __uint8_t(server_addr_size)
addr.memory.sin_family = sa_family_t(AF_INET) // chooses IPv4
addr.memory.sin_port = 12321 // chooses the port
let bind_server = bind(sock_fd, UnsafePointer<sockaddr>(server_addr.mutableBytes), socklen_t(server_addr_size))
if bind_server == -1 {
print("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
print("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = NSMutableData(length: server_addr_size)!
memset(UnsafeMutablePointer<Void>(client_addr.mutableBytes), 0, server_addr_size)
let client_fd = accept(sock_fd, UnsafeMutablePointer<sockaddr>(client_addr.mutableBytes), UnsafeMutablePointer<socklen_t>(bitPattern: server_addr_size))
if client_fd == -1 {
print("Failure: accepting connection")
exit(EXIT_FAILURE);
}
The call to accept fails as it can be seen on the output given by the mentioned code:
Failure: accepting connection
Program ended with exit code: 1
In addition to the assistance on fixing the code, I would also like to know how I could read and write to/from the connection.
Thanks,
G Oliveira
In
UnsafeMutablePointer<socklen_t>(bitPattern: server_addr_size)
you are re-interpreting an integer variable as a pointer. That makes no
sense and crashes at runtime because the contents of the variable does
not point to valid memory. The accept() function expects the address
of a variable of type socklen_t here.
There are other problems as well, e.g. the port number in the socket address must be in big-endian byte order:
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
otherwise your program listens on port 8496 instead of 12321.
Using NSMutableData is not really necessary, Since Swift 1.2 you can
create a sockaddr_in structure with all elements set to zero
simply with:
var server_addr = sockaddr_in()
and then withUnsafePointer() can be used to get an address to the structure.
If a system call fails, the global variable errno is set to a non-zero value indicating the cause of the error. perror() can be used to print the error message corresponding to errno.
You may want to set the SO_REUSEADDR socket option to avoid
an "Address is already in use" error when binding the socket, see
Uses of SO_REUSEADDR? or
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems? for more information.
Here is a cleaned-up version of your code which works as expected
in my test:
let sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var sock_opt_on = Int32(1)
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(sizeofValue(sock_opt_on)))
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(sizeofValue(server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
let bind_server = withUnsafePointer(&server_addr) {
bind(sock_fd, UnsafePointer($0), server_addr_size)
}
if bind_server == -1 {
perror("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
perror("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = sockaddr_storage()
var client_addr_len = socklen_t(sizeofValue(client_addr))
let client_fd = withUnsafeMutablePointer(&client_addr) {
accept(sock_fd, UnsafeMutablePointer($0), &client_addr_len)
}
if client_fd == -1 {
perror("Failure: accepting connection")
exit(EXIT_FAILURE);
}
print("connection accepted")
The read() and write() system calls are then used to read from
and write to the accepted socket.
Just a little update for Swift 4.
import Foundation
let sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var sock_opt_on = Int32(1)
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(MemoryLayout.size(ofValue: sock_opt_on)))
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(MemoryLayout.size(ofValue: server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(12321).bigEndian // chooses the port
let bind_server = withUnsafePointer(to: &server_addr) {
bind(sock_fd, UnsafeRawPointer($0).assumingMemoryBound(to: sockaddr.self), server_addr_size)
}
if bind_server == -1 {
perror("Failure: binding port")
exit(EXIT_FAILURE)
}
if listen(sock_fd, 5) == -1 {
perror("Failure: listening")
exit(EXIT_FAILURE)
}
var client_addr = sockaddr_storage()
var client_addr_len = socklen_t(MemoryLayout.size(ofValue: client_addr))
let client_fd = withUnsafeMutablePointer(to: &client_addr) {
accept(sock_fd, UnsafeMutableRawPointer($0).assumingMemoryBound(to: sockaddr.self), &client_addr_len)
}
if client_fd == -1 {
perror("Failure: accepting connection")
exit(EXIT_FAILURE);
}
To those who came to this topic looking for some help on the same subject, in addition to Martin's answer, I present, below, a small example on how I read and wrote to/from the socket:
// reading one char at a time
var buff_rcvd = CChar()
read(client_fd, &buff_rcvd, 1)
print(NSString(format:"Received: *%c*",buff_rcvd))
// writing one chat at a time
var buff_send: CChar = 65 // character "A" defined as CChar
write(client_fd, &buff_send, 1)
print(NSString(format:"Sent: *%c*",buff_send))
and we must not forget to close the connection after the code is done:
close(sock_fd)
close(client_fd)
EDIT: With FileDescriptors, we can do it even simpler!
let fileHandle = FileHandle(fileDescriptor: client_fd)
let data = fileHandle.readDataToEndOfFile()
print(String(data: data, encoding: .utf8))