DataHoarder
e1d0e27c29
All checks were successful
continuous-integration/drone/push Build is passing
134 lines
3.4 KiB
Go
134 lines
3.4 KiB
Go
package content
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"git.gammaspectra.live/S.O.N.G/FinalCommander/utilities"
|
|
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival"
|
|
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival/contentmessage"
|
|
"github.com/cloudflare/circl/sign/ed25519"
|
|
"github.com/multiformats/go-multihash"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Server struct {
|
|
Index int
|
|
Address string
|
|
Weight uint
|
|
LastCheckResult bool
|
|
LastCheckMutex sync.RWMutex
|
|
}
|
|
|
|
func NewContentServerFromArgument(arg string, index int) (*Server, error) {
|
|
//Format address:PORT/WEIGHT[/publicKey],
|
|
p := strings.Split(arg, "/")
|
|
if len(p) < 2 {
|
|
return nil, fmt.Errorf("invalid weighted server %s", arg)
|
|
}
|
|
|
|
weight, err := strconv.ParseUint(p[1], 10, 32)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cs := &Server{
|
|
Index: index,
|
|
Address: p[0],
|
|
Weight: uint(weight),
|
|
LastCheckResult: false,
|
|
}
|
|
|
|
return cs, nil
|
|
}
|
|
|
|
func (s *Server) GetContentURL(content *Entry, key ed25519.PrivateKey, skip []int) string {
|
|
message := contentmessage.NewContentMessageV1(content.Multihash(), key)
|
|
skip = append(skip, s.Index)
|
|
return s.getURL(MakyuuIchaival.Bech32Encoding.EncodeToString(message.Encode()), MakyuuIchaival.Bech32Encoding.EncodeToString(utilities.EncodeIntegerList(skip)))
|
|
}
|
|
|
|
func (s *Server) GetHashURL(mh multihash.Multihash, key ed25519.PrivateKey, skip []int) string {
|
|
message := contentmessage.NewContentMessageV1(mh, key)
|
|
skip = append(skip, s.Index)
|
|
return s.getURL(MakyuuIchaival.Bech32Encoding.EncodeToString(message.Encode()), MakyuuIchaival.Bech32Encoding.EncodeToString(utilities.EncodeIntegerList(skip)))
|
|
}
|
|
|
|
func (s *Server) getURL(args ...string) string {
|
|
return fmt.Sprintf("https://%s/%s", s.Address, strings.Join(args, "/"))
|
|
}
|
|
|
|
func (s *Server) GetCheckResult() bool {
|
|
s.LastCheckMutex.RLock()
|
|
defer s.LastCheckMutex.RUnlock()
|
|
return s.LastCheckResult
|
|
}
|
|
|
|
func (s *Server) setCheckResult(result bool) {
|
|
s.LastCheckMutex.Lock()
|
|
defer s.LastCheckMutex.Unlock()
|
|
s.LastCheckResult = result
|
|
}
|
|
|
|
func (s *Server) Check() {
|
|
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
|
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
|
client := &http.Client{
|
|
Transport: customTransport,
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
response, err := client.Head(s.getURL())
|
|
|
|
if err != nil {
|
|
s.setCheckResult(false)
|
|
return
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusBadRequest {
|
|
s.setCheckResult(false)
|
|
return
|
|
}
|
|
s.setCheckResult(true)
|
|
}
|
|
|
|
func (s *Server) CheckEntryKey(key *HashIdentifier, privateKey ed25519.PrivateKey) *HashIdentifier {
|
|
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
|
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
|
client := &http.Client{
|
|
Transport: customTransport,
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
response, err := client.Head(s.GetHashURL(key.Hash(), privateKey, []int{}))
|
|
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return nil
|
|
}
|
|
|
|
v := strings.Split(response.Header.Get("Digest"), "=")
|
|
if len(v) >= 2 && v[0] == "sha-256" {
|
|
sha, err := base64.StdEncoding.DecodeString(strings.Join(v[1:], "="))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
mh, err := multihash.Encode(sha, multihash.SHA2_256)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return NewHashIdentifierFromMultihash(mh)
|
|
}
|
|
|
|
return nil
|
|
}
|