mirror of
https://github.com/hanzozt/dilithium.git
synced 2026-10-30 20:38:17 +00:00
175 lines
3.4 KiB
Go
175 lines
3.4 KiB
Go
package loop
|
|
|
|
import (
|
|
"crypto/sha512"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"io"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
type Receiver struct {
|
|
headerPool *Pool
|
|
pool *Pool
|
|
conn net.Conn
|
|
blocks chan *buffer
|
|
blocksDone chan struct{}
|
|
metrics *Metrics
|
|
rate *transferReporter
|
|
Done chan struct{}
|
|
}
|
|
|
|
func NewReceiver(metrics *Metrics, conn net.Conn) *Receiver {
|
|
return &Receiver{
|
|
headerPool: NewPool(headerSz + 1),
|
|
conn: conn,
|
|
blocks: make(chan *buffer, 4096),
|
|
blocksDone: make(chan struct{}),
|
|
metrics: metrics,
|
|
rate: newTransferReporter("rx"),
|
|
Done: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (self *Receiver) Run(hasher bool) {
|
|
logrus.Info("starting")
|
|
defer logrus.Info("exiting")
|
|
|
|
go self.rate.run()
|
|
|
|
if hasher {
|
|
go self.hasher()
|
|
defer func() {
|
|
logrus.Infof("closing hasher")
|
|
close(self.blocks)
|
|
<-self.blocksDone
|
|
close(self.Done)
|
|
}()
|
|
} else {
|
|
defer close(self.Done)
|
|
}
|
|
|
|
if err := self.receiveStart(); err != nil {
|
|
logrus.Errorf("error receiving start (%v)", err)
|
|
return
|
|
}
|
|
if err := self.receiveData(hasher); err != nil {
|
|
logrus.Errorf("error receiving data (%v)", err)
|
|
return
|
|
}
|
|
|
|
logrus.Infof("[%d] header pool allocations", self.headerPool.Allocations)
|
|
if self.pool != nil {
|
|
logrus.Infof("[%d] data pool allocations", self.pool.Allocations)
|
|
}
|
|
|
|
close(self.rate.in)
|
|
}
|
|
|
|
func (self *Receiver) receiveStart() error {
|
|
h, err := readHeader(self.conn, self.headerPool)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if h.mt != START {
|
|
return errors.Errorf("expected start message")
|
|
}
|
|
if h.sz != 0 {
|
|
return errors.Errorf("non-empty start message")
|
|
}
|
|
h.buffer.unref()
|
|
return nil
|
|
}
|
|
|
|
func (self *Receiver) receiveData(hasher bool) error {
|
|
count := 0
|
|
for {
|
|
h, err := readHeader(self.conn, self.headerPool)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if h.mt == DATA {
|
|
if self.pool == nil {
|
|
self.pool = NewPool(h.sz)
|
|
}
|
|
|
|
buffer := self.pool.get()
|
|
n, err := io.ReadFull(self.conn, buffer.data[0:h.sz])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if n != int(h.sz) {
|
|
return errors.Errorf("short read [%d != %d]", n, h.sz)
|
|
}
|
|
buffer.uz = int64(n)
|
|
h.buffer.unref()
|
|
|
|
self.metrics.Rx(buffer.uz)
|
|
self.rate.in <- &transferReport{time.Now(), buffer.uz}
|
|
|
|
if hasher {
|
|
self.blocks <- buffer
|
|
}
|
|
|
|
count++
|
|
|
|
} else if h.mt == END {
|
|
if h.sz != 0 {
|
|
return errors.Errorf("non-empty end message")
|
|
}
|
|
h.buffer.unref()
|
|
|
|
if err := self.sendEnd(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
|
|
} else {
|
|
h.buffer.unref()
|
|
return errors.Errorf("unexpected message type (%d)", h.mt)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (self *Receiver) sendEnd() error {
|
|
h := &header{uint32(0), END, 0, self.headerPool.get()}
|
|
if err := writeHeader(h, self.conn); err != nil {
|
|
return err
|
|
}
|
|
h.buffer.unref()
|
|
return nil
|
|
}
|
|
|
|
func (self *Receiver) hasher() {
|
|
logrus.Infof("started")
|
|
defer logrus.Infof("exited")
|
|
defer func() { close(self.blocksDone) }()
|
|
|
|
for {
|
|
block, ok := <-self.blocks
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
inHash, data, err := decodeDataBlock(block)
|
|
if err != nil {
|
|
logrus.Errorf("error decoding data block (%v)", err)
|
|
}
|
|
|
|
outHash := sha512.Sum512(data)
|
|
if len(outHash) != len(inHash) {
|
|
logrus.Errorf("hash length mismatch [%d != %d]", len(outHash), len(inHash))
|
|
}
|
|
for i := 0; i < len(outHash); i++ {
|
|
if outHash[i] != inHash[i] {
|
|
logrus.Errorf("hash mismatch at [#%d]", i)
|
|
return
|
|
}
|
|
}
|
|
|
|
block.unref()
|
|
}
|
|
}
|