github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/kex2_router.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"encoding/base64"
     8  	"time"
     9  
    10  	"github.com/keybase/client/go/kex2"
    11  )
    12  
    13  // KexRouter implements the kex2.MessageRouter interface.
    14  type KexRouter struct {
    15  	MetaContextified
    16  }
    17  
    18  // NewKexRouter creates a contextified KexRouter.
    19  func NewKexRouter(m MetaContext) *KexRouter {
    20  	return &KexRouter{
    21  		MetaContextified: NewMetaContextified(m),
    22  	}
    23  }
    24  
    25  // Post implements Post in the kex2.MessageRouter interface.
    26  func (k *KexRouter) Post(sessID kex2.SessionID, sender kex2.DeviceID, seqno kex2.Seqno, msg []byte) (err error) {
    27  	mctx := k.M().WithLogTag("KEXR")
    28  	mctx.Debug("+ KexRouter.Post(%x, %x, %d, ...)", sessID, sender, seqno)
    29  	defer func() {
    30  		mctx.Debug("- KexRouter.Post(%x, %x, %d) -> %s", sessID, sender, seqno, ErrToOk(err))
    31  	}()
    32  
    33  	arg := APIArg{
    34  		Endpoint: "kex2/send",
    35  		Args: HTTPArgs{
    36  			"I":      HexArg(sessID[:]),
    37  			"sender": HexArg(sender[:]),
    38  			"seqno":  I{Val: int(seqno)},
    39  			"msg":    B64Arg(msg),
    40  		},
    41  	}
    42  	mctx = mctx.BackgroundWithLogTags()
    43  	kexAPITimeout(&arg, time.Second*5)
    44  	_, err = mctx.G().API.Post(mctx, arg)
    45  
    46  	return err
    47  }
    48  
    49  type kexResp struct {
    50  	Msgs []struct {
    51  		Msg string `json:"msg"`
    52  	} `json:"msgs"`
    53  	Status AppStatus `json:"status"`
    54  }
    55  
    56  func (k *kexResp) GetAppStatus() *AppStatus {
    57  	return &k.Status
    58  }
    59  
    60  func kexAPITimeout(arg *APIArg, initial time.Duration) {
    61  	arg.RetryCount = 5
    62  	arg.RetryMultiplier = 1.0
    63  	initialMin := time.Second * 3
    64  	if initial < initialMin {
    65  		initial = initialMin
    66  	}
    67  	arg.InitialTimeout = initial
    68  }
    69  
    70  // Get implements Get in the kex2.MessageRouter interface.
    71  func (k *KexRouter) Get(sessID kex2.SessionID, receiver kex2.DeviceID, low kex2.Seqno, poll time.Duration) (msgs [][]byte, err error) {
    72  	mctx := k.M().WithLogTag("KEXR")
    73  	mctx.Debug("+ KexRouter.Get(%x, %x, %d, %s)", sessID, receiver, low, poll)
    74  	defer func() {
    75  		mctx.Debug("- KexRouter.Get(%x, %x, %d, %s) -> %s (messages: %d)", sessID, receiver, low, poll, ErrToOk(err), len(msgs))
    76  	}()
    77  
    78  	if poll > HTTPPollMaximum {
    79  		poll = HTTPPollMaximum
    80  	}
    81  
    82  	arg := APIArg{
    83  		Endpoint: "kex2/receive",
    84  		Args: HTTPArgs{
    85  			"I":        HexArg(sessID[:]),
    86  			"receiver": HexArg(receiver[:]),
    87  			"low":      I{Val: int(low)},
    88  			"poll":     I{Val: int(poll / time.Millisecond)},
    89  		},
    90  	}
    91  	kexAPITimeout(&arg, 2*poll)
    92  	var j kexResp
    93  
    94  	if err = mctx.G().API.GetDecode(mctx.BackgroundWithLogTags(), arg, &j); err != nil {
    95  		return nil, err
    96  	}
    97  	if j.Status.Code != SCOk {
    98  		return nil, AppStatusError{Code: j.Status.Code, Name: j.Status.Name, Desc: j.Status.Desc}
    99  	}
   100  
   101  	for _, m := range j.Msgs {
   102  		dec, err := base64.StdEncoding.DecodeString(m.Msg)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		msgs = append(msgs, dec)
   107  	}
   108  
   109  	return msgs, nil
   110  }