recvLoop reads WinDivert packets and forwards them on b.packets. The caller's Verdict decides whether the packet is reinjected (Accept), dropped (Drop), or reinjected-modified (AcceptModified — caller must have handed us the mutated bytes elsewhere; today the engine uses Inject() instead, so we just
(ctx context.Context)
| 103 | // handed us the mutated bytes elsewhere; today the engine uses Inject() |
| 104 | // instead, so we just treat all non-Drop verdicts as Accept). |
| 105 | func (b *Backend) recvLoop(ctx context.Context) { |
| 106 | defer b.reader.Done() |
| 107 | defer close(b.packets) |
| 108 | |
| 109 | buf := make([]byte, b.cfg.ReadBufferSize) |
| 110 | for { |
| 111 | n, addr, err := Recv(b.handle, buf) |
| 112 | if err != nil { |
| 113 | // ERROR_NO_DATA (232) is the graceful signal that Close() tore |
| 114 | // the handle down mid-Recv; exit silently. Anything else gets |
| 115 | // printed once so users notice unexpected errors. |
| 116 | if IsHandleClosed(err) { |
| 117 | return |
| 118 | } |
| 119 | select { |
| 120 | case <-b.closed: |
| 121 | return |
| 122 | default: |
| 123 | } |
| 124 | fmt.Printf("snix/windows: recv error: %v\n", err) |
| 125 | return |
| 126 | } |
| 127 | // Copy payload so the caller can keep it past next Recv. |
| 128 | pkt := make([]byte, n) |
| 129 | copy(pkt, buf[:n]) |
| 130 | // Copy address too (80 bytes) so the verdict closure can reinject. |
| 131 | addrCopy := addr |
| 132 | dir := snixplatform.DirInbound |
| 133 | if addr.Outbound() { |
| 134 | dir = snixplatform.DirOutbound |
| 135 | // Stash last outbound address for Inject() to reuse. |
| 136 | b.mu.Lock() |
| 137 | a := addr |
| 138 | b.outboundAddr = &a |
| 139 | b.mu.Unlock() |
| 140 | } |
| 141 | |
| 142 | verdict := func(k snixplatform.VerdictKind) { |
| 143 | switch k { |
| 144 | case snixplatform.Drop: |
| 145 | return // don't reinject; packet is dropped by not calling Send. |
| 146 | default: |
| 147 | // Reinject the original packet via WinDivertSend. |
| 148 | _, _ = Send(b.handle, pkt, &addrCopy) |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | select { |
| 153 | case b.packets <- snixplatform.Packet{Dir: dir, Raw: pkt, Verdict: verdict}: |
| 154 | case <-b.closed: |
| 155 | // Shutting down: reinject so the stack keeps flowing. |
| 156 | _, _ = Send(b.handle, pkt, &addrCopy) |
| 157 | return |
| 158 | case <-ctx.Done(): |
| 159 | _, _ = Send(b.handle, pkt, &addrCopy) |
| 160 | return |
| 161 | } |
| 162 | } |
no test coverage detected