![JAR search and dependency download from the Maven repository](/logo.png)
io.vertx.grpcio.server.impl.GrpcIoServiceBridgeImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2011-2022 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.grpcio.server.impl;
import io.grpc.Attributes;
import io.grpc.Context;
import io.grpc.Compressor;
import io.grpc.CompressorRegistry;
import io.grpc.Decompressor;
import io.grpc.DecompressorRegistry;
import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerMethodDefinition;
import io.grpc.ServerServiceDefinition;
import io.grpc.Status;
import io.vertx.core.Vertx;
import io.vertx.core.net.SocketAddress;
import io.vertx.grpc.common.GrpcError;
import io.vertx.grpc.common.GrpcStatus;
import io.vertx.grpc.common.impl.*;
import io.vertx.grpc.server.GrpcServerRequest;
import io.vertx.grpc.server.GrpcServerResponse;
import io.vertx.grpc.server.impl.GrpcServerResponseImpl;
import io.vertx.grpcio.common.impl.BridgeMessageDecoder;
import io.vertx.grpcio.common.impl.BridgeMessageEncoder;
import io.vertx.grpcio.common.impl.ReadStreamAdapter;
import io.vertx.grpcio.server.GrpcIoServer;
import io.vertx.grpcio.server.GrpcIoServiceBridge;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
public class GrpcIoServiceBridgeImpl implements GrpcIoServiceBridge {
private final ServerServiceDefinition serviceDef;
public GrpcIoServiceBridgeImpl(ServerServiceDefinition serviceDef) {
this.serviceDef = serviceDef;
}
@Override
public void unbind(GrpcIoServer server) {
serviceDef.getMethods().forEach(m -> unbind(server, m));
}
private void unbind(GrpcIoServer server, ServerMethodDefinition methodDef) {
server.callHandler(methodDef.getMethodDescriptor(), null);
}
@Override
public void bind(GrpcIoServer server) {
serviceDef.getMethods().forEach(m -> bind(server, m));
}
private void bind(GrpcIoServer server, ServerMethodDefinition methodDef) {
server.callHandler(methodDef.getMethodDescriptor(), req -> {
ServerCallHandler callHandler = methodDef.getServerCallHandler();
Context context = Context.current();
if (req.timeout() > 0L) {
Context.CancellableContext cancellable = context.withDeadlineAfter(req.timeout(), TimeUnit.MILLISECONDS, new VertxScheduledExecutorService(Vertx.currentContext()));
context = cancellable;
context.addListener(context1 -> ((GrpcServerResponseImpl)req.response()).handleTimeout(), new Executor() {
@Override
public void execute(Runnable command) {
command.run();
}
});
}
Context theContext = context;
Runnable task = theContext.wrap(() -> {
ServerCallImpl call = new ServerCallImpl<>(theContext, req, methodDef);
ServerCall.Listener listener = callHandler.startCall(call, io.vertx.grpcio.common.impl.Utils.readMetadata(req.headers()));
call.init(listener);
});
task.run();
});
}
private static class ServerCallImpl extends ServerCall {
private final Context context;
private final GrpcServerRequest req;
private final ServerMethodDefinition methodDef;
private final ReadStreamAdapter readAdapter;
private final WriteStreamAdapter writeAdapter;
private ServerCall.Listener listener;
private final Decompressor decompressor;
private Compressor compressor;
private boolean halfClosed;
private boolean closed;
private int messagesSent;
private final Attributes attributes;
public ServerCallImpl(Context context, GrpcServerRequest req, ServerMethodDefinition methodDef) {
String encoding = req.encoding();
this.context = context;
this.decompressor = DecompressorRegistry.getDefaultInstance().lookupDecompressor(encoding);
this.req = req;
this.methodDef = methodDef;
this.readAdapter = new ReadStreamAdapter() {
@Override
protected void handleClose() {
halfClosed = true;
Context previous = context.attach();
try {
listener.onHalfClose();
} finally {
context.detach(previous);
}
}
@Override
protected void handleMessage(Req msg) {
Context previous = context.attach();
try {
listener.onMessage(msg);
} finally {
context.detach(previous);
}
}
};
this.writeAdapter = new WriteStreamAdapter() {
@Override
protected void handleReady() {
Context previous = context.attach();
try {
listener.onReady();
} finally {
context.detach(previous);
}
}
};
this.attributes = createAttributes();
}
void init(ServerCall.Listener listener) {
this.listener = listener;
req.errorHandler(error -> {
if (error == GrpcError.CANCELLED && !closed) {
listener.onCancel();
}
});
readAdapter.init(req, new BridgeMessageDecoder<>(methodDef.getMethodDescriptor().getRequestMarshaller(), decompressor));
writeAdapter.init(req.response(), new BridgeMessageEncoder<>(methodDef.getMethodDescriptor().getResponseMarshaller(), compressor));
}
private Attributes createAttributes() {
Attributes.Builder builder = Attributes.newBuilder();
SocketAddress remoteAddr = req.connection().remoteAddress();
if (remoteAddr != null && remoteAddr.isInetSocket()) {
try {
InetAddress address = InetAddress.getByName(remoteAddr.hostAddress());
builder.set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, new InetSocketAddress(address, remoteAddr.port()));
} catch (UnknownHostException ignored) {
}
}
SocketAddress localAddr = req.connection().localAddress();
if (localAddr != null && localAddr.isInetSocket()) {
try {
InetAddress address = InetAddress.getByName(localAddr.hostAddress());
builder.set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, new InetSocketAddress(address, localAddr.port()));
} catch (UnknownHostException ignored) {
}
}
if (req.connection().isSsl()) {
builder.set(Grpc.TRANSPORT_ATTR_SSL_SESSION, req.connection().sslSession());
}
return builder.build();
}
@Override
public boolean isReady() {
return writeAdapter.isReady();
}
@Override
public void request(int numMessages) {
readAdapter.request(numMessages);
}
@Override
public void sendHeaders(Metadata headers) {
io.vertx.grpcio.common.impl.Utils.writeMetadata(headers, req.response().headers());
}
@Override
public void sendMessage(Resp message) {
messagesSent++;
writeAdapter.write(message);
}
@Override
public void close(Status status, Metadata trailers) {
if (closed) {
throw new IllegalStateException("Already closed");
}
closed = true;
GrpcServerResponse response = req.response();
if (status == Status.OK && methodDef.getMethodDescriptor().getType().serverSendsOneMessage() && messagesSent == 0) {
response.status(GrpcStatus.UNAVAILABLE).end();
} else {
io.vertx.grpcio.common.impl.Utils.writeMetadata(trailers, response.trailers());
response.status(GrpcStatus.valueOf(status.getCode().value()));
response.statusMessage(status.getDescription());
response.end();
}
listener.onComplete();
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public MethodDescriptor getMethodDescriptor() {
return methodDef.getMethodDescriptor();
}
@Override
public void setCompression(String encoding) {
compressor = CompressorRegistry.getDefaultInstance().lookupCompressor(encoding);
req.response().encoding(encoding);
}
@Override
public void setMessageCompression(boolean enabled) {
// ????
super.setMessageCompression(enabled);
}
@Override
public Attributes getAttributes() {
return this.attributes;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy