github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/net/service/request.go (about) 1 package service 2 3 import ( 4 crand "crypto/rand" 5 6 msg "github.com/jbenet/go-ipfs/net/message" 7 pb "github.com/jbenet/go-ipfs/net/service/internal/pb" 8 peer "github.com/jbenet/go-ipfs/peer" 9 10 proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" 11 ) 12 13 const ( 14 // IDSize is the size of the ID in bytes. 15 IDSize int = 4 16 ) 17 18 // RequestID is a field that identifies request-response flows. 19 type RequestID []byte 20 21 // Request turns a RequestID into a Request (unsetting first bit) 22 func (r RequestID) Request() RequestID { 23 if r == nil { 24 return nil 25 } 26 r2 := make([]byte, len(r)) 27 copy(r2, r) 28 r2[0] = r[0] & 0x7F // unset first bit for request 29 return RequestID(r2) 30 } 31 32 // Response turns a RequestID into a Response (setting first bit) 33 func (r RequestID) Response() RequestID { 34 if r == nil { 35 return nil 36 } 37 r2 := make([]byte, len(r)) 38 copy(r2, r) 39 r2[0] = r[0] | 0x80 // set first bit for response 40 return RequestID(r2) 41 } 42 43 // IsRequest returns whether a RequestID identifies a request 44 func (r RequestID) IsRequest() bool { 45 if r == nil { 46 return false 47 } 48 return !r.IsResponse() 49 } 50 51 // IsResponse returns whether a RequestID identifies a response 52 func (r RequestID) IsResponse() bool { 53 if r == nil { 54 return false 55 } 56 return bool(r[0]&0x80 == 0x80) 57 } 58 59 // RandomRequestID creates and returns a new random request ID 60 func RandomRequestID() (RequestID, error) { 61 buf := make([]byte, IDSize) 62 _, err := crand.Read(buf) 63 return RequestID(buf).Request(), err 64 } 65 66 // RequestMap is a map of Requests. the key = (peer.ID concat RequestID). 67 type RequestMap map[string]*Request 68 69 // Request objects are used to multiplex request-response flows. 70 type Request struct { 71 72 // ID is the RequestID identifying this Request-Response Flow. 73 ID RequestID 74 75 // PeerID identifies the peer from whom to expect the response. 76 PeerID peer.ID 77 78 // Response is the channel of incoming responses. 79 Response chan msg.NetMessage 80 } 81 82 // NewRequest creates a request for given peer.ID 83 func NewRequest(pid peer.ID) (*Request, error) { 84 id, err := RandomRequestID() 85 if err != nil { 86 return nil, err 87 } 88 89 return &Request{ 90 ID: id, 91 PeerID: pid, 92 Response: make(chan msg.NetMessage, 1), 93 }, nil 94 } 95 96 // Key returns the RequestKey for this request. Use with maps. 97 func (r *Request) Key() string { 98 return RequestKey(r.PeerID, r.ID) 99 } 100 101 // RequestKey is the peer.ID concatenated with the RequestID. Use with maps. 102 func RequestKey(pid peer.ID, rid RequestID) string { 103 return string(pid) + string(rid.Request()[:]) 104 } 105 106 func wrapData(data []byte, rid RequestID) ([]byte, error) { 107 // Marshal 108 pbm := new(pb.PBRequest) 109 pbm.Data = data 110 pbm.Tag = rid 111 b, err := proto.Marshal(pbm) 112 if err != nil { 113 return nil, err 114 } 115 116 return b, nil 117 } 118 119 func unwrapData(data []byte) ([]byte, RequestID, error) { 120 // Unmarshal 121 pbm := new(pb.PBRequest) 122 err := proto.Unmarshal(data, pbm) 123 if err != nil { 124 return nil, nil, err 125 } 126 127 return pbm.GetData(), pbm.GetTag(), nil 128 }