Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ios: utilize engine handle at platform layer #327

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions library/common/include/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ load("@envoy//bazel:envoy_build_system.bzl", "envoy_cc_library", "envoy_package"

envoy_package()

envoy_cc_library(
name = "c_typedefs_interface",
hdrs = ["c_typedefs.h"],
repository = "@envoy",
)

envoy_cc_library(
name = "c_types_interface",
srcs = ["c_types.cc"],
hdrs = ["c_types.h"],
deps = ["c_typedefs_interface"],
repository = "@envoy",
)
27 changes: 27 additions & 0 deletions library/common/include/c_typedefs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

// NOLINT(namespace-envoy)

/**
* Handle to an Envoy engine instance. Valid only for the lifetime of the engine and not intended
* for any external interpretation or use.
*/
typedef uint64_t envoy_engine_t;

/**
* Handle to an outstanding Envoy HTTP stream. Valid only for the duration of the stream and not
* intended for any external interpretation or use.
*/
typedef uint64_t envoy_stream_t;


/**
* Result codes returned by all calls made to this interface.
*/
typedef enum { ENVOY_SUCCESS, ENVOY_FAILURE } envoy_status_t;

/**
* Error code associated with terminal status of a HTTP stream.
*/
typedef enum { ENVOY_STREAM_RESET } envoy_error_code_t;

24 changes: 2 additions & 22 deletions library/common/include/c_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,9 @@
#include <stdint.h>
#include <stdlib.h>

// NOLINT(namespace-envoy)

/**
* Handle to an Envoy engine instance. Valid only for the lifetime of the engine and not intended
* for any external interpretation or use.
*/
typedef uint64_t envoy_engine_t;

/**
* Handle to an outstanding Envoy HTTP stream. Valid only for the duration of the stream and not
* intended for any external interpretation or use.
*/
typedef uint64_t envoy_stream_t;
#include "library/common/include/c_typedefs.h"

/**
* Result codes returned by all calls made to this interface.
*/
typedef enum { ENVOY_SUCCESS, ENVOY_FAILURE } envoy_status_t;

/**
* Error code associated with terminal status of a HTTP stream.
*/
typedef enum { ENVOY_STREAM_RESET } envoy_error_code_t;
// NOLINT(namespace-envoy)

#ifdef __cplusplus
extern "C" { // release function
Expand Down
68 changes: 36 additions & 32 deletions library/objective-c/EnvoyEngine.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>

#import "library/common/include/c_typedefs.h"

NS_ASSUME_NONNULL_BEGIN

// MARK: - Aliases
Expand Down Expand Up @@ -59,44 +61,13 @@ typedef NSDictionary<NSString *, NSArray<NSString *> *> EnvoyHeaders;

@end

/// Wrapper layer for calling into Envoy's C/++ API.
@protocol EnvoyEngine

/**
Run the Envoy engine with the provided config and log level.

@param config The configuration file with which to start Envoy.
@return A status indicating if the action was successful.
*/
+ (int)runWithConfig:(NSString *)config;

/**
Run the Envoy engine with the provided config and log level.

@param config The configuration file with which to start Envoy.
@param logLevel The log level to use when starting Envoy.
@return A status indicating if the action was successful.
*/
+ (int)runWithConfig:(NSString *)config logLevel:(NSString *)logLevel;

/// Performs necessary setup after Envoy has initialized and started running.
/// TODO: create a post-initialization callback from Envoy to handle this automatically.
+ (void)setupEnvoy;

@end

// Concrete implementation of the `EnvoyEngine` protocol.
@interface EnvoyEngineImpl : NSObject <EnvoyEngine>

@end

@interface EnvoyHttpStream : NSObject
/**
Open an underlying HTTP stream.

@param observer the observer that will run the stream callbacks.
*/
- (instancetype)initWithObserver:(EnvoyObserver *)observer;
- (instancetype)initWithHandle:(envoy_stream_t)streamHandle observer:(EnvoyObserver *)observer;

/**
Send headers over the provided stream.
Expand Down Expand Up @@ -137,4 +108,37 @@ typedef NSDictionary<NSString *, NSArray<NSString *> *> EnvoyHeaders;

@end

/// Wrapper layer for calling into Envoy's C/++ API.
@protocol EnvoyEngine

/**
Run the Envoy engine with the provided config and log level.

@param config The configuration file with which to start Envoy.
@return A status indicating if the action was successful.
*/
- (int)runWithConfig:(NSString *)config;

/**
Run the Envoy engine with the provided config and log level.

@param config The configuration file with which to start Envoy.
@param logLevel The log level to use when starting Envoy.
@return A status indicating if the action was successful.
*/
- (int)runWithConfig:(NSString *)config logLevel:(NSString *)logLevel;

/// Performs necessary setup after Envoy has initialized and started running.
/// TODO: create a post-initialization callback from Envoy to handle this automatically.
- (void)setupEnvoy;

- (EnvoyHttpStream *)openHttpStreamWithObserver:(EnvoyObserver *)observer;

@end

// Concrete implementation of the `EnvoyEngine` protocol.
@interface EnvoyEngineImpl : NSObject <EnvoyEngine>

@end

NS_ASSUME_NONNULL_END
45 changes: 31 additions & 14 deletions library/objective-c/EnvoyEngine.m
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
#import "library/objective-c/EnvoyEngine.h"

#import "library/common/main_interface.h"
#import "library/common/include/c_types.h"

#import <stdatomic.h>

@implementation EnvoyObserver
@end

@implementation EnvoyEngineImpl
@implementation EnvoyEngineImpl {
envoy_engine_t _engineHandle;
}

- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
// TODO: _engineHandle = init_engine();
_engineHandle = 0;
return self;
}

#pragma mark - class methods
+ (int)runWithConfig:(NSString *)config {
- (int)runWithConfig:(NSString *)config {
return [self runWithConfig:config logLevel:@"info"];
}

+ (int)runWithConfig:(NSString *)config logLevel:(NSString *)logLevel {
- (int)runWithConfig:(NSString *)config logLevel:(NSString *)logLevel {
// Envoy exceptions will only be caught here when compiled for 64-bit arches.
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html
@try {
Expand All @@ -27,10 +37,16 @@ + (int)runWithConfig:(NSString *)config logLevel:(NSString *)logLevel {
}
}

+ (void)setupEnvoy {
- (void)setup {
// TODO: setup_envoy(_engineHandle);
setup_envoy();
}

- (EnvoyHttpStream *)openHttpStreamWithObserver:(EnvoyObserver *)observer {
// TODO: return [[EnvoyHttpStream alloc] initWithHandle:init_stream(_engineHandle) observer:observer];
return [[EnvoyHttpStream alloc] initWithHandle:0 observer:observer];
}

@end

#pragma mark - utility functions to move elsewhere
Expand Down Expand Up @@ -189,14 +205,15 @@ @implementation EnvoyHttpStream {
EnvoyHttpStream *_strongSelf;
EnvoyObserver *_platformObserver;
envoy_observer *_nativeObserver;
envoy_stream_t _nativeStream;
envoy_stream_t _streamHandle;
}

- (instancetype)initWithObserver:(EnvoyObserver *)observer {
- (instancetype)initWithHandle:(envoy_stream_t)streamHandle observer:(EnvoyObserver *)observer {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like this approach more than the original engine approach

This is a similar concept to what I was thinking about doing for the java side

Definitely can chat more tomorrow in case we think of a better solution

self = [super init];
if (!self) {
return nil;
}
_streamHandle = streamHandle;

// Retain platform observer
_platformObserver = observer;
Expand All @@ -215,11 +232,11 @@ - (instancetype)initWithObserver:(EnvoyObserver *)observer {
_nativeObserver = native_obs;

envoy_stream result = start_stream(*native_obs);
// TODO: envoy_status result = start_stream(_streamHandle, *native_obs);
if (result.status != ENVOY_SUCCESS) {
return nil;
}

_nativeStream = result.stream;
_strongSelf = self;
return self;
}
Expand All @@ -234,20 +251,20 @@ - (void)dealloc {
}

- (void)sendHeaders:(EnvoyHeaders *)headers close:(BOOL)close {
send_headers(_nativeStream, toNativeHeaders(headers), close);
send_headers(_streamHandle, toNativeHeaders(headers), close);
}

- (void)sendData:(NSData *)data close:(BOOL)close {
// TODO: implement
// send_data(_nativeStream, toNativeData(data), close);
// send_data(_streamHandle, toNativeData(data), close);
}

- (void)sendMetadata:(EnvoyHeaders *)metadata {
send_metadata(_nativeStream, toNativeHeaders(metadata));
send_metadata(_streamHandle, toNativeHeaders(metadata));
}

- (void)sendTrailers:(EnvoyHeaders *)trailers {
send_trailers(_nativeStream, toNativeHeaders(trailers));
send_trailers(_streamHandle, toNativeHeaders(trailers));
}

- (int)cancel {
Expand All @@ -258,7 +275,7 @@ - (int)cancel {
// Step 2: directly fire the cancel callback.
ios_on_cancel(context);
// Step 3: propagate the reset into native code.
reset_stream(_nativeStream);
reset_stream(_streamHandle);
return 0;
} else {
return 1;
Expand Down
12 changes: 8 additions & 4 deletions library/swift/src/Envoy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

@objcMembers
public final class Envoy: NSObject {
private let engine: EnvoyEngine
private let runner: RunnerThread

/// Indicates whether this Envoy instance is currently active and running.
Expand All @@ -18,22 +19,25 @@ public final class Envoy: NSObject {
///
/// - parameter config: Configuration file that is recognizable by Envoy (YAML).
/// - parameter logLevel: Log level to use for this instance.
public init(config: String, logLevel: LogLevel = .info) {
self.runner = RunnerThread(config: config, logLevel: logLevel)
public init(config: String, logLevel: LogLevel = .info, engine: EnvoyEngine = EnvoyEngineImpl()) {
self.engine = engine
self.runner = RunnerThread(config: config, logLevel: logLevel, engine: engine)
self.runner.start()
}

private final class RunnerThread: Thread {
private let engine: EnvoyEngine
private let config: String
private let logLevel: LogLevel

init(config: String, logLevel: LogLevel) {
init(config: String, logLevel: LogLevel, engine: EnvoyEngine) {
self.engine = engine
self.config = config
self.logLevel = logLevel
}

override func main() {
EnvoyEngineImpl.run(withConfig: self.config, logLevel: self.logLevel.stringValue)
self.engine.run(withConfig: self.config, logLevel: self.logLevel.stringValue)
}
}
}