1
#include "source/extensions/io_socket/user_space/file_event_impl.h"
2

            
3
#include "source/common/common/assert.h"
4
#include "source/extensions/io_socket/user_space/io_handle.h"
5

            
6
namespace Envoy {
7
namespace Extensions {
8
namespace IoSocket {
9
namespace UserSpace {
10

            
11
FileEventImpl::FileEventImpl(Event::Dispatcher& dispatcher, Event::FileReadyCb cb, uint32_t events,
12
                             IoHandle& io_source)
13
294
    : schedulable_(dispatcher.createSchedulableCallback([this, cb]() {
14
291
        auto ephemeral_events = event_listener_.getAndClearEphemeralEvents();
15
291
        ENVOY_LOG(trace, "User space event {} invokes callbacks on events = {}",
16
291
                  static_cast<void*>(this), ephemeral_events);
17
291
        THROW_IF_NOT_OK(cb(ephemeral_events));
18
291
      })),
19
88
      io_source_(io_source) {
20
88
  setEnabled(events);
21
88
}
22

            
23
375
void FileEventImpl::activate(uint32_t events) {
24
  // Only supported event types are set.
25
375
  ASSERT((events & (Event::FileReadyType::Read | Event::FileReadyType::Write |
26
375
                    Event::FileReadyType::Closed)) == events);
27
375
  event_listener_.onEventActivated(events);
28
375
  schedulable_->scheduleCallbackNextIteration();
29
375
}
30

            
31
151
void FileEventImpl::setEnabled(uint32_t events) {
32
  // Only supported event types are set.
33
151
  ASSERT((events & (Event::FileReadyType::Read | Event::FileReadyType::Write |
34
151
                    Event::FileReadyType::Closed)) == events);
35
  // Align with Event::FileEventImpl. Clear pending events on updates to the fd event mask to avoid
36
  // delivering events that are no longer relevant.
37
151
  event_listener_.clearEphemeralEvents();
38
151
  event_listener_.setEnabledEvents(events);
39
151
  bool was_enabled = schedulable_->enabled();
40
  // Recalculate activated events.
41
151
  uint32_t events_to_notify = 0;
42
151
  if ((events & Event::FileReadyType::Read) && (io_source_.isReadable() ||
43
                                                // Notify Read event when end-of-stream is received.
44
110
                                                io_source_.hasReceivedEof())) {
45
23
    events_to_notify |= Event::FileReadyType::Read;
46
23
  }
47
151
  if ((events & Event::FileReadyType::Write) && io_source_.isWritable()) {
48
114
    events_to_notify |= Event::FileReadyType::Write;
49
114
  }
50
151
  if ((events & Event::FileReadyType::Closed) && io_source_.hasReceivedEof()) {
51
6
    events_to_notify |= Event::FileReadyType::Closed;
52
6
  }
53
151
  if (events_to_notify != 0) {
54
125
    activate(events_to_notify);
55
127
  } else {
56
26
    schedulable_->cancel();
57
26
  }
58
151
  ENVOY_LOG(
59
151
      trace,
60
151
      "User space file event {} set enabled events {} and events {} is active. Will {}reschedule.",
61
151
      static_cast<void*>(this), events, events_to_notify, was_enabled ? "not " : "");
62
151
}
63

            
64
120
void FileEventImpl::activateIfEnabled(uint32_t events) {
65
120
  ASSERT((events & (Event::FileReadyType::Read | Event::FileReadyType::Write |
66
120
                    Event::FileReadyType::Closed)) == events);
67
  // Filter out disabled events.
68
120
  uint32_t filtered_events = events & event_listener_.getEnabledEvents();
69
120
  if (filtered_events == 0) {
70
11
    return;
71
11
  }
72
109
  activate(filtered_events);
73
109
}
74
} // namespace UserSpace
75
} // namespace IoSocket
76
} // namespace Extensions
77
} // namespace Envoy