/** * Copyright © 2016-2017 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.thingsboard.server.actors.rpc; import akka.event.Logging; import akka.event.LoggingAdapter; import io.grpc.Channel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.StreamObserver; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.service.ContextAwareActor; import org.thingsboard.server.actors.service.ContextBasedCreator; import org.thingsboard.server.common.msg.cluster.ServerAddress; import org.thingsboard.server.gen.cluster.ClusterAPIProtos; import org.thingsboard.server.gen.cluster.ClusterRpcServiceGrpc; import org.thingsboard.server.service.cluster.rpc.GrpcSession; import org.thingsboard.server.service.cluster.rpc.GrpcSessionListener; import java.util.UUID; /** * @author Andrew Shvayka */ public class RpcSessionActor extends ContextAwareActor { private final LoggingAdapter log = Logging.getLogger(getContext().system(), this); private final UUID sessionId; private GrpcSession session; private GrpcSessionListener listener; public RpcSessionActor(ActorSystemContext systemContext, UUID sessionId) { super(systemContext); this.sessionId = sessionId; } @Override public void onReceive(Object msg) throws Exception { if (msg instanceof RpcSessionTellMsg) { tell((RpcSessionTellMsg) msg); } else if (msg instanceof RpcSessionCreateRequestMsg) { initSession((RpcSessionCreateRequestMsg) msg); } } private void tell(RpcSessionTellMsg msg) { session.sendMsg(msg.getMsg()); } @Override public void postStop() { log.info("Closing session -> {}", session.getRemoteServer()); session.close(); } private void initSession(RpcSessionCreateRequestMsg msg) { log.info("[{}] Initializing session", context().self()); ServerAddress remoteServer = msg.getRemoteAddress(); listener = new BasicRpcSessionListener(systemContext, context().parent(), context().self()); if (msg.getRemoteAddress() == null) { // Server session session = new GrpcSession(listener); session.setOutputStream(msg.getResponseObserver()); session.initInputStream(); session.initOutputStream(); systemContext.getRpcService().onSessionCreated(msg.getMsgUid(), session.getInputStream()); } else { // Client session Channel channel = ManagedChannelBuilder.forAddress(remoteServer.getHost(), remoteServer.getPort()).usePlaintext(true).build(); session = new GrpcSession(remoteServer, listener); session.initInputStream(); ClusterRpcServiceGrpc.ClusterRpcServiceStub stub = ClusterRpcServiceGrpc.newStub(channel); StreamObserver<ClusterAPIProtos.ToRpcServerMessage> outputStream = stub.handlePluginMsgs(session.getInputStream()); session.setOutputStream(outputStream); session.initOutputStream(); outputStream.onNext(toConnectMsg()); } } public static class ActorCreator extends ContextBasedCreator<RpcSessionActor> { private static final long serialVersionUID = 1L; private final UUID sessionId; public ActorCreator(ActorSystemContext context, UUID sessionId) { super(context); this.sessionId = sessionId; } @Override public RpcSessionActor create() throws Exception { return new RpcSessionActor(context, sessionId); } } private ClusterAPIProtos.ToRpcServerMessage toConnectMsg() { ServerAddress instance = systemContext.getDiscoveryService().getCurrentServer().getServerAddress(); return ClusterAPIProtos.ToRpcServerMessage.newBuilder().setConnectMsg( ClusterAPIProtos.ConnectRpcMessage.newBuilder().setServerAddress( ClusterAPIProtos.ServerAddress.newBuilder().setHost(instance.getHost()).setPort(instance.getPort()).build()).build()).build(); } }