fizz/protocol/FizzBase.h (69 lines of code) (raw):
/*
* Copyright (c) 2018-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fizz/protocol/Factory.h>
#include <fizz/protocol/Params.h>
#include <fizz/util/Variant.h>
namespace fizz {
namespace detail {
#define FIZZ_PENDING_EVENT(F, ...) \
F(AppWrite, __VA_ARGS__) \
F(EarlyAppWrite, __VA_ARGS__) \
F(AppClose, __VA_ARGS__) \
F(WriteNewSessionTicket, __VA_ARGS__)
// `fizz::detail::PendingEvent` is declared here, rather than
// being declared as a private struct within `fizz::FizzBase` in order to
// work around an MSVC ICE.
//
// See https://github.com/facebookincubator/fizz/issues/59
FIZZ_DECLARE_VARIANT_TYPE(PendingEvent, FIZZ_PENDING_EVENT)
#undef FIZZ_PENDING_EVENT
} // namespace detail
/**
* FizzBase defines an async method of communicating with the fizz state
* machine. Given a const reference to state, and a reference to
* transportReadBuf, FizzBase will consume the transportReadBuf and process
* events as applicable. The buffer and allocation options given will be passed
* to the record layer to dictate its behavior. visitor is variant visitor that
* is expected to process Actions as they are received. A DestructorGuard on
* owner will be taken when async actions are in flight, during which time this
* class must not be deleted.
*/
template <typename Derived, typename ActionMoveVisitor, typename StateMachine>
class FizzBase {
public:
FizzBase(
const typename StateMachine::StateType& state,
folly::IOBufQueue& transportReadBuf,
Aead::AeadOptions& readAeadOptions,
ActionMoveVisitor& visitor,
folly::DelayedDestructionBase* owner)
: state_(state),
transportReadBuf_(transportReadBuf),
readAeadOptions_(readAeadOptions),
visitor_(visitor),
owner_(owner) {}
virtual ~FizzBase() = default;
/**
* Server only: Called to write new session ticket to client.
*/
void writeNewSessionTicket(WriteNewSessionTicket writeNewSessionTicket);
/**
* Called to write application data.
*/
void appWrite(AppWrite appWrite);
/**
* Called to write early application data.
*/
void earlyAppWrite(EarlyAppWrite appWrite);
/**
* Called when the application wants to close the connection, and wait for
* the corresponding peer's acknowledgement.
*/
void appClose();
/**
* Called when the application wants to immediately close the connection
* without waiting for the corresponding peer's acknowledgement.
*/
void appCloseImmediate();
/**
* Called to pause processing of transportReadBuf until new data is available.
*
* Call newTransportData() to resume processing.
*/
void waitForData();
/**
* Called to notify that new transport data is available in transportReadBuf.
*/
void newTransportData();
/**
* Calls error callbacks on any pending events and prevents any further events
* from being processed. Should be called when an error is received from
* either the state machine or the transport that will cause the connection to
* abort. Note that this does not stop a currently processing event.
*/
void moveToErrorState(const folly::AsyncSocketException& ex);
/**
* Pause the state machine from processing further events. Note that any event
* currently being processed will continue.
*/
void pause();
/**
* Resume processing events.
*/
void resume();
/**
* Returns true if in error state where no further events will be processed.
*/
bool inErrorState() const;
/**
* Returns true if in a terminal state where no further events will be
* processed.
*/
bool inTerminalState() const;
/**
* Returns true if the state machine is actively processing an event or
* action.
*/
bool actionProcessing() const;
/**
* Returns an exported key material derived from the 1-RTT secret of the TLS
* connection.
*/
Buf getExportedKeyingMaterial(
const Factory& factory,
folly::StringPiece label,
Buf context,
uint16_t length) const;
protected:
void processActions(typename StateMachine::CompletedActions actions);
void addProcessingActions(typename StateMachine::ProcessingActions actions);
virtual void visitActions(
typename StateMachine::CompletedActions& actions) = 0;
StateMachine machine_;
const typename StateMachine::StateType& state_;
folly::IOBufQueue& transportReadBuf_;
Aead::AeadOptions& readAeadOptions_;
ActionMoveVisitor& visitor_;
private:
void processPendingEvents();
folly::DelayedDestructionBase* owner_;
std::deque<detail::PendingEvent> pendingEvents_;
bool waitForData_{true};
folly::Optional<folly::DelayedDestruction::DestructorGuard> actionGuard_;
bool inProcessPendingEvents_{false};
bool externalError_{false};
bool paused_{false};
};
} // namespace fizz
#include <fizz/protocol/FizzBase-inl.h>