(pkt []byte, len int, from, to bindtest.ChannelEndpoint2, i *InMemoryNetwork)
| 58 | } |
| 59 | |
| 60 | func (v *VirtualLink) simulate(pkt []byte, len int, from, to bindtest.ChannelEndpoint2, i *InMemoryNetwork) { |
| 61 | //fmt.Printf("begin send: %s -> %s\n", from.DstToString(), to.DstToString()) |
| 62 | if rand.Float64() < v.PacketLoss { |
| 63 | // drop |
| 64 | //fmt.Printf("dropped send: %s -> %s\n", from.DstToString(), to.DstToString()) |
| 65 | return |
| 66 | } |
| 67 | |
| 68 | toIdx := i.cfg.IndexOf(i.cfg.Endpoints[to.DstToString()]) |
| 69 | if v.Latency != 0 { |
| 70 | simJitter := rand.Float64() * float64(v.Jitter.Nanoseconds()) |
| 71 | simLat := v.Latency + time.Duration(simJitter) |
| 72 | go func() { // this is quite costly, but should be fine as long as we don't send packets too fast |
| 73 | select { |
| 74 | case <-i.cfg.Context.Done(): |
| 75 | return |
| 76 | case <-time.After(simLat): |
| 77 | //fmt.Printf("delay sent: %s -> %s\n", from.DstToString(), to.DstToString()) |
| 78 | err := i.binds[toIdx].Send([][]byte{pkt[:len]}, from) |
| 79 | if err != nil && !errors.Is(err, net.ErrClosed) { |
| 80 | panic(err) |
| 81 | } |
| 82 | } |
| 83 | }() |
| 84 | } else { |
| 85 | //fmt.Printf("sent: %s -> %s\n", from.DstToString(), to.DstToString()) |
| 86 | err := i.binds[toIdx].Send([][]byte{pkt[:len]}, from) |
| 87 | if err != nil && !errors.Is(err, net.ErrClosed) { |
| 88 | panic(err) |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | func (v *VirtualLink) WithLatency(lat, jitter time.Duration) *VirtualLink { |
| 94 | v.Latency = lat |
no test coverage detected