Skip to content

Commit

Permalink
Merge branch 'nonblockRead'
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Sep 12, 2018
2 parents b63ac95 + 981076d commit 881c319
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 10 deletions.
65 changes: 55 additions & 10 deletions Sources/BluetoothLinux/L2CAP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import Foundation
import Bluetooth
import CSwiftBluetoothLinux

/// L2CAP Bluetooth socket
public final class L2CAPSocket: L2CAPSocketProtocol {
Expand Down Expand Up @@ -133,7 +134,9 @@ public final class L2CAPSocket: L2CAPSocketProtocol {
addressType: AddressType?) throws -> (CInt, sockaddr_l2) {

// open socket
let internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BluetoothProtocol.l2cap.rawValue)
let internalSocket = socket(AF_BLUETOOTH,
SOCK_SEQPACKET,
BluetoothProtocol.l2cap.rawValue)

// error creating socket
guard internalSocket >= 0
Expand Down Expand Up @@ -226,9 +229,14 @@ public final class L2CAPSocket: L2CAPSocketProtocol {
// error accepting new connection
guard client >= 0 else { throw POSIXError.fromErrno! }

return L2CAPSocket(clientSocket: client,
remoteAddress: remoteAddress,
securityLevel: securityLevel)
let newSocket = L2CAPSocket(clientSocket: client,
remoteAddress: remoteAddress,
securityLevel: securityLevel)

// make socket non-blocking
try newSocket.setNonblocking()

return newSocket
}

/// Connect to another L2CAP server.
Expand All @@ -249,11 +257,19 @@ public final class L2CAPSocket: L2CAPSocketProtocol {
connect(internalSocket, $0, socklen_t(MemoryLayout<sockaddr_l2>.size)) == 0
})
}) else { throw POSIXError.fromErrno! }

// make socket non-blocking
try setNonblocking()
}

/// Reads from the socket.
public func recieve(_ bufferSize: Int = 1024) throws -> Data {

public func recieve(_ bufferSize: Int = 1024) throws -> Data? {

// check if reading buffer has data.
guard try canRead()
else { return nil }

// read socket
var buffer = [UInt8](repeating: 0, count: bufferSize)

let actualByteCount = read(internalSocket, &buffer, bufferSize)
Expand All @@ -264,7 +280,36 @@ public final class L2CAPSocket: L2CAPSocketProtocol {

return Data(bytes: actualBytes)
}


private func canRead() throws -> Bool {

var readSockets = FileDescriptorSet()
readSockets.zero()
readSockets.add(internalSocket)

var time = timeval()

let fdCount = select(internalSocket + 1, &readSockets, nil, nil, &time)

guard fdCount != -1
else { throw POSIXError.fromErrno! }

return fdCount > 0
}

private func setNonblocking() throws {

var flags = fcntl(internalSocket, F_GETFL, 0)

guard flags != -1
else { throw POSIXError.fromErrno! }

flags = fcntl(internalSocket, F_SETFL, flags | O_NONBLOCK);

guard flags != -1
else { throw POSIXError.fromErrno! }
}

/// Write to the socket.
public func send(_ data: Data) throws {

Expand Down Expand Up @@ -389,8 +434,8 @@ struct bt_security {

#if os(Linux)

public let SOCK_SEQPACKET: CInt = 5
let SOCK_SEQPACKET: CInt = CInt(Glibc.SOCK_SEQPACKET.rawValue)

#endif

// MARK: - OS X support
Expand All @@ -400,5 +445,5 @@ struct bt_security {
let SO_PROTOCOL: CInt = 38

let SO_DOMAIN: CInt = 39

#endif
52 changes: 52 additions & 0 deletions Sources/CSwiftBluetoothLinux/include/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
*/

#include <stdint.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/select.h>

/**
@brief Manipulates the underlying device parameters of special files.
Expand All @@ -32,3 +35,52 @@ __attribute__((swift_name("HCISetBit(_:_:)")))
{
*((uint32_t *) destination + (bit >> 5)) |= (1 << (bit & 31));
}

/**
A set of file descriptors.
*/
typedef fd_set FileDescriptorSet __attribute__((swift_name("FileDescriptorSet")));

/**
Initializes a file descriptor set on the stack.
*/
static inline FileDescriptorSet* swift_bluetooth_fd_set_zero(FileDescriptorSet* set)
__attribute__((swift_name("FileDescriptorSet.zero(self:)")))
{
FD_ZERO(set);
return set;
}

/**
Add a given file descriptor to a set.
@param fd The file descriptor to add to the set.
@param set The file descriptor set.
*/
static inline void swift_bluetooth_fd_set_add(FileDescriptorSet* set, int fileDescriptor)
__attribute__((swift_name("FileDescriptorSet.add(self:_:)")))
{
FD_SET(fileDescriptor, set);
}

/**
Removed a given file descriptor from a set.
@param fd The file descriptor to add to the set.
@param set The file descriptor set.
*/
static inline void swift_bluetooth_fd_set_remove(FileDescriptorSet* set, int fileDescriptor)
__attribute__((swift_name("FileDescriptorSet.remove(self:_:)")))
{
FD_CLR(fileDescriptor, set);
}

/**
Checks if a file descriptor is part of the set.
@param fd The file descriptor to to check for membership.
@param set The targeted value.
*/
static inline bool swift_bluetooth_fd_set_contains(FileDescriptorSet* set, int fileDescriptor)
__attribute__((swift_name("FileDescriptorSet.contains(self:_:)")))
{
return FD_ISSET(fileDescriptor, set);
}

0 comments on commit 881c319

Please sign in to comment.