reflector.go/peer/server.go
2018-01-29 14:37:26 -05:00

190 lines
3.3 KiB
Go

package peer
import (
"crypto/sha512"
"encoding/hex"
"encoding/json"
"io"
"net"
"github.com/lbryio/reflector.go/store"
log "github.com/sirupsen/logrus"
)
const (
DefaultPort = 3333
)
type Server struct {
store store.BlobStore
}
func NewServer(store store.BlobStore) *Server {
return &Server{
store: store,
}
}
func (s *Server) ListenAndServe(address string) error {
log.Println("Listening on " + address)
l, err := net.Listen("tcp", address)
if err != nil {
return err
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
log.Error(err)
} else {
go s.handleConn(conn)
}
}
}
func (s *Server) handleConn(conn net.Conn) {
// TODO: connection should time out eventually
defer conn.Close()
err := s.doAvailabilityRequest(conn)
if err != nil {
log.Error(err)
return
}
err = s.doPaymentRateNegotiation(conn)
if err != nil {
log.Error(err)
return
}
for {
err = s.doBlobRequest(conn)
if err != nil {
if err != io.EOF {
log.Error(err)
}
return
}
}
}
func (s *Server) doAvailabilityRequest(conn net.Conn) error {
var request availabilityRequest
err := json.NewDecoder(conn).Decode(&request)
if err != nil {
return err
}
address := "bJxKvpD96kaJLriqVajZ7SaQTsWWyrGQct"
availableBlobs := []string{}
for _, blobHash := range request.RequestedBlobs {
exists, err := s.store.Has(blobHash)
if err != nil {
return err
}
if exists {
availableBlobs = append(availableBlobs, blobHash)
}
}
response, err := json.Marshal(availabilityResponse{LbrycrdAddress: address, AvailableBlobs: availableBlobs})
if err != nil {
return err
}
_, err = conn.Write(response)
if err != nil {
return err
}
return nil
}
func (s *Server) doPaymentRateNegotiation(conn net.Conn) error {
var request paymentRateRequest
err := json.NewDecoder(conn).Decode(&request)
if err != nil {
return err
}
offerReply := paymentRateAccepted
if request.BlobDataPaymentRate < 0 {
offerReply = paymentRateTooLow
}
response, err := json.Marshal(paymentRateResponse{BlobDataPaymentRate: offerReply})
if err != nil {
return err
}
_, err = conn.Write(response)
if err != nil {
return err
}
return nil
}
func (s *Server) doBlobRequest(conn net.Conn) error {
var request blobRequest
err := json.NewDecoder(conn).Decode(&request)
if err != nil {
return err
}
log.Println("Sending blob " + request.RequestedBlob[:8])
blob, err := s.store.Get(request.RequestedBlob)
if err != nil {
return err
}
response, err := json.Marshal(blobResponse{IncomingBlob: incomingBlob{
BlobHash: getBlobHash(blob),
Length: len(blob),
}})
if err != nil {
return err
}
_, err = conn.Write(response)
if err != nil {
return err
}
_, err = conn.Write(blob)
if err != nil {
return err
}
return nil
}
func readAll(conn net.Conn) {
buf := make([]byte, 0, 4096) // big buffer
tmp := make([]byte, 256) // using small tmo buffer for demonstrating
for {
n, err := conn.Read(tmp)
if err != nil {
if err != io.EOF {
log.Println("read error:", err)
}
break
}
log.Println("got", n, "bytes.")
buf = append(buf, tmp[:n]...)
}
log.Println("total size:", len(buf))
if len(buf) > 0 {
log.Println(string(buf))
}
}
func getBlobHash(blob []byte) string {
hashBytes := sha512.Sum384(blob)
return hex.EncodeToString(hashBytes[:])
}