remote-mic/connection/listen.go

67 lines
1.5 KiB
Go

package connection
import (
"net"
)
// NewListen starts listening for a single connection on the given address.
// This method blocks until this is done.
func NewListen(address string) (*Connection, error) {
conn, err := listenAndAcceptTCP(address)
if err != nil {
return nil, err
}
return &Connection{
conn: conn,
BufSize: defaultBufSize,
stopFlag: false,
}, nil
}
func listenAndAcceptTCP(address string) (*net.TCPConn, error) {
addr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return nil, err
}
sock, err := net.ListenTCP("tcp", addr)
if err != nil {
return nil, err
}
conn, err := sock.AcceptTCP()
if err != nil {
return nil, err
}
conn.SetNoDelay(true)
return conn, nil
}
// RecvChan returns a read-only channel of byte slices and starts
// receiving and pushing data into it asynchronously.
// The channel is closed when the sender closes the connection.
// Use this to read bytes from the network connection.
// The data read is owned by the reader, it is thread-safe to modify.
func (c *Connection) RecvChan() <-chan []byte {
c.dataChan = make(chan []byte)
go c.recvLoop()
return c.dataChan
}
func (c *Connection) recvLoop() {
buf := make([]byte, c.BufSize)
for !c.stopFlag {
n, err := c.conn.Read(buf)
if err != nil {
c.stopFlag = true
}
if n > 0 {
// the underlying memory of the buffer
// must be copied for thread safety
sendBuf := make([]byte, n)
copy(sendBuf, buf)
c.dataChan <- sendBuf
}
}
close(c.dataChan)
}