Files
modbus/udp.go
2025-11-07 13:53:18 +08:00

103 lines
2.3 KiB
Go

package modbus
import (
"net"
"time"
)
// udpSockWrapper wraps a net.UDPConn (UDP socket) to
// allow transports to consume data off the network socket on
// a byte per byte basis rather than datagram by datagram.
type udpSockWrapper struct {
leftoverCount int
rxbuf []byte
sock *net.UDPConn
}
func newUDPSockWrapper(sock net.Conn) (usw *udpSockWrapper) {
usw = &udpSockWrapper{
rxbuf: make([]byte, maxTCPFrameLength),
sock: sock.(*net.UDPConn),
}
return
}
func (usw *udpSockWrapper) Read(buf []byte) (rlen int, err error) {
var copied int
if usw.leftoverCount > 0 {
// if we're holding onto any bytes from a previous datagram,
// use them to satisfy the read (potentially partially)
copied = copy(buf, usw.rxbuf[0:usw.leftoverCount])
if usw.leftoverCount > copied {
// move any leftover bytes to the beginning of the buffer
copy(usw.rxbuf, usw.rxbuf[copied:usw.leftoverCount])
}
// make a note of how many leftover bytes we have in the buffer
usw.leftoverCount -= copied
} else {
// read up to maxTCPFrameLength bytes from the socket
rlen, err = usw.sock.Read(usw.rxbuf)
if err != nil {
return
}
// copy as many bytes as possible to satisfy the read
copied = copy(buf, usw.rxbuf[0:rlen])
if rlen > copied {
// move any leftover bytes to the beginning of the buffer
copy(usw.rxbuf, usw.rxbuf[copied:rlen])
}
// make a note of how many leftover bytes we have in the buffer
usw.leftoverCount = rlen - copied
}
rlen = copied
return
}
func (usw *udpSockWrapper) Close() (err error) {
err = usw.sock.Close()
return
}
func (usw *udpSockWrapper) Write(buf []byte) (wlen int, err error) {
wlen, err = usw.sock.Write(buf)
return
}
func (usw *udpSockWrapper) SetDeadline(deadline time.Time) (err error) {
err = usw.sock.SetDeadline(deadline)
return
}
func (usw *udpSockWrapper) SetReadDeadline(deadline time.Time) (err error) {
err = usw.sock.SetReadDeadline(deadline)
return
}
func (usw *udpSockWrapper) SetWriteDeadline(deadline time.Time) (err error) {
err = usw.sock.SetWriteDeadline(deadline)
return
}
func (usw *udpSockWrapper) LocalAddr() (addr net.Addr) {
addr = usw.sock.LocalAddr()
return
}
func (usw *udpSockWrapper) RemoteAddr() (addr net.Addr) {
addr = usw.sock.RemoteAddr()
return
}