Guest User

Untitled

a guest
Apr 25th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.01 KB | None | 0 0
  1. package kademlia
  2.  
  3. import (
  4. "container/heap";
  5. "container/vector";
  6. "fmt";
  7. "log";
  8. "http";
  9. "net";
  10. "os";
  11. "rpc";
  12. "sort";
  13. )
  14.  
  15. type Kademlia struct {
  16. routes *RoutingTable;
  17. NetworkId string;
  18. }
  19.  
  20. func NewKademlia(self *Contact, networkId string) (ret *Kademlia) {
  21. ret = new(Kademlia);
  22. ret.routes = NewRoutingTable(self);
  23. ret.NetworkId = networkId;
  24. return;
  25. }
  26.  
  27. func (k *Kademlia) Serve() (err os.Error) {
  28. rpc.Register(&KademliaCore{k});
  29.  
  30. rpc.HandleHTTP();
  31. if l, err := net.Listen("tcp", k.routes.node.address); err == nil {
  32. go http.Serve(l, nil);
  33. }
  34. return;
  35. }
  36.  
  37. func (k *Kademlia) Call(contact *Contact, method string, args, reply interface{}) (err os.Error) {
  38. if client, err := rpc.DialHTTP("tcp", contact.address); err == nil {
  39. err = client.Call(method, args, reply);
  40. if err == nil {
  41. k.routes.Update(contact);
  42. }
  43. }
  44. return;
  45. }
  46.  
  47. func (k *Kademlia) sendQuery(node *Contact, target NodeID, done chan []Contact) {
  48. args := FindNodeRequest{RPCHeader{&k.routes.node, k.NetworkId}, target};
  49. reply := FindNodeResponse{};
  50.  
  51. if err := k.Call(node, "KademliaCore.FindNode", &args, &reply); err == nil {
  52. done <- reply.contacts;
  53. } else {
  54. done <- []Contact{};
  55. }
  56. }
  57.  
  58. func (k *Kademlia) IterativeFindNode(target NodeID, delta int) (ret *vector.Vector) {
  59. done := make(chan []Contact);
  60.  
  61. // A vector of *ContactRecord structs
  62. ret = new(vector.Vector).Resize(0, BucketSize);
  63.  
  64. // A heap of not-yet-queried *Contact structs
  65. frontier := new(vector.Vector).Resize(0, BucketSize);
  66.  
  67. // A map of client values we've seen so far
  68. seen := make(map[string] bool);
  69.  
  70. // Initialize the return list, frontier heap, and seen list with local nodes
  71. for node := range k.routes.FindClosest(target, delta).Iter() {
  72. record := node.(*ContactRecord);
  73. ret.Push(record);
  74. heap.Push(frontier, record.node);
  75. seen[record.node.id.String()] = true;
  76. }
  77.  
  78. // Start off delta queries
  79. pending := 0;
  80. for i := 0; i < delta && frontier.Len() > 0; i++ {
  81. pending++;
  82. go k.sendQuery(frontier.Pop().(*Contact), target, done);
  83. }
  84.  
  85. // Iteratively look for closer nodes
  86. for pending > 0 {
  87. nodes := <-done;
  88. pending--;
  89. for _, node := range nodes {
  90. // If we haven't seen the node before, add it
  91. if _, ok := seen[node.id.String()]; ok == false {
  92. ret.Push(&ContactRecord{&node, node.id.Xor(target)});
  93. heap.Push(frontier, node);
  94. seen[node.id.String()] = true;
  95. }
  96. }
  97.  
  98. for pending < delta && frontier.Len() > 0 {
  99. go k.sendQuery(frontier.Pop().(*Contact), target, done);
  100. pending++;
  101. }
  102. }
  103.  
  104. sort.Sort(ret);
  105. if ret.Len() > BucketSize {
  106. ret.Cut(BucketSize, ret.Len());
  107. }
  108.  
  109. return;
  110. }
  111.  
  112. type RPCHeader struct {
  113. Sender *Contact;
  114. NetworkId string;
  115. }
  116.  
  117. func (k *Kademlia) HandleRPC(request, response *RPCHeader) os.Error {
  118. if request.NetworkId != k.NetworkId {
  119. return os.NewError(fmt.Sprintf("Expected network ID %s, got %s",
  120. k.NetworkId, request.NetworkId));
  121. }
  122. if request.Sender != nil {
  123. k.routes.Update(request.Sender);
  124. }
  125. response.Sender = &k.routes.node;
  126. return nil;
  127. }
  128.  
  129. type KademliaCore struct {
  130. kad *Kademlia;
  131. }
  132.  
  133. type PingRequest struct {
  134. RPCHeader;
  135. }
  136.  
  137. type PingResponse struct {
  138. RPCHeader;
  139. }
  140.  
  141. func (kc *KademliaCore) Ping(args *PingRequest, response *PingResponse) (err os.Error) {
  142. if err = kc.kad.HandleRPC(&args.RPCHeader, &response.RPCHeader); err == nil {
  143. log.Stderr("Ping from %s\n", args.RPCHeader);
  144. }
  145. return;
  146. }
  147.  
  148. type FindNodeRequest struct {
  149. RPCHeader;
  150. target NodeID;
  151. }
  152.  
  153. type FindNodeResponse struct {
  154. RPCHeader;
  155. contacts []Contact;
  156. }
  157.  
  158. func (kc *KademliaCore) FindNode(args *FindNodeRequest, response *FindNodeResponse) (err os.Error) {
  159. if err = kc.kad.HandleRPC(&args.RPCHeader, &response.RPCHeader); err == nil {
  160. contacts := kc.kad.routes.FindClosest(args.target, BucketSize);
  161. response.contacts = make([]Contact, contacts.Len());
  162.  
  163. for i := 0; i < contacts.Len(); i++ {
  164. response.contacts[i] = *contacts.At(i).(*ContactRecord).node;
  165. }
  166. }
  167. return;
  168. }
Add Comment
Please, Sign In to add comment