(buffers [][]byte, eps []conn.Endpoint)
| 119 | } |
| 120 | |
| 121 | func (peer *Peer) SendBuffers(buffers [][]byte, eps []conn.Endpoint) error { |
| 122 | peer.device.net.RLock() |
| 123 | defer peer.device.net.RUnlock() |
| 124 | |
| 125 | if peer.device.isClosed() { |
| 126 | return nil |
| 127 | } |
| 128 | |
| 129 | peer.endpoints.Lock() |
| 130 | endpoints := peer.endpoints.val |
| 131 | if len(endpoints) == 0 { |
| 132 | peer.endpoints.Unlock() |
| 133 | return errors.New("no known endpoints for peer") |
| 134 | } |
| 135 | if peer.endpoints.clearSrcOnTx { |
| 136 | for _, ep := range endpoints { |
| 137 | ep.ClearSrc() |
| 138 | } |
| 139 | for _, ep := range eps { |
| 140 | if ep != nil { |
| 141 | ep.ClearSrc() |
| 142 | } |
| 143 | } |
| 144 | peer.endpoints.clearSrcOnTx = false |
| 145 | } |
| 146 | peer.endpoints.Unlock() |
| 147 | |
| 148 | // optimization, if multiple contiguous buffers share the same endpoint, send them in a single batch |
| 149 | prevIdx := 0 |
| 150 | prevEp := eps[0] |
| 151 | |
| 152 | var anyError error |
| 153 | for i := 0; i <= len(buffers); i++ { |
| 154 | if i == len(buffers) || eps[i] != prevEp { |
| 155 | // send batch from prevIdx to i-1 |
| 156 | if prevEp == nil { |
| 157 | prevEp = endpoints[0] // default endpoint |
| 158 | } |
| 159 | err := peer.device.net.bind.Send(buffers[prevIdx:i], prevEp) |
| 160 | if err != nil { |
| 161 | anyError = err |
| 162 | } |
| 163 | prevIdx = i |
| 164 | if i < len(buffers) { |
| 165 | prevEp = eps[i] |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | var totalLen uint64 |
| 171 | for _, b := range buffers { |
| 172 | totalLen += uint64(len(b)) |
| 173 | } |
| 174 | perf.SentPacketPerSecond.Add(float64(len(buffers))) |
| 175 | perf.SentBytesPerSecond.Add(float64(totalLen)) |
| 176 | peer.txBytes.Add(totalLen) |
| 177 | return anyError |
| 178 | } |
no test coverage detected