struct Options {
std::string tlsPEMKeyFile;
std::string tlsCAFile;
};
auto certificateConfigCallback(void* options, grpc_ssl_server_certificate_config** config) {
// Return `GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED` if not changed.
// Return `GRPC_SSL_ROOTS_OVERRIDE_FAIL` if loading (or verifying) the certificates fails.
// Otherwise, load the new certificates ...
Options* optionsPtr = reinterpret_cast<Options*>(options);
std::string caCert = util::readPEMFile(optionsPtr->tlsCAFile);
auto keyCertPair = util::parsePEMKeyFile(optionsPtr->tlsPEMKeyFile);
grpc_ssl_pem_key_cert_pair pemKeyCertPair = {keyCertPair.private_key.c_str(),
keyCertPair.cert_chain.c_str()};
*config = grpc_ssl_server_certificate_config_create(caCert.c_str(), &pemKeyCertPair, 1);
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW;
}
auto makeServerCredentialsWithFetcher() {
Options options;
grpc_ssl_server_credentials_options* opts =
grpc_ssl_server_credentials_create_options_using_config_fetcher(
::grpc_ssl_client_certificate_request_type::GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
certificateConfigCallback,
&options);
grpc_server_credentials* creds = grpc_ssl_server_credentials_create_with_options(opts);
return std::shared_ptr<::grpc::ServerCredentials>(new ::grpc::SecureServerCredentials(creds));
}
void startServer() {
::grpc::ServerBuilder builder;
auto credentials = makeServerCredentialsWithFetcher();
// TODO register service via `builder.RegisterService()`
builder.SetMaxReceiveMessageSize(MaxMessageSizeBytes);
builder.SetMaxSendMessageSize(MaxMessageSizeBytes);
builder.SetDefaultCompressionAlgorithm(::grpc_compression_algorithm::GRPC_COMPRESS_NONE);
::grpc::ResourceQuota quota;
quota.SetMaxThreads(MaxWorkerThreads);
builder.SetResourceQuota(quota);
server = builder.BuildAndStart();
}