Skip to content

Commit d02ff28

Browse files
committed
upgrade xdc to use gorilla for websocket instead of the native net
1 parent 1404cb0 commit d02ff28

32 files changed

+193
-4686
lines changed

cmd/faucet/faucet.go

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import (
5858
"github.com/XinFinOrg/XDC-Subnet/p2p/discv5"
5959
"github.com/XinFinOrg/XDC-Subnet/p2p/nat"
6060
"github.com/XinFinOrg/XDC-Subnet/params"
61-
"golang.org/x/net/websocket"
61+
"github.com/gorilla/websocket"
6262
)
6363

6464
var (
@@ -204,14 +204,21 @@ type faucet struct {
204204
nonce uint64 // Current pending nonce of the faucet
205205
price *big.Int // Current gas price to issue funds with
206206

207-
conns []*websocket.Conn // Currently live websocket connections
207+
conns []*wsConn // Currently live websocket connections
208208
timeouts map[string]time.Time // History of users and their funding timeouts
209209
reqs []*request // Currently pending funding requests
210210
update chan struct{} // Channel to signal request updates
211211

212212
lock sync.RWMutex // Lock protecting the faucet's internals
213213
}
214214

215+
// wsConn wraps a websocket connection with a write mutex as the underlying
216+
// websocket library does not synchronize access to the stream.
217+
type wsConn struct {
218+
conn *websocket.Conn
219+
wlock sync.Mutex
220+
}
221+
215222
func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) {
216223
// Assemble the raw devp2p protocol stack
217224
stack, err := node.New(&node.Config{
@@ -289,7 +296,7 @@ func (f *faucet) listenAndServe(port int) error {
289296
go f.loop()
290297

291298
http.HandleFunc("/", f.webHandler)
292-
http.Handle("/api", websocket.Handler(f.apiHandler))
299+
http.HandleFunc("/api", f.apiHandler)
293300

294301
return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
295302
}
@@ -301,18 +308,24 @@ func (f *faucet) webHandler(w http.ResponseWriter, r *http.Request) {
301308
}
302309

303310
// apiHandler handles requests for Ether grants and transaction statuses.
304-
func (f *faucet) apiHandler(conn *websocket.Conn) {
311+
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
312+
upgrader := websocket.Upgrader{}
313+
conn, err := upgrader.Upgrade(w, r, nil)
314+
if err != nil {
315+
return
316+
}
305317
// Start tracking the connection and drop at the end
306318
defer conn.Close()
307319

308320
f.lock.Lock()
309-
f.conns = append(f.conns, conn)
321+
wsconn := &wsConn{conn: conn}
322+
f.conns = append(f.conns, wsconn)
310323
f.lock.Unlock()
311324

312325
defer func() {
313326
f.lock.Lock()
314327
for i, c := range f.conns {
315-
if c == conn {
328+
if c.conn == conn {
316329
f.conns = append(f.conns[:i], f.conns[i+1:]...)
317330
break
318331
}
@@ -324,7 +337,6 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
324337
head *types.Header
325338
balance *big.Int
326339
nonce uint64
327-
err error
328340
)
329341
for {
330342
// Attempt to retrieve the stats, may error on no faucet connectivity
@@ -340,7 +352,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
340352

341353
// If stats retrieval failed, wait a bit and retry
342354
if err != nil {
343-
if err = sendError(conn, errors.New("Faucet offline: "+err.Error())); err != nil {
355+
if err = sendError(wsconn, errors.New("Faucet offline: "+err.Error())); err != nil {
344356
log.Warn("Failed to send faucet error to client", "err", err)
345357
return
346358
}
@@ -351,7 +363,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
351363
break
352364
}
353365
// Send over the initial stats and the latest header
354-
if err = send(conn, map[string]interface{}{
366+
if err = send(wsconn, map[string]interface{}{
355367
"funds": balance.Div(balance, ether),
356368
"funded": nonce,
357369
"peers": f.stack.Server().PeerCount(),
@@ -360,7 +372,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
360372
log.Warn("Failed to send initial stats to client", "err", err)
361373
return
362374
}
363-
if err = send(conn, head, 3*time.Second); err != nil {
375+
if err = send(wsconn, head, 3*time.Second); err != nil {
364376
log.Warn("Failed to send initial header to client", "err", err)
365377
return
366378
}
@@ -372,19 +384,19 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
372384
Tier uint `json:"tier"`
373385
Captcha string `json:"captcha"`
374386
}
375-
if err = websocket.JSON.Receive(conn, &msg); err != nil {
387+
if err = conn.ReadJSON(&msg); err != nil {
376388
return
377389
}
378390
if !*noauthFlag && !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") &&
379391
!strings.HasPrefix(msg.URL, "https://plus.google.com/") && !strings.HasPrefix(msg.URL, "https://www.facebook.com/") {
380-
if err = sendError(conn, errors.New("URL doesn't link to supported services")); err != nil {
392+
if err = sendError(wsconn, errors.New("URL doesn't link to supported services")); err != nil {
381393
log.Warn("Failed to send URL error to client", "err", err)
382394
return
383395
}
384396
continue
385397
}
386398
if msg.Tier >= uint(*tiersFlag) {
387-
if err = sendError(conn, errors.New("Invalid funding tier requested")); err != nil {
399+
if err = sendError(wsconn, errors.New("Invalid funding tier requested")); err != nil {
388400
log.Warn("Failed to send tier error to client", "err", err)
389401
return
390402
}
@@ -400,7 +412,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
400412

401413
res, err := http.PostForm("https://www.google.com/recaptcha/api/siteverify", form)
402414
if err != nil {
403-
if err = sendError(conn, err); err != nil {
415+
if err = sendError(wsconn, err); err != nil {
404416
log.Warn("Failed to send captcha post error to client", "err", err)
405417
return
406418
}
@@ -413,15 +425,15 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
413425
err = json.NewDecoder(res.Body).Decode(&result)
414426
res.Body.Close()
415427
if err != nil {
416-
if err = sendError(conn, err); err != nil {
428+
if err = sendError(wsconn, err); err != nil {
417429
log.Warn("Failed to send captcha decode error to client", "err", err)
418430
return
419431
}
420432
continue
421433
}
422434
if !result.Success {
423435
log.Warn("Captcha verification failed", "err", string(result.Errors))
424-
if err = sendError(conn, errors.New("Beep-bop, you're a robot!")); err != nil {
436+
if err = sendError(wsconn, errors.New("Beep-bop, you're a robot!")); err != nil {
425437
log.Warn("Failed to send captcha failure to client", "err", err)
426438
return
427439
}
@@ -436,7 +448,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
436448
)
437449
switch {
438450
case strings.HasPrefix(msg.URL, "https://gist.github.com/"):
439-
if err = sendError(conn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil {
451+
if err = sendError(wsconn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil {
440452
log.Warn("Failed to send GitHub deprecation to client", "err", err)
441453
return
442454
}
@@ -453,7 +465,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
453465
err = errors.New("Something funky happened, please open an issue at https://github.com/XinFinOrg/XDC-Subnet/issues")
454466
}
455467
if err != nil {
456-
if err = sendError(conn, err); err != nil {
468+
if err = sendError(wsconn, err); err != nil {
457469
log.Warn("Failed to send prefix error to client", "err", err)
458470
return
459471
}
@@ -477,7 +489,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
477489
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainId)
478490
if err != nil {
479491
f.lock.Unlock()
480-
if err = sendError(conn, err); err != nil {
492+
if err = sendError(wsconn, err); err != nil {
481493
log.Warn("Failed to send transaction creation error to client", "err", err)
482494
return
483495
}
@@ -486,7 +498,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
486498
// Submit the transaction and mark as funded if successful
487499
if err := f.client.SendTransaction(context.Background(), signed); err != nil {
488500
f.lock.Unlock()
489-
if err = sendError(conn, err); err != nil {
501+
if err = sendError(wsconn, err); err != nil {
490502
log.Warn("Failed to send transaction transmission error to client", "err", err)
491503
return
492504
}
@@ -505,13 +517,13 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
505517

506518
// Send an error if too frequent funding, othewise a success
507519
if !fund {
508-
if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
520+
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
509521
log.Warn("Failed to send funding error to client", "err", err)
510522
return
511523
}
512524
continue
513525
}
514-
if err = sendSuccess(conn, fmt.Sprintf("Funding request accepted for %s into %s", username, address.Hex())); err != nil {
526+
if err = sendSuccess(wsconn, fmt.Sprintf("Funding request accepted for %s into %s", username, address.Hex())); err != nil {
515527
log.Warn("Failed to send funding success to client", "err", err)
516528
return
517529
}
@@ -581,12 +593,12 @@ func (f *faucet) loop() {
581593
"requests": f.reqs,
582594
}, time.Second); err != nil {
583595
log.Warn("Failed to send stats to client", "err", err)
584-
conn.Close()
596+
conn.conn.Close()
585597
continue
586598
}
587599
if err := send(conn, head, time.Second); err != nil {
588600
log.Warn("Failed to send header to client", "err", err)
589-
conn.Close()
601+
conn.conn.Close()
590602
}
591603
}
592604
f.lock.RUnlock()
@@ -608,7 +620,7 @@ func (f *faucet) loop() {
608620
for _, conn := range f.conns {
609621
if err := send(conn, map[string]interface{}{"requests": f.reqs}, time.Second); err != nil {
610622
log.Warn("Failed to send requests to client", "err", err)
611-
conn.Close()
623+
conn.conn.Close()
612624
}
613625
}
614626
f.lock.RUnlock()
@@ -618,23 +630,25 @@ func (f *faucet) loop() {
618630

619631
// sends transmits a data packet to the remote end of the websocket, but also
620632
// setting a write deadline to prevent waiting forever on the node.
621-
func send(conn *websocket.Conn, value interface{}, timeout time.Duration) error {
633+
func send(conn *wsConn, value interface{}, timeout time.Duration) error {
622634
if timeout == 0 {
623635
timeout = 60 * time.Second
624636
}
625-
conn.SetWriteDeadline(time.Now().Add(timeout))
626-
return websocket.JSON.Send(conn, value)
637+
conn.wlock.Lock()
638+
defer conn.wlock.Unlock()
639+
conn.conn.SetWriteDeadline(time.Now().Add(timeout))
640+
return conn.conn.WriteJSON(value)
627641
}
628642

629643
// sendError transmits an error to the remote end of the websocket, also setting
630644
// the write deadline to 1 second to prevent waiting forever.
631-
func sendError(conn *websocket.Conn, err error) error {
645+
func sendError(conn *wsConn, err error) error {
632646
return send(conn, map[string]string{"error": err.Error()}, time.Second)
633647
}
634648

635649
// sendSuccess transmits a success message to the remote end of the websocket, also
636650
// setting the write deadline to 1 second to prevent waiting forever.
637-
func sendSuccess(conn *websocket.Conn, msg string) error {
651+
func sendSuccess(conn *wsConn, msg string) error {
638652
return send(conn, map[string]string{"success": msg}, time.Second)
639653
}
640654

0 commit comments

Comments
 (0)