1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-09-17 21:06:18 +08:00
Files
kubo/net/service/request.go
Brian Tiger Chow add0f3f935 feat(net:message) get net package from e2430ae4279
fix(net:msg) use vendored imports
2014-09-22 04:05:13 -07:00

128 lines
2.8 KiB
Go

package service
import (
crand "crypto/rand"
msg "github.com/jbenet/go-ipfs/net/message"
peer "github.com/jbenet/go-ipfs/peer"
proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
)
const (
// IDSize is the size of the ID in bytes.
IDSize int = 4
)
// RequestID is a field that identifies request-response flows.
type RequestID []byte
// Request turns a RequestID into a Request (unsetting first bit)
func (r RequestID) Request() RequestID {
if r == nil {
return nil
}
r2 := make([]byte, len(r))
copy(r2, r)
r2[0] = r[0] & 0x7F // unset first bit for request
return RequestID(r2)
}
// Response turns a RequestID into a Response (setting first bit)
func (r RequestID) Response() RequestID {
if r == nil {
return nil
}
r2 := make([]byte, len(r))
copy(r2, r)
r2[0] = r[0] | 0x80 // set first bit for response
return RequestID(r2)
}
// IsRequest returns whether a RequestID identifies a request
func (r RequestID) IsRequest() bool {
if r == nil {
return false
}
return !r.IsResponse()
}
// IsResponse returns whether a RequestID identifies a response
func (r RequestID) IsResponse() bool {
if r == nil {
return false
}
return bool(r[0]&0x80 == 0x80)
}
// RandomRequestID creates and returns a new random request ID
func RandomRequestID() (RequestID, error) {
buf := make([]byte, IDSize)
_, err := crand.Read(buf)
return RequestID(buf).Request(), err
}
// RequestMap is a map of Requests. the key = (peer.ID concat RequestID).
type RequestMap map[string]*Request
// Request objects are used to multiplex request-response flows.
type Request struct {
// ID is the RequestID identifying this Request-Response Flow.
ID RequestID
// PeerID identifies the peer from whom to expect the response.
PeerID peer.ID
// Response is the channel of incoming responses.
Response chan msg.NetMessage
}
// NewRequest creates a request for given peer.ID
func NewRequest(pid peer.ID) (*Request, error) {
id, err := RandomRequestID()
if err != nil {
return nil, err
}
return &Request{
ID: id,
PeerID: pid,
Response: make(chan msg.NetMessage, 1),
}, nil
}
// Key returns the RequestKey for this request. Use with maps.
func (r *Request) Key() string {
return RequestKey(r.PeerID, r.ID)
}
// RequestKey is the peer.ID concatenated with the RequestID. Use with maps.
func RequestKey(pid peer.ID, rid RequestID) string {
return string(pid) + string(rid.Request()[:])
}
func wrapData(data []byte, rid RequestID) ([]byte, error) {
// Marshal
pbm := new(PBRequest)
pbm.Data = data
pbm.Tag = rid
b, err := proto.Marshal(pbm)
if err != nil {
return nil, err
}
return b, nil
}
func unwrapData(data []byte) ([]byte, RequestID, error) {
// Unmarshal
pbm := new(PBRequest)
err := proto.Unmarshal(data, pbm)
if err != nil {
return nil, nil, err
}
return pbm.GetData(), pbm.GetTag(), nil
}