1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/buffer/buffer.h"
6
#include "envoy/event/dispatcher.h"
7

            
8
#include "source/common/common/c_smart_ptr.h"
9
#include "source/extensions/transport_sockets/alts/alts_tsi_handshaker.h"
10
#include "source/extensions/transport_sockets/alts/grpc_tsi.h"
11

            
12
#include "absl/status/status.h"
13

            
14
namespace Envoy {
15
namespace Extensions {
16
namespace TransportSockets {
17
namespace Alts {
18

            
19
/**
20
 * An interface to get callbacks from TsiHandshaker. TsiHandshaker will call this callbacks in the
21
 * thread which its dispatcher posts to.
22
 */
23
class TsiHandshakerCallbacks {
24
public:
25
60
  virtual ~TsiHandshakerCallbacks() = default;
26

            
27
  struct NextResult {
28
    // A status of the result.
29
    absl::Status status_;
30

            
31
    // The buffer to be sent to the peer.
32
    Buffer::InstancePtr to_send_;
33

            
34
    // A pointer to AltsHandshakeResult. Owned by instance.
35
    std::unique_ptr<AltsHandshakeResult> result_;
36
  };
37

            
38
  using NextResultPtr = std::unique_ptr<NextResult>;
39

            
40
  /**
41
   * Called when `next` is done, this may be called inline in `next` if the handshaker is not
42
   * asynchronous.
43
   * @param result a unique pointer to NextResult struct including the result returned by TSI.
44
   */
45
  virtual void onNextDone(NextResultPtr&& result) PURE;
46
};
47

            
48
/**
49
 * A C++ wrapper for tsi_handshaker interface.
50
 * For detail of tsi_handshaker, see
51
 * https://github.com/grpc/grpc/blob/v1.12.0/src/core/tsi/transport_security_interface.h#L236
52
 */
53
class TsiHandshaker final : public Event::DeferredDeletable {
54
public:
55
  explicit TsiHandshaker(std::unique_ptr<AltsTsiHandshaker> handshaker,
56
                         Event::Dispatcher& dispatcher);
57
  ~TsiHandshaker() override;
58

            
59
  /**
60
   * Conduct next step of handshake, see
61
   * https://github.com/grpc/grpc/blob/v1.12.0/src/core/tsi/transport_security_interface.h#L418
62
   * It is callers responsibility to not call this method again until the
63
   * TsiHandshakerCallbacks::onNextDone is called.
64
   * @param received the buffer received from peer.
65
   */
66
  absl::Status next(Buffer::Instance& received);
67

            
68
  /**
69
   * Set handshaker callbacks. This must be called before calling next.
70
   * @param callbacks supplies the callback instance.
71
   */
72
45
  void setHandshakerCallbacks(TsiHandshakerCallbacks& callbacks) { callbacks_ = &callbacks; }
73

            
74
  /**
75
   * Delete the handshaker when it is ready. This must be called after releasing from a smart
76
   * pointer. If there is no call in progress, this calls dispatcher_.deferredDelete(). If there is
77
   * a call in progress dispatcher_.deferredDelete happens after ongoing next call are processed.
78
   */
79
  void deferredDelete();
80

            
81
private:
82
  static void onNextDone(absl::Status status, void* handshaker, const unsigned char* bytes_to_send,
83
                         size_t bytes_to_send_size,
84
                         std::unique_ptr<AltsHandshakeResult> handshake_result);
85

            
86
  std::unique_ptr<AltsTsiHandshaker> handshaker_;
87
  TsiHandshakerCallbacks* callbacks_{};
88

            
89
  // This is set to true when there is an ongoing next call to handshaker, and set to false when
90
  // the callback posted to dispatcher_ by TsiHandshaker::onNextDone is executed.
91
  bool calling_{false};
92

            
93
  // This will be set when deferredDelete is called. If there is an ongoing next call,
94
  // the handshaker will delete itself after the call is processed.
95
  bool delete_on_done_{false};
96

            
97
  Event::Dispatcher& dispatcher_;
98
};
99

            
100
using TsiHandshakerPtr = std::unique_ptr<TsiHandshaker>;
101

            
102
} // namespace Alts
103
} // namespace TransportSockets
104
} // namespace Extensions
105
} // namespace Envoy