# Implementation Goals
From a working Transport Layer (TL + Socket) implementation, wrap/decorate to add an disruption layer, to simulate various network incidents:
- Delay (fixed, random, ...)
- Reordering packets
- Packet injection (duplication, fake packets,...)
- Packet loss
- Buffer/Jam behavior (blocking packets until threshold on time/#packets/...)
- other behaviors
Suggested implementation direction:
- focus on sender-side: trigger new behaviors on calling Send()
- implement a new Socket type (leveraging the existing interface), wrapping another socket
# Implementation
## Design choices
- Buffer Jam: we realized that taking into account the number of packets to be buffered will introduce sequentiality. It might be better to simulate the jam using sinusoidal (or similar, having a stateful filter) delays
- Injection: Beyond randomizing the payload, we also thought about spoofing (changing the source address for example).
But:
- too 'random' packets -> trigger early drops, more useful as unit tests rather than stress-test
- crafting precise packets: hard to define, + risk of implementing an actual attack (overkill given the threat model considered?)
- Reordering: To avoid sequentiality issues (and +-converting a packet-based system to a stream-based system) we implicitly implemented it through delays only
## New Transport Layer - DisruptedLayer
```
type DisruptedTransport struct {
transport.Transport
filters []Filter
}
```
Wrapper for a 'normal TL'. Needed as Sockets are instantiated by call to the TL.
Contains the 'normal TL', and a list of filters (uninitialized) to be copied and launched for every instantiated disrupted socket.
On socket creation, a 'normal socket' is created through the wrapped TL, then wrapped in a DisruptedSocket, for which filters are copied and `Start()`-ed, then an 'end-of-line' listening goroutine is launched (see further).
## New Socket - DisruptedSocket
```
type Socket struct {
transport.ClosableSocket
filters []Filter
}
```
Wrapper for a 'normal Socket'.
Contains an ordered list of autonomous filters, sequentially connected by channels transmitting `SendingTriplet`s (decorated packets with destination and timeout to use on the actual normalSocket `Send()`).
```
type SendingTriplet struct {
dest string
pkt transport.Packet
timeout time.Duration
}
```
An incoming packet is transferred to the first Filter of the list through its input channel (non-blocking `In()` call), which will act on it and transmit to the next filter, etc.
The DisruptedSocket has a goroutine listening on the last channel, and calling the normalSocket `Send()` as soon as a SendingTriplet is available.
Due to the asynchronous nature of this implementation, DisruptedSocket's `Send()` is non-blocking (always returning nil).
## Filters (old version)
Spec: one op only, `Pass(pkt transport.Packet) ([]transport.Packet)`, called concurrently (slice to handle packet injection)
Issues:
- apply filter n+1 on all filters outputted by filter n ?
- delays: blocking on a packet blocks all the slice
- privileges: trying to send duplicates directly means the Filter has sending privileges (-> access to the socket ?)
## Filters (new version)
```
type Filter interface {
Start() // Launch Filter listener
Stop() // Stop Filter listener
Copy() Filter // Copy Filter
pass(tripl SendingTriplet) // Internal, compute the filter function on an augmented packet
SetIO(chan SendingTriplet, chan SendingTriplet) // Used to initialize channels
In(SendingTriplet) // (blocking) To feed a packet into the filter
}
```
Autonomous item with in/out channels.
Once `Start()`-ed, waits on input packets, processes (non-blocking) them using `pass()` and transmits to `out` channel. Also waits on a quit channel, triggered by `Stop()`. `Copy()` needed to instantiate all sockets.
`SetIO()` and `In()` needed at TL-level to resp. initialize all filters for a new socket, and feed a packet into the first filter when calling `Send()`.
- Injection:
- Pseudo-random:
- [ ] unmarshable (sanity check)
- [ ] marshable w/ random packet ID
- [ ] marshable w/ random source (spoof)
- [x] Duplication: poisson distribution for #packets added
- Delay:
- [x] Exponential (HW transfer time)
- [x] Stateful (pseudo-atomic op needed, at least monotonic inc) ~periodic for jam simulation w/ non-0 mean
- [x] Fixed
- Loss:
- [x] Probabilistic drops of packets
---
---
# Draft
## Issues - various
(Filter design) Issue: need for interface (~virtual class), so that `Start()` launches listener on in/out and calls `pass()`. Pb: `pass()` needs out channel, ended up with cyclic dependancy design. (lack of virtual classes/inheritance in Golang?)
**Solved** by accepting redundant code (every Filter has its own Start(), Stop(), SetIO(), In() implementations even if identical)
## How to test filters
- integrate them into some tests
-
# Discussions
- Ref implem => 100% tests ?
- Adapt all tests, only integration ?
- filters implement Socket (ClosableSocket)
- Send direct
- go routine en continue + delais
# Réu 02/08
- recv side
- filter -> interface Socket (truc récursif)
- integrate filters into tests
- func option pattern pr init
- implementation with a queue
