dissertation-2-code/proxy/proxy.go
Jake Hillion d65e8d3571
Some checks failed
continuous-integration/drone/push Build is failing
udp testing
2020-11-26 22:10:37 +00:00

129 lines
2.2 KiB
Go

package proxy
import (
"log"
"time"
)
type Producer interface {
IsAlive() bool
Produce(MacVerifier) (Packet, error)
}
type Consumer interface {
IsAlive() bool
Consume(Packet, MacGenerator) error
}
type Reconnectable interface {
Reconnect() error
}
type Source interface {
Source() (Packet, error)
}
type Sink interface {
Sink(packet Packet) error
}
type Proxy struct {
Source Source
Sink Sink
Generator MacGenerator
proxyChan chan Packet
sinkChan chan Packet
}
func NewProxy(bufferSize int) *Proxy {
return &Proxy{
proxyChan: make(chan Packet, bufferSize),
sinkChan: make(chan Packet, bufferSize),
}
}
func (p Proxy) Start() {
go func() {
for {
if packet, err := p.Source.Source(); err != nil {
panic(err)
return
} else {
p.proxyChan <- packet
}
}
}()
go func() {
for {
packet := <-p.sinkChan
if err := p.Sink.Sink(packet); err != nil {
panic(err)
return
}
}
}()
}
func (p Proxy) AddConsumer(c Consumer) {
go func() {
_, reconnectable := c.(Reconnectable)
for once := true; reconnectable || once; once = false {
if reconnectable {
var err error
for once := true; err != nil || once; once = false {
log.Printf("attempting to connect consumer `%v`\n", c)
err = c.(Reconnectable).Reconnect()
if !once {
time.Sleep(time.Second)
}
}
log.Printf("connected consumer `%v`\n", c)
}
for c.IsAlive() {
if err := c.Consume(<-p.proxyChan, p.Generator); err != nil {
log.Println(err)
break
}
}
}
log.Printf("closed consumer `%v`\n", c)
}()
}
func (p Proxy) AddProducer(pr Producer, v MacVerifier) {
go func() {
_, reconnectable := pr.(Reconnectable)
for once := true; reconnectable || once; once = false {
if reconnectable {
var err error
for once := true; err != nil || once; once = false {
log.Printf("attempting to connect producer `%v`\n", pr)
err = pr.(Reconnectable).Reconnect()
if !once {
time.Sleep(time.Second)
}
}
log.Printf("connected producer `%v`\n", pr)
}
for pr.IsAlive() {
if packet, err := pr.Produce(v); err != nil {
log.Println(err)
break
} else {
p.sinkChan <- packet
}
}
}
log.Printf("closed producer `%v`\n", pr)
}()
}