blob: a375a8f51a76c3e684a89cfc4beedd1dfff4b08c [file] [log] [blame]
// +build linux,!android
package bluetooth
import (
"fmt"
"net"
"unsafe"
)
// // Explicitly link libbluetooth and other libraries as "go build" cannot
// // figure out these dependencies..
// #cgo LDFLAGS: -lbluetooth
// #include <stdlib.h>
// #include <unistd.h>
// #include "bt.h"
import "C"
// listener waits for incoming RFCOMM connections on the provided socket.
// It implements the net.Listener interface.
type listener struct {
fd *fd
acceptChan chan (acceptResult)
localAddr net.Addr
}
type acceptResult struct {
conn net.Conn
err error
}
func newListener(sockfd int, addr net.Addr) (net.Listener, error) {
fd, err := newFD(sockfd)
if err != nil {
return nil, err
}
return &listener{fd: fd, acceptChan: make(chan acceptResult), localAddr: addr}, nil
}
// Implements the net.Listener interface.
func (l *listener) Accept() (net.Conn, error) {
go l.fd.RunWhenReadable(l.accept)
r := <-l.acceptChan
return r.conn, r.err
}
func (l *listener) accept(sockfd int) {
var fd C.int
var remoteMAC *C.char
var result acceptResult
defer func() { l.acceptChan <- result }()
if es := C.bt_accept(C.int(sockfd), &fd, &remoteMAC); es != nil {
defer C.free(unsafe.Pointer(es))
result.err = fmt.Errorf("error accepting connection on %s, socket: %d, error: %s", l.localAddr, sockfd, C.GoString(es))
return
}
defer C.free(unsafe.Pointer(remoteMAC))
// Parse remote address.
var remote addr
var err error
if remote.mac, err = net.ParseMAC(C.GoString(remoteMAC)); err != nil {
result.err = fmt.Errorf("invalid remote MAC address: %s, err: %s", C.GoString(remoteMAC), err)
return
}
// There's no way to get accurate remote channel number, so use 0.
remote.channel = 0
result.conn, result.err = newConn(int(fd), l.localAddr, &remote)
}
// Implements the net.Listener interface.
func (l *listener) Close() error {
return l.fd.Close()
}
// Implements the net.Listener interface.
func (l *listener) Addr() net.Addr {
return l.localAddr
}