| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- package mmsg
- import (
- "net"
- "github.com/anacrolix/missinggo/expect"
- "github.com/anacrolix/mmsg/socket"
- )
- // Considered MSG_DONTWAIT, but I think Go puts the socket into non-blocking
- // mode in its runtime and it seems to do the right thing.
- const flags = 0
- type Conn struct {
- err error
- s *socket.Conn
- pr PacketReader
- }
- type PacketReader interface {
- ReadFrom([]byte) (int, net.Addr, error)
- }
- func NewConn(pr PacketReader) *Conn {
- ret := Conn{
- pr: pr,
- }
- ret.s, ret.err = socket.NewConn(pr)
- return &ret
- }
- func (me *Conn) recvMsgAsMsgs(ms []Message) (int, error) {
- err := me.RecvMsg(&ms[0])
- if err != nil {
- return 0, err
- }
- return 1, err
- }
- func (me *Conn) RecvMsgs(ms []Message) (n int, err error) {
- if me.err != nil || len(ms) == 1 {
- return me.recvMsgAsMsgs(ms)
- }
- sms := make([]socket.Message, len(ms))
- for i := range ms {
- sms[i].Buffers = ms[i].Buffers
- }
- n, err = me.s.RecvMsgs(sms, flags)
- if err != nil && err.Error() == "not implemented" {
- expect.Nil(me.err)
- me.err = err
- if n <= 0 {
- return me.recvMsgAsMsgs(ms)
- }
- err = nil
- }
- for i := 0; i < n; i++ {
- ms[i].Addr = sms[i].Addr
- ms[i].N = sms[i].N
- }
- return n, err
- }
- func (me *Conn) RecvMsg(m *Message) error {
- if len(m.Buffers) == 1 { // What about 0?
- var err error
- m.N, m.Addr, err = me.pr.ReadFrom(m.Buffers[0])
- return err
- }
- sm := socket.Message{
- Buffers: m.Buffers,
- }
- err := me.s.RecvMsg(&sm, flags)
- m.Addr = sm.Addr
- m.N = sm.N
- return err
- }
- type Message struct {
- Buffers [][]byte
- N int
- Addr net.Addr
- }
- func (me *Message) Payload() (p []byte) {
- n := me.N
- for _, b := range me.Buffers {
- if len(b) >= n {
- p = append(p, b[:n]...)
- return
- }
- p = append(p, b...)
- n -= len(b)
- }
- panic(n)
- }
- func (me *Conn) Err() error {
- return me.err
- }
|