blob: 9b5a5731064d3249eb88dba5e87c70b1f93c9bb6 [file] [log] [blame]
// +build veyronbluetooth,!android
package bluetooth
import (
"fmt"
"net"
"syscall"
"time"
)
// conn represents one RFCOMM connection between two bluetooth devices.
// It implements the net.Conn interface.
type conn struct {
fd *fd
localAddr, remoteAddr net.Addr
readDeadline time.Time
writeDeadline time.Time
}
func newConn(sockfd int, local, remote net.Addr) (net.Conn, error) {
fd, err := newFD(sockfd)
if err != nil {
syscall.Close(sockfd)
return nil, err
}
return &conn{fd: fd, localAddr: local, remoteAddr: remote}, nil
}
func (c *conn) String() string {
return fmt.Sprintf("Bluetooth (%s) <--> (%s)", c.localAddr, c.remoteAddr)
}
// net.Conn interface methods
func (c *conn) Read(p []byte) (n int, err error) { return c.fd.Read(p) }
func (c *conn) Write(p []byte) (n int, err error) { return c.fd.Write(p) }
func (c *conn) Close() error { return c.fd.Close() }
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
func (c *conn) SetReadDeadline(t time.Time) error { return c.setSockoptTimeval(t, syscall.SO_RCVTIMEO) }
func (c *conn) SetWriteDeadline(t time.Time) error { return c.setSockoptTimeval(t, syscall.SO_SNDTIMEO) }
func (c *conn) SetDeadline(t time.Time) error {
if err := c.SetReadDeadline(t); err != nil {
return err
}
if err := c.SetWriteDeadline(t); err != nil {
return err
}
return nil
}
func (c *conn) setSockoptTimeval(t time.Time, opt int) error {
fd, err := c.fd.Reference()
if err != nil {
return err
}
defer c.fd.ReleaseReference()
if timeout := getTimeout(t); timeout != nil {
return syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, opt, timeout)
}
return nil
}
// getTimeout returns timeout for socket read/write operations, given the
// deadline specified as absolute time. Return value nil indicates no timeout.
// Return value 0 indicates that the read/write operation should timeout
// immediately.
func getTimeout(deadline time.Time) *syscall.Timeval {
if deadline.IsZero() {
return nil
}
d := deadline.Sub(time.Now())
if d < 0 {
ret := syscall.NsecToTimeval(0)
return &ret
}
ret := syscall.NsecToTimeval(d.Nanoseconds())
return &ret
}