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
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

event_stream.go 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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) {
  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.EventStart:
  59. observer.EventStart(typedEvt)
  60. case mtglib.EventConnectedToDC:
  61. observer.EventConnectedToDC(typedEvt)
  62. case mtglib.EventTraffic:
  63. observer.EventTraffic(typedEvt)
  64. case mtglib.EventFinish:
  65. observer.EventFinish(typedEvt)
  66. case mtglib.EventIPBlocklisted:
  67. observer.EventIPBlocklisted(typedEvt)
  68. case mtglib.EventConcurrencyLimited:
  69. observer.EventConcurrencyLimited(typedEvt)
  70. }
  71. }
  72. }
  73. }