Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support WebRTC communication #961

Merged
merged 1 commit into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions api/common/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import (
"encoding/json"
"fmt"
"net"
"net/url"
"strings"
"time"

"github.com/nknorg/nkn/v2/api/common/errcode"
"github.com/nknorg/nkn/v2/api/httpjson/client"
"github.com/nknorg/nkn/v2/api/webrtc"
"github.com/nknorg/nkn/v2/block"
"github.com/nknorg/nkn/v2/chain"
"github.com/nknorg/nkn/v2/common"
Expand Down Expand Up @@ -412,12 +416,13 @@ func getVersion(s Serverer, params map[string]interface{}, ctx context.Context)
return respPacking(errcode.SUCCESS, config.Version)
}

func NodeInfo(wsAddr, rpcAddr string, pubkey, id []byte) map[string]string {
func NodeInfo(wsAddr, rpcAddr string, pubkey, id []byte, sdp string) map[string]string {
nodeInfo := make(map[string]string)
nodeInfo["addr"] = wsAddr
nodeInfo["rpcAddr"] = rpcAddr
nodeInfo["pubkey"] = hex.EncodeToString(pubkey)
nodeInfo["id"] = hex.EncodeToString(id)
nodeInfo["sdp"] = sdp
return nodeInfo
}

Expand All @@ -444,7 +449,7 @@ func getWsAddr(s Serverer, params map[string]interface{}, ctx context.Context) m
return respPacking(errcode.INTERNAL_ERROR, err.Error())
}

return respPacking(errcode.SUCCESS, NodeInfo(wsAddr, rpcAddr, pubkey, id))
return respPacking(errcode.SUCCESS, NodeInfo(wsAddr, rpcAddr, pubkey, id, ""))
}

func getWssAddr(s Serverer, params map[string]interface{}, ctx context.Context) map[string]interface{} {
Expand All @@ -467,7 +472,7 @@ func getWssAddr(s Serverer, params map[string]interface{}, ctx context.Context)
return respPacking(errcode.INTERNAL_ERROR, err.Error())
}

return respPacking(errcode.SUCCESS, NodeInfo(wsAddr, rpcAddr, pubkey, id))
return respPacking(errcode.SUCCESS, NodeInfo(wsAddr, rpcAddr, pubkey, id, ""))
}

// getBalanceByAddr gets balance by address
Expand Down Expand Up @@ -953,6 +958,59 @@ func findSuccessorAddr(s Serverer, params map[string]interface{}, ctx context.Co
return respPacking(errcode.SUCCESS, addrs[0])
}

// getPeerAddr get a node address
// params: {"address":<address>}
// return: {"resultOrData":<result>|<error data>, "error":<errcode>}
func getPeerAddr(s Serverer, params map[string]interface{}, ctx context.Context) map[string]interface{} {
if len(params) < 1 {
return RespPacking("length of params is less than 1", errcode.INVALID_PARAMS)
}

str, ok := params["address"].(string)
if !ok {
return RespPacking("address should be a string", errcode.INTERNAL_ERROR)
}

clientID, _, _, err := address.ParseClientAddress(str)
if err != nil {
return RespPacking(err.Error(), errcode.INTERNAL_ERROR)
}

wsAddr, rpcAddr, pubkey, id, err := s.GetNetNode().FindWsAddr(clientID)
if err != nil {
return RespPacking(err.Error(), errcode.INTERNAL_ERROR)
}

n := s.GetNetNode()
if n == nil {
return nil
}

if n.GetWsAddr() == wsAddr {
offer := params["offer"].(string)
peer := webrtc.NewPeer(config.Parameters.StunList)

err = peer.Answer(offer)
if err != nil {
return RespPacking(err.Error(), errcode.INTERNAL_ERROR)
}
select {
case answer := <-peer.OnSdp:
return RespPacking(NodeInfo(wsAddr, rpcAddr, pubkey, id, answer), errcode.SUCCESS)
case <-time.After(10 * time.Second):
return RespPacking(fmt.Errorf("webrtc, wait for sdp time out"), errcode.INTERNAL_ERROR)
}
}

reqAddr := (&url.URL{Scheme: "http", Host: rpcAddr}).String()
yilunzhang marked this conversation as resolved.
Show resolved Hide resolved
wsAddr, rpcAddr, pubkey, id, sdp, err := client.GetPeerAddr(reqAddr, params)
if err != nil {
return RespPacking(err.Error(), errcode.INTERNAL_ERROR)
}

return RespPacking(NodeInfo(wsAddr, rpcAddr, pubkey, id, sdp), errcode.SUCCESS)
}

var InitialAPIHandlers = map[string]APIHandler{
"getlatestblockhash": {Handler: getLatestBlockHash, AccessCtrl: BIT_JSONRPC},
"getblock": {Handler: getBlock, AccessCtrl: BIT_JSONRPC},
Expand Down Expand Up @@ -983,4 +1041,5 @@ var InitialAPIHandlers = map[string]APIHandler{
"findsuccessoraddr": {Handler: findSuccessorAddr, AccessCtrl: BIT_JSONRPC},
"findsuccessoraddrs": {Handler: findSuccessorAddrs, AccessCtrl: BIT_JSONRPC},
"getregistrant": {Handler: getRegistrant, AccessCtrl: BIT_JSONRPC},
"getpeeraddr": {Handler: getPeerAddr, AccessCtrl: BIT_JSONRPC},
}
1 change: 1 addition & 0 deletions api/httpjson/RPCserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func (s *RPCServer) Handle(w http.ResponseWriter, r *http.Request) {
}
method, ok = request["method"].(string)
if !ok {
log.Warning("RPC Server - No function to call for ", method)
code = errcode.INVALID_METHOD
}
if request["params"] != nil {
Expand Down
33 changes: 33 additions & 0 deletions api/httpjson/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,36 @@ func GetNonceByAddr(remote, addr string, txPool bool) (uint64, uint32, error) {

return nonce, ret.Result.CurrentHeight, nil
}

func GetPeerAddr(remote string, params map[string]interface{}) (string, string, []byte, []byte, string, error) {
fmt.Println("......GetPeerAddr, remote: ", remote)
resp, err := Call(remote, "getpeeraddr", 0, params)
if err != nil {
return "", "", nil, nil, "", err
}

// log.Infof("Node-to-Node GetPeerAddr got resp: %v from %s\n", string(resp), remote)

var ret struct {
Result struct {
Addr string `json:"addr"`
RpcAddr string `json:"rpcAddr"`
Pubkey []byte `json:"pubkey"`
Id []byte `json:"id"`
Sdp string `json:"sdp"`
} `json:"result"`
Err map[string]interface{} `json:"error"`
}

if err := json.Unmarshal(resp, &ret); err != nil {
log.Error("Node-to-Node GetPeerAddr json.Unmarshal error: ", err)
return "", "", nil, nil, "", err
}
if len(ret.Err) != 0 { // resp.error NOT empty
log.Error("Node-to-Node GetPeerAddr ret.Err: ", ret.Err)
return "", "", nil, nil, "", fmt.Errorf("GetPeerAddr(%s) resp error: %v", remote, string(resp))
}

fmt.Printf("......GetPeerAddr got result: %+v\n", ret.Result)
return ret.Result.Addr, ret.Result.RpcAddr, ret.Result.Pubkey, ret.Result.Id, ret.Result.Sdp, nil
}
Loading
Loading