github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/kcp-go/readloop_linux.go (about) 1 // +build linux 2 3 package kcp 4 5 import ( 6 "net" 7 "os" 8 "sync/atomic" 9 10 "github.com/pkg/errors" 11 "golang.org/x/net/ipv4" 12 "golang.org/x/net/ipv6" 13 ) 14 15 // the read loop for a client session 16 func (s *UDPSession) readLoop() { 17 // default version 18 if s.xconn == nil { 19 s.defaultReadLoop() 20 return 21 } 22 23 // x/net version 24 var src string 25 msgs := make([]ipv4.Message, batchSize) 26 for k := range msgs { 27 msgs[k].Buffers = [][]byte{make([]byte, mtuLimit)} 28 } 29 30 for { 31 if count, err := s.xconn.ReadBatch(msgs, 0); err == nil { 32 for i := 0; i < count; i++ { 33 msg := &msgs[i] 34 // make sure the packet is from the same source 35 if src == "" { // set source address if nil 36 src = msg.Addr.String() 37 } else if msg.Addr.String() != src { 38 atomic.AddUint64(&DefaultSnmp.InErrs, 1) 39 continue 40 } 41 42 if msg.N < s.headerSize()+IKCP_OVERHEAD { 43 atomic.AddUint64(&DefaultSnmp.InErrs, 1) 44 continue 45 } 46 47 // source and size has validated 48 s.packetInput(msg.Buffers[0][:msg.N]) 49 } 50 } else { 51 // compatibility issue: 52 // for linux kernel<=2.6.32, support for sendmmsg is not available 53 // an error of type os.SyscallError will be returned 54 if operr, ok := err.(*net.OpError); ok { 55 if se, ok := operr.Err.(*os.SyscallError); ok { 56 if se.Syscall == "recvmmsg" { 57 s.defaultReadLoop() 58 return 59 } 60 } 61 } 62 s.notifyReadError(errors.WithStack(err)) 63 return 64 } 65 } 66 } 67 68 // monitor incoming data for all connections of server 69 func (l *Listener) monitor() { 70 var xconn batchConn 71 if _, ok := l.conn.(*net.UDPConn); ok { 72 addr, err := net.ResolveUDPAddr("udp", l.conn.LocalAddr().String()) 73 if err == nil { 74 if addr.IP.To4() != nil { 75 xconn = ipv4.NewPacketConn(l.conn) 76 } else { 77 xconn = ipv6.NewPacketConn(l.conn) 78 } 79 } 80 } 81 82 // default version 83 if xconn == nil { 84 l.defaultMonitor() 85 return 86 } 87 88 // x/net version 89 msgs := make([]ipv4.Message, batchSize) 90 for k := range msgs { 91 msgs[k].Buffers = [][]byte{make([]byte, mtuLimit)} 92 } 93 94 for { 95 if count, err := xconn.ReadBatch(msgs, 0); err == nil { 96 for i := 0; i < count; i++ { 97 msg := &msgs[i] 98 if msg.N >= l.headerSize+IKCP_OVERHEAD { 99 l.packetInput(msg.Buffers[0][:msg.N], msg.Addr) 100 } else { 101 atomic.AddUint64(&DefaultSnmp.InErrs, 1) 102 } 103 } 104 } else { 105 // compatibility issue: 106 // for linux kernel<=2.6.32, support for sendmmsg is not available 107 // an error of type os.SyscallError will be returned 108 if operr, ok := err.(*net.OpError); ok { 109 if se, ok := operr.Err.(*os.SyscallError); ok { 110 if se.Syscall == "recvmmsg" { 111 l.defaultMonitor() 112 return 113 } 114 } 115 } 116 l.notifyReadError(errors.WithStack(err)) 117 return 118 } 119 } 120 }