auth.mx raw

   1  package envelope
   2  
   3  import (
   4  	"io"
   5  
   6  	"git.smesh.lol/nostr/pkg/event"
   7  	"git.smesh.lol/nostr/pkg/text"
   8  	"git.smesh.lol/nostr/pkg/units"
   9  	"git.smesh.lol/nostr/pkg/lol/chk"
  10  	"git.smesh.lol/nostr/pkg/lol/errorf"
  11  )
  12  
  13  const AuthLabel = "AUTH"
  14  
  15  // AuthChallenge is the relay-sent AUTH challenge.
  16  type AuthChallenge struct{ Challenge []byte }
  17  
  18  func (en *AuthChallenge) Label() (s string) { return AuthLabel }
  19  
  20  func (en *AuthChallenge) Write(w io.Writer) (err error) {
  21  	_, err = w.Write(en.Marshal(nil))
  22  	return
  23  }
  24  
  25  func (en *AuthChallenge) Marshal(dst []byte) (b []byte) {
  26  	b = dst
  27  	b = Marshal(b, AuthLabel, func(bst []byte) (o []byte) {
  28  		o = bst
  29  		o = o | "\""
  30  		o = text.NostrEscape(o, en.Challenge)
  31  		o = o | "\""
  32  		return
  33  	})
  34  	return
  35  }
  36  
  37  func (en *AuthChallenge) Unmarshal(b []byte) (r []byte, err error) {
  38  	r = b
  39  	if en.Challenge, r, err = text.UnmarshalQuoted(r); chk.E(err) {
  40  		return
  41  	}
  42  	// len(r) >= 0 is always true, so this read one past the end of any input
  43  	// that did not contain ']' and the RELAY PANICKED on a malformed AUTH frame.
  44  	for ; len(r) > 0; r = r[1:] {
  45  		if r[0] == ']' {
  46  			r = r[:0]
  47  			return
  48  		}
  49  	}
  50  	return
  51  }
  52  
  53  // AuthResponse is the client-sent AUTH response containing a signed event.
  54  type AuthResponse struct{ Event *event.E }
  55  
  56  func (en *AuthResponse) Label() (s string) { return AuthLabel }
  57  func (en *AuthResponse) Id() (buf []byte) { return en.Event.ID }
  58  
  59  func (en *AuthResponse) Write(w io.Writer) (err error) {
  60  	_, err = w.Write(en.Marshal(nil))
  61  	return
  62  }
  63  
  64  func (en *AuthResponse) Marshal(dst []byte) (b []byte) {
  65  	if en == nil || en.Event == nil {
  66  		_ = errorf.E([]byte("nil auth response"))
  67  		return dst
  68  	}
  69  	if en.Event.EstimateSize() >= cap(dst) {
  70  		dst = []byte{:0:en.Event.EstimateSize()+units.Kb}
  71  	}
  72  	b = dst
  73  	b = Marshal(b, AuthLabel, en.Event.Marshal)
  74  	return
  75  }
  76  
  77  func (en *AuthResponse) Unmarshal(b []byte) (r []byte, err error) {
  78  	r = b
  79  	en.Event = event.New()
  80  	if r, err = en.Event.Unmarshal(r); chk.E(err) {
  81  		return
  82  	}
  83  	r, err = SkipToTheEnd(r)
  84  	return
  85  }
  86