Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

event_stream.go 2.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package events
  2. import (
  3. "context"
  4. "math/rand"
  5. "runtime"
  6. "github.com/9seconds/mtg/v2/mtglib"
  7. "github.com/OneOfOne/xxhash"
  8. )
  9. type eventStream struct {
  10. ctx context.Context
  11. ctxCancel context.CancelFunc
  12. chans []chan mtglib.Event
  13. }
  14. func (e eventStream) Send(ctx context.Context, evt mtglib.Event) {
  15. var chanNo uint32
  16. if streamID := evt.StreamID(); streamID != "" {
  17. chanNo = xxhash.ChecksumString32(streamID)
  18. } else {
  19. chanNo = rand.Uint32()
  20. }
  21. select {
  22. case <-ctx.Done():
  23. case <-e.ctx.Done():
  24. case e.chans[int(chanNo)%len(e.chans)] <- evt:
  25. }
  26. }
  27. func (e eventStream) Shutdown() {
  28. e.ctxCancel()
  29. }
  30. func NewEventStream(observerFactories []ObserverFactory) mtglib.EventStream {
  31. if len(observerFactories) == 0 {
  32. observerFactories = append(observerFactories, NewNoopObserver)
  33. }
  34. ctx, cancel := context.WithCancel(context.Background())
  35. rv := eventStream{
  36. ctx: ctx,
  37. ctxCancel: cancel,
  38. chans: make([]chan mtglib.Event, runtime.NumCPU()),
  39. }
  40. for i := 0; i < runtime.NumCPU(); i++ {
  41. rv.chans[i] = make(chan mtglib.Event, 1)
  42. if len(observerFactories) == 1 {
  43. go eventStreamProcessor(ctx, rv.chans[i], observerFactories[0]())
  44. } else {
  45. go eventStreamProcessor(ctx, rv.chans[i], newMultiObserver(observerFactories))
  46. }
  47. }
  48. return rv
  49. }
  50. func eventStreamProcessor(ctx context.Context, eventChan <-chan mtglib.Event, observer Observer) { // nolint: cyclop
  51. defer observer.Shutdown()
  52. for {
  53. select {
  54. case <-ctx.Done():
  55. return
  56. case evt := <-eventChan:
  57. switch typedEvt := evt.(type) {
  58. case mtglib.EventTraffic:
  59. observer.EventTraffic(typedEvt)
  60. case mtglib.EventStart:
  61. observer.EventStart(typedEvt)
  62. case mtglib.EventFinish:
  63. observer.EventFinish(typedEvt)
  64. case mtglib.EventConnectedToDC:
  65. observer.EventConnectedToDC(typedEvt)
  66. case mtglib.EventDomainFronting:
  67. observer.EventDomainFronting(typedEvt)
  68. case mtglib.EventIPBlocklisted:
  69. observer.EventIPBlocklisted(typedEvt)
  70. case mtglib.EventConcurrencyLimited:
  71. observer.EventConcurrencyLimited(typedEvt)
  72. }
  73. }
  74. }
  75. }