1
#pragma once
2

            
3
#include <cstdint>
4
#include <functional>
5
#include <memory>
6

            
7
#include "envoy/common/pure.h"
8

            
9
#include "absl/status/status.h"
10

            
11
namespace Envoy {
12
namespace Event {
13

            
14
struct FileReadyType {
15
  // File is ready for reading.
16
  static constexpr uint32_t Read = 0x1;
17
  // File is ready for writing.
18
  static constexpr uint32_t Write = 0x2;
19
  // File has been remote closed.
20
  static constexpr uint32_t Closed = 0x4;
21
};
22

            
23
enum class FileTriggerType {
24
  // See @man 7 epoll(7)
25
  // They are used on all platforms for DNS and TCP listeners.
26
  Level,
27
  // See @man 7 epoll(7)
28
  // They are used on all platforms that support Edge triggering as the default trigger type.
29
  Edge,
30
  // These are synthetic edge events managed by Envoy. They are based on level events and when they
31
  // are activated they are immediately disabled. This makes them behave like Edge events. Then it
32
  // is is the responsibility of the consumer of the event to reactivate the event
33
  // when the socket operation would block.
34
  //
35
  // Their main application in Envoy is for Win32 which does not support edge-triggered events. They
36
  // should be used in Win32 instead of level events. They can only be used in platforms where
37
  // `PlatformDefaultTriggerType` is `FileTriggerType::EmulatedEdge`.
38
  EmulatedEdge
39
};
40

            
41
// For POSIX developers to get the Windows behavior of file events
42
// you need to add the following definition:
43
// `FORCE_LEVEL_EVENTS`
44
// You can do this with bazel if you add the following build/test options
45
// `--copt="-DFORCE_LEVEL_EVENTS"`
46
constexpr FileTriggerType determinePlatformPreferredEventType() {
47
#if defined(WIN32) || defined(FORCE_LEVEL_EVENTS)
48
  return FileTriggerType::EmulatedEdge;
49
#else
50
  return FileTriggerType::Edge;
51
#endif
52
}
53

            
54
static constexpr FileTriggerType PlatformDefaultTriggerType = determinePlatformPreferredEventType();
55

            
56
/**
57
 * Callback invoked when a FileEvent is ready for reading or writing.
58
 */
59
using FileReadyCb = std::function<absl::Status(uint32_t events)>;
60

            
61
/**
62
 * Wrapper for file based (read/write) event notifications.
63
 */
64
class FileEvent {
65
public:
66
162463
  virtual ~FileEvent() = default;
67

            
68
  /**
69
   * Activate the file event explicitly for a set of events. Should be a logical OR of FileReadyType
70
   * events. This method "injects" the event (and fires callbacks) regardless of whether the event
71
   * is actually ready on the underlying file.
72
   */
73
  virtual void activate(uint32_t events) PURE;
74

            
75
  /**
76
   * Enable the file event explicitly for a set of events. Should be a logical OR of FileReadyType
77
   * events. As opposed to activate(), this routine causes the file event to listen for the
78
   * registered events and fire callbacks when they are active.
79
   */
80
  virtual void setEnabled(uint32_t events) PURE;
81

            
82
  /**
83
   * Add a single event from the event registration mark.
84
   */
85
  virtual void registerEventIfEmulatedEdge(uint32_t event) PURE;
86

            
87
  /**
88
   * Remove a single event from the event registration mark.
89
   */
90
  virtual void unregisterEventIfEmulatedEdge(uint32_t event) PURE;
91
};
92

            
93
using FileEventPtr = std::unique_ptr<FileEvent>;
94

            
95
} // namespace Event
96
} // namespace Envoy