state.go raw

   1  package main
   2  
   3  import (
   4  	"common/helpers"
   5  	"common/jsbridge/subtle"
   6  	"common/jsbridge/sw"
   7  )
   8  
   9  // Shared state not yet assigned to a specific domain.
  10  var (
  11  	dmSubIDs     map[string]bool
  12  	dmRelayURLs  []string
  13  	cryptoCBs    map[int]func(string, string)
  14  	nextCryptoID int
  15  )
  16  
  17  func initSharedState() {
  18  	dmSubIDs = make(map[string]bool)
  19  	cryptoCBs = make(map[int]func(string, string))
  20  }
  21  
  22  // --- Shared utilities ---
  23  
  24  func sendToClient(clientID, msg string) {
  25  	sw.GetClientByID(clientID, func(c sw.Client, ok bool) {
  26  		if ok {
  27  			sw.PostMessageJSON(c, msg)
  28  		}
  29  	})
  30  }
  31  
  32  func broadcastToClients(msg string) {
  33  	sw.MatchClients(func(c sw.Client) {
  34  		sw.PostMessageJSON(c, msg)
  35  	})
  36  }
  37  
  38  func jstr(s string) string { return helpers.JsonString(s) }
  39  
  40  func hexTo32(s string) [32]byte {
  41  	out, _ := helpers.HexDecode32(s)
  42  	return out
  43  }
  44  
  45  func random32() [32]byte {
  46  	var b [32]byte
  47  	subtle.RandomBytes(b[:])
  48  	return b
  49  }
  50  
  51  // mw is a JSON array message walker for parsing client messages.
  52  type mw struct {
  53  	s string
  54  	i int
  55  }
  56  
  57  func newMW(s string) mw {
  58  	w := mw{s: s}
  59  	for w.i < len(s) && s[w.i] != '[' {
  60  		w.i++
  61  	}
  62  	if w.i < len(s) {
  63  		w.i++
  64  	}
  65  	return w
  66  }
  67  
  68  func (w *mw) sep() {
  69  	for w.i < len(w.s) {
  70  		c := w.s[w.i]
  71  		if c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != ',' {
  72  			break
  73  		}
  74  		w.i++
  75  	}
  76  }
  77  
  78  func (w *mw) str() string {
  79  	w.sep()
  80  	if w.i >= len(w.s) || w.s[w.i] != '"' {
  81  		return ""
  82  	}
  83  	w.i++
  84  	start := w.i
  85  	for w.i < len(w.s) && w.s[w.i] != '"' {
  86  		if w.s[w.i] == '\\' {
  87  			w.i++
  88  		}
  89  		w.i++
  90  	}
  91  	if w.i >= len(w.s) {
  92  		return ""
  93  	}
  94  	result := w.s[start:w.i]
  95  	w.i++
  96  	return result
  97  }
  98  
  99  func (w *mw) num() int64 {
 100  	w.sep()
 101  	neg := false
 102  	if w.i < len(w.s) && w.s[w.i] == '-' {
 103  		neg = true
 104  		w.i++
 105  	}
 106  	var n int64
 107  	for w.i < len(w.s) && w.s[w.i] >= '0' && w.s[w.i] <= '9' {
 108  		n = n*10 + int64(w.s[w.i]-'0')
 109  		w.i++
 110  	}
 111  	if neg {
 112  		n = -n
 113  	}
 114  	return n
 115  }
 116  
 117  func (w *mw) raw() string {
 118  	w.sep()
 119  	start := w.i
 120  	w.i = skipval(w.s, w.i)
 121  	if w.i < 0 {
 122  		w.i = len(w.s)
 123  		return ""
 124  	}
 125  	return w.s[start:w.i]
 126  }
 127  
 128  func (w *mw) strs() []string {
 129  	w.sep()
 130  	if w.i >= len(w.s) || w.s[w.i] != '[' {
 131  		return nil
 132  	}
 133  	w.i++
 134  	var out []string
 135  	for {
 136  		w.sep()
 137  		if w.i >= len(w.s) {
 138  			return out
 139  		}
 140  		if w.s[w.i] == ']' {
 141  			w.i++
 142  			return out
 143  		}
 144  		if w.s[w.i] != '"' {
 145  			return out
 146  		}
 147  		w.i++
 148  		start := w.i
 149  		for w.i < len(w.s) && w.s[w.i] != '"' {
 150  			if w.s[w.i] == '\\' {
 151  				w.i++
 152  			}
 153  			w.i++
 154  		}
 155  		if w.i < len(w.s) {
 156  			out = append(out, w.s[start:w.i])
 157  			w.i++
 158  		}
 159  	}
 160  }
 161  
 162  func skipval(s string, i int) int {
 163  	if i >= len(s) {
 164  		return -1
 165  	}
 166  	switch s[i] {
 167  	case '"':
 168  		i++
 169  		for i < len(s) {
 170  			if s[i] == '\\' {
 171  				i += 2
 172  				continue
 173  			}
 174  			if s[i] == '"' {
 175  				return i + 1
 176  			}
 177  			i++
 178  		}
 179  		return -1
 180  	case '{':
 181  		return skipBrack(s, i, '{', '}')
 182  	case '[':
 183  		return skipBrack(s, i, '[', ']')
 184  	case 't':
 185  		if i+4 <= len(s) {
 186  			return i + 4
 187  		}
 188  		return -1
 189  	case 'f':
 190  		if i+5 <= len(s) {
 191  			return i + 5
 192  		}
 193  		return -1
 194  	case 'n':
 195  		if i+4 <= len(s) {
 196  			return i + 4
 197  		}
 198  		return -1
 199  	default:
 200  		for i < len(s) && s[i] != ',' && s[i] != '}' && s[i] != ']' && s[i] != ' ' && s[i] != '\n' {
 201  			i++
 202  		}
 203  		return i
 204  	}
 205  }
 206  
 207  func skipBrack(s string, i int, open, close byte) int {
 208  	depth := 1
 209  	i++
 210  	inStr := false
 211  	for i < len(s) && depth > 0 {
 212  		if inStr {
 213  			if s[i] == '\\' {
 214  				i++
 215  			} else if s[i] == '"' {
 216  				inStr = false
 217  			}
 218  		} else {
 219  			switch s[i] {
 220  			case '"':
 221  				inStr = true
 222  			case open:
 223  				depth++
 224  			case close:
 225  				depth--
 226  			}
 227  		}
 228  		i++
 229  	}
 230  	if depth != 0 {
 231  		return -1
 232  	}
 233  	return i
 234  }
 235