ltep.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package torrent
  2. import (
  3. "fmt"
  4. "slices"
  5. g "github.com/anacrolix/generics"
  6. pp "github.com/anacrolix/torrent/peer_protocol"
  7. )
  8. type LocalLtepProtocolMap struct {
  9. // 1-based mapping from extension number to extension name (subtract one from the extension ID
  10. // to find the corresponding protocol name). The first LocalLtepProtocolBuiltinCount of these
  11. // are use builtin handlers. If you want to handle builtin protocols yourself, you would move
  12. // them above the threshold. You can disable them by removing them entirely, and add your own.
  13. // These changes should be done in the PeerConnAdded callback.
  14. Index []pp.ExtensionName
  15. // How many of the protocols are using the builtin handlers.
  16. NumBuiltin int
  17. }
  18. func (me *LocalLtepProtocolMap) toSupportedExtensionDict() (m map[pp.ExtensionName]pp.ExtensionNumber) {
  19. g.MakeMapWithCap(&m, len(me.Index))
  20. for i, name := range me.Index {
  21. old := g.MapInsert(m, name, pp.ExtensionNumber(i+1))
  22. if old.Ok {
  23. panic(fmt.Sprintf("extension %q already defined with id %v", name, old.Value))
  24. }
  25. }
  26. return
  27. }
  28. // Returns the local extension name for the given ID. If builtin is true, the implementation intends
  29. // to handle it itself. For incoming messages with extension ID 0, the message is a handshake, and
  30. // should be treated specially.
  31. func (me *LocalLtepProtocolMap) LookupId(id pp.ExtensionNumber) (name pp.ExtensionName, builtin bool, err error) {
  32. if id == 0 {
  33. err = fmt.Errorf("extension ID 0 is handshake")
  34. builtin = true
  35. return
  36. }
  37. protocolIndex := int(id - 1)
  38. if protocolIndex >= len(me.Index) {
  39. err = fmt.Errorf("unexpected extended message ID: %v", id)
  40. return
  41. }
  42. builtin = protocolIndex < me.NumBuiltin
  43. name = me.Index[protocolIndex]
  44. return
  45. }
  46. func (me *LocalLtepProtocolMap) builtin() []pp.ExtensionName {
  47. return me.Index[:me.NumBuiltin]
  48. }
  49. func (me *LocalLtepProtocolMap) user() []pp.ExtensionName {
  50. return me.Index[me.NumBuiltin:]
  51. }
  52. func (me *LocalLtepProtocolMap) AddUserProtocol(name pp.ExtensionName) {
  53. builtin := slices.DeleteFunc(me.builtin(), func(delName pp.ExtensionName) bool {
  54. return delName == name
  55. })
  56. user := slices.DeleteFunc(me.user(), func(delName pp.ExtensionName) bool {
  57. return delName == name
  58. })
  59. me.Index = append(append(builtin, user...), name)
  60. me.NumBuiltin = len(builtin)
  61. }