Skip to content

Commit

Permalink
Initial self review
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoPolo committed Jul 20, 2023
1 parent 59721e3 commit 6f0fa81
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 20 deletions.
14 changes: 8 additions & 6 deletions p2p/http/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,15 @@ func AuthenticateClient(hostKey crypto.PrivKey, responseHeader http.Header, requ
return "", fmt.Errorf("error generating noise payload: %w", err)
}

authInfoMsg, _, _, err := hs.WriteMessage(hbuf[:0], payload)
authInfoMsg, cs1, cs2, err := hs.WriteMessage(hbuf[:0], payload)
if err != nil {
return "", fmt.Errorf("error writing handshake message: %w", err)
}

if cs1 == nil || cs2 == nil {
return "", errors.New("expected handshake to be complete")
}

authInfoMsgEncoded, err := multibase.Encode(multibase.Encodings["base32"], authInfoMsg)
if err != nil {
return "", fmt.Errorf("error encoding handshake message: %w", err)
Expand Down Expand Up @@ -171,7 +175,7 @@ func (s AuthState) AuthenticateServer(expectedSNI string, responseHeader http.He
}

if cs1 == nil || cs2 == nil {
return "", errors.New("expected ciphersuites to be present")
return "", errors.New("expected handshake to be complete")
}

server, extensions, err := handleRemoteHandshakePayload(payload, s.hs.PeerStatic())
Expand All @@ -198,9 +202,7 @@ func (s AuthState) AuthenticateServer(expectedSNI string, responseHeader http.He
}

func generateNoisePayload(hostKey crypto.PrivKey, localStatic noise.DHKey, ext *pb.NoiseExtensions) ([]byte, error) {
// obtain the public key from the handshake session, so we can sign it with
// our libp2p secret key.
localKeyRaw, err := crypto.MarshalPublicKey(hostKey.GetPublic())
localPubKeyRaw, err := crypto.MarshalPublicKey(hostKey.GetPublic())
if err != nil {
return nil, fmt.Errorf("error serializing libp2p identity key: %w", err)
}
Expand All @@ -214,7 +216,7 @@ func generateNoisePayload(hostKey crypto.PrivKey, localStatic noise.DHKey, ext *

// create payload
payloadEnc, err := proto.Marshal(&pb.NoiseHandshakePayload{
IdentityKey: localKeyRaw,
IdentityKey: localPubKeyRaw,
IdentitySig: signedPayload,
Extensions: ext,
})
Expand Down
39 changes: 26 additions & 13 deletions p2p/http/libp2phttp.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// HTTP semantics with libp2p. Can use a libp2p stream transport or stock HTTP
// transports. This API is experimental and will likely change soon. Implements libp2p spec #508.
package libp2phttp

import (
Expand Down Expand Up @@ -39,7 +41,8 @@ type WellKnownProtocolMeta struct {

type WellKnownProtoMap map[protocol.ID]WellKnownProtocolMeta

type wellKnownHandler struct {
// WellKnownHandler is an http.Handler that serves the .well-known/libp2p resource
type WellKnownHandler struct {
wellknownMapMu sync.Mutex
wellKnownMapping WellKnownProtoMap
}
Expand All @@ -49,11 +52,7 @@ func StreamHostListen(streamHost host.Host) (net.Listener, error) {
return gostream.Listen(streamHost, ProtocolIDForMultistreamSelect)
}

func NewWellKnownHandler() wellKnownHandler {
return wellKnownHandler{wellKnownMapping: make(map[protocol.ID]WellKnownProtocolMeta)}
}

func (h *wellKnownHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (h *WellKnownHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Check if the requests accepts JSON
accepts := r.Header.Get("Accept")
if accepts != "" && !(strings.Contains(accepts, "application/json") || strings.Contains(accepts, "*/*")) {
Expand All @@ -78,21 +77,29 @@ func (h *wellKnownHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write(mapping)
}

func (h *wellKnownHandler) AddProtocolMapping(p protocol.ID, path string) {
func (h *WellKnownHandler) AddProtocolMapping(p protocol.ID, path string) {
h.wellknownMapMu.Lock()
if h.wellKnownMapping == nil {
h.wellKnownMapping = make(map[protocol.ID]WellKnownProtocolMeta)
}
h.wellKnownMapping[p] = WellKnownProtocolMeta{Path: path}
h.wellknownMapMu.Unlock()
}

func (h *wellKnownHandler) RmProtocolMapping(p protocol.ID, path string) {
func (h *WellKnownHandler) RmProtocolMapping(p protocol.ID, path string) {
h.wellknownMapMu.Lock()
delete(h.wellKnownMapping, p)
if h.wellKnownMapping != nil {
delete(h.wellKnownMapping, p)
}
h.wellknownMapMu.Unlock()
}

// HTTPHost is a libp2p host for request/responses with HTTP semantics. This is
// in contrast to a stream-oriented host like the host.Host interface. Warning,
// this is experimental. The API will likely change.
type HTTPHost struct {
rootHandler http.ServeMux
wk wellKnownHandler
wk WellKnownHandler
httpRoundTripper http.RoundTripper
recentHTTPAddrs *lru.Cache[peer.ID, httpAddr]
peerMetadata *lru.Cache[peer.ID, WellKnownProtoMap]
Expand All @@ -113,12 +120,12 @@ func New() *HTTPHost {
recentHTTP, err := lru.New[peer.ID, httpAddr](recentConnsLimit)
peerMetadata, err2 := lru.New[peer.ID, WellKnownProtoMap](PeerMetadataLRUSize)
if err != nil || err2 != nil {
// Only happens if size is < 1. We set it to 32, so this should never happen.
// Only happens if size is < 1. We make sure to not do that, so this should never happen.
panic(err)
}

h := &HTTPHost{
wk: NewWellKnownHandler(),
wk: WellKnownHandler{},
rootHandler: http.ServeMux{},
httpRoundTripper: http.DefaultTransport,
recentHTTPAddrs: recentHTTP,
Expand Down Expand Up @@ -270,6 +277,9 @@ func RoundTripperPreferHTTPTransport(o roundTripperOpts) roundTripperOpts {

type RoundTripperOptsFn func(o roundTripperOpts) roundTripperOpts

// NewRoundTripper returns an http.RoundTripper that can fulfill and HTTP
// request to the given server. It may use an HTTP transport or a stream based
// transport. It is valid to pass an empty server.ID and a nil streamHost.
func (h *HTTPHost) NewRoundTripper(streamHost host.Host, server peer.AddrInfo, opts ...RoundTripperOptsFn) (http.RoundTripper, error) {
options := roundTripperOpts{}
for _, o := range opts {
Expand Down Expand Up @@ -340,6 +350,9 @@ func (h *HTTPHost) NewRoundTripper(streamHost host.Host, server peer.AddrInfo, o
}

// Otherwise use a stream based transport
if streamHost == nil {
return nil, fmt.Errorf("no http addresses for peer, and no stream host provided")
}
if !existingStreamConn {
if server.ID == "" {
return nil, fmt.Errorf("no http addresses for peer, and no server peer ID provided")
Expand Down Expand Up @@ -398,7 +411,7 @@ func (h *HTTPHost) GetAndStorePeerProtoMap(roundtripper http.RoundTripper, serve
}
req.Header.Set("Accept", "application/json")

client := &http.Client{Transport: roundtripper}
client := http.Client{Transport: roundtripper}
resp, err := client.Do(req)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion p2p/http/libp2phttp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func TestRoundTrippers(t *testing.T) {
// TODO test with a native Go HTTP server
func TestPlainOldHTTPServer(t *testing.T) {
mux := http.NewServeMux()
wk := libp2phttp.NewWellKnownHandler()
wk := libp2phttp.WellKnownHandler{}
mux.Handle("/.well-known/libp2p", &wk)

mux.HandleFunc("/ping/", libp2phttp.Ping)
Expand Down

0 comments on commit 6f0fa81

Please sign in to comment.