├── src └── main │ ├── java │ └── com │ │ └── ibyte │ │ └── iot │ │ ├── tcp │ │ ├── remoting │ │ │ ├── Sender.java │ │ │ └── TcpSender.java │ │ ├── invoke │ │ │ └── ApiProxy.java │ │ ├── connector │ │ │ ├── Connection.java │ │ │ ├── Connector.java │ │ │ ├── tcp │ │ │ │ ├── ExchangeTcpSessionManager.java │ │ │ │ ├── codec │ │ │ │ │ ├── MessageBuf.proto │ │ │ │ │ ├── ProtobufAdapter.java │ │ │ │ │ └── MessageBuf.java │ │ │ │ ├── config │ │ │ │ │ └── ServerTransportConfig.java │ │ │ │ ├── server │ │ │ │ │ ├── ServerChannelInitializer.java │ │ │ │ │ ├── TcpServer.java │ │ │ │ │ └── TcpServerHandler.java │ │ │ │ ├── ExchangeTcpConnector.java │ │ │ │ ├── NoKeepAliveTcpConnection.java │ │ │ │ ├── TcpSessionManager.java │ │ │ │ ├── TcpConnector.java │ │ │ │ ├── listener │ │ │ │ │ └── TcpHeartbeatListener.java │ │ │ │ └── TcpConnection.java │ │ │ ├── api │ │ │ │ ├── listener │ │ │ │ │ ├── LogSessionListener.java │ │ │ │ │ ├── SessionEvent.java │ │ │ │ │ └── SessionListener.java │ │ │ │ ├── ExchangeConnection.java │ │ │ │ ├── ExchangeConnector.java │ │ │ │ ├── ExchangeSessionManager.java │ │ │ │ ├── SessionValid.java │ │ │ │ └── ExchangeSession.java │ │ │ ├── Session.java │ │ │ └── SessionManager.java │ │ ├── constant │ │ │ └── Constants.java │ │ ├── exception │ │ │ ├── PushException.java │ │ │ ├── InitErrorException.java │ │ │ ├── DispatchException.java │ │ │ ├── CommunicationException.java │ │ │ └── LostConnectException.java │ │ ├── message │ │ │ ├── SystemMessage.java │ │ │ └── MessageWrapper.java │ │ ├── utils │ │ │ ├── ByteUtils.java │ │ │ └── NetUtils.java │ │ ├── common │ │ │ ├── Endpoint.java │ │ │ └── Node.java │ │ └── notify │ │ │ ├── NotifyProxy.java │ │ │ └── NotifyFuture.java │ │ └── test │ │ ├── server │ │ ├── TestTcpServer.java │ │ ├── TestSimpleProxy.java │ │ └── TestNotify.java │ │ ├── client │ │ ├── TcpClientHandler.java │ │ └── TcpClient.java │ │ └── data │ │ ├── Login.proto │ │ └── Protocol.java │ └── resources │ ├── spring-config.xml │ └── spring-tcp-server.xml ├── .gitignore ├── .project ├── .classpath ├── README.md ├── pom.xml └── LICENSE /src/main/java/com/ibyte/iot/tcp/remoting/Sender.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.remoting; 2 | 3 | import com.ibyte.iot.tcp.message.MessageWrapper; 4 | 5 | public interface Sender { 6 | 7 | void sendMessage(MessageWrapper wrapper) throws RuntimeException; 8 | 9 | boolean existSession(MessageWrapper wrapper) throws RuntimeException; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/invoke/ApiProxy.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.invoke; 2 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 3 | import com.ibyte.iot.tcp.message.MessageWrapper; 4 | import com.ibyte.iot.tcp.message.SystemMessage; 5 | 6 | public interface ApiProxy { 7 | 8 | MessageWrapper invoke(SystemMessage sMsg, MessageBuf.JMTransfer message); 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | /target/ 25 | /.classpath/ 26 | /.settings/ 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/Connection.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector; 2 | 3 | /** 4 | * Created by Li.shangzhi on 17/1/10. 5 | */ 6 | public interface Connection { 7 | 8 | void connect(); 9 | 10 | void close(); 11 | 12 | void send(T message); 13 | 14 | String getConnectionId(); 15 | 16 | void setConnectionId(String connectionId); 17 | 18 | Session getSession(); 19 | 20 | void setSession(Session session); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/Connector.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector; 2 | /** 3 | * @FileName Connector.java 4 | * @Description: 5 | * @Date Jan 15, 2019 2:33:15 PM 6 | * @author Li.shangzhi 7 | * @version 1.0 8 | */ 9 | public interface Connector { 10 | 11 | void init(); 12 | 13 | void destroy(); 14 | 15 | void send(String sessionId, T message) throws Exception; 16 | 17 | boolean exist(String sessionId) throws Exception; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/ExchangeTcpSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | import com.ibyte.iot.tcp.connector.api.ExchangeSessionManager; 5 | 6 | import io.netty.channel.ChannelHandlerContext; 7 | 8 | public abstract class ExchangeTcpSessionManager extends ExchangeSessionManager { 9 | 10 | public abstract Session createSession(String sessionId, ChannelHandlerContext ctx); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/spring-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/server/TestTcpServer.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.server; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.context.support.FileSystemXmlApplicationContext; 5 | 6 | public class TestTcpServer { 7 | 8 | /** 9 | * 程序启动 Server 10 | * @param args 11 | */ 12 | public static void main(String[] args) { 13 | ApplicationContext context = new FileSystemXmlApplicationContext(new String[]{"classpath:spring-config.xml"}); 14 | context.getApplicationName(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.constant; 2 | 3 | import io.netty.util.AttributeKey; 4 | 5 | public class Constants { 6 | 7 | /** 8 | * 默认启动端口,包括不配置或者随机,都从此端口开始计算 9 | */ 10 | public static final int DEFAULT_SERVER_PORT = 22000; 11 | 12 | public static final int NOTIFY_SUCCESS = 1; 13 | public static final int NOTIFY_FAILURE = 0; 14 | public static final int NOTIFY_NO_SESSION = 2; 15 | 16 | public static final AttributeKey SERVER_SESSION_HOOK = AttributeKey.valueOf("SERVER_SESSION_HOOK"); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/exception/PushException.java: -------------------------------------------------------------------------------- 1 | 2 | package com.ibyte.iot.tcp.exception; 3 | 4 | public class PushException extends IllegalStateException { 5 | 6 | private static final long serialVersionUID = -4953949710626671131L; 7 | 8 | public PushException() { 9 | super(); 10 | } 11 | 12 | public PushException(String message) { 13 | super(message); 14 | } 15 | 16 | public PushException(Throwable throwable) { 17 | super(throwable); 18 | } 19 | 20 | public PushException(String message, Throwable throwable) { 21 | super(message, throwable); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | icloud-tcp-gateway 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/exception/InitErrorException.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.exception; 2 | 3 | public class InitErrorException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 4401440531171871948L; 6 | 7 | private int errorCode = 1; 8 | 9 | private String errorMsg; 10 | 11 | protected InitErrorException() { 12 | 13 | } 14 | 15 | public InitErrorException(String errorMsg, Throwable e) { 16 | super(errorMsg, e); 17 | this.errorMsg = errorMsg; 18 | } 19 | 20 | public InitErrorException(String errorMsg) { 21 | super(errorMsg); 22 | this.errorMsg = errorMsg; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/message/SystemMessage.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.message; 2 | import java.io.Serializable; 3 | public class SystemMessage implements Serializable { 4 | 5 | private String remoteAddress; 6 | private String localAddress; 7 | 8 | public String getRemoteAddress() { 9 | return remoteAddress; 10 | } 11 | 12 | public void setRemoteAddress(String remoteAddress) { 13 | this.remoteAddress = remoteAddress; 14 | } 15 | 16 | public String getLocalAddress() { 17 | return localAddress; 18 | } 19 | 20 | public void setLocalAddress(String localAddress) { 21 | this.localAddress = localAddress; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/codec/MessageBuf.proto: -------------------------------------------------------------------------------- 1 | message JMTransfer { 2 | required string version = 1;//接口版本号 3 | required string deviceId = 2;//设备uuid 4 | required uint32 cmd = 3;//请求接口命令字 5 | required uint64 seq = 4;//请求序列号 6 | required uint32 format = 5;//请求1,应答2,通知3,响应4 7 | required uint32 flag = 6;//1 rsa加密 2aes加密 8 | required string platform = 7;//mobile-ios mobile-android pc-windows pc-mac 9 | required string platformVersion = 8;//客户端版本号 10 | required string token = 9;//客户端凭证 11 | required string appKey = 10;//客户端key 12 | required string timeStamp = 11;//时间戳 13 | required string sign = 12;//签名 md5(secret++(body base64)++(timeStamp)++secret) 14 | optional bytes body = 20;//请求数据 15 | } -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/listener/LogSessionListener.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api.listener; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * Created by Li.shangzhi on 17/1/10. 8 | */ 9 | public class LogSessionListener implements SessionListener { 10 | 11 | private final static Logger logger = LoggerFactory.getLogger(LogSessionListener.class); 12 | 13 | public void sessionCreated(SessionEvent se) { 14 | logger.info("session " + se.getSession().getSessionId() + " have been created!"); 15 | } 16 | 17 | public void sessionDestroyed(SessionEvent se) { 18 | logger.info("session " + se.getSession().getSessionId() + " have been destroyed!"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/codec/ProtobufAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.codec; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.config.ServerTransportConfig; 4 | 5 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 6 | import io.netty.handler.codec.protobuf.ProtobufEncoder; 7 | 8 | public class ProtobufAdapter { 9 | 10 | private ProtobufDecoder decoder = new ProtobufDecoder(MessageBuf.JMTransfer.getDefaultInstance()); 11 | private ProtobufEncoder encoder = new ProtobufEncoder(); 12 | 13 | public ProtobufAdapter(ServerTransportConfig config) { 14 | // nothing to do 15 | } 16 | 17 | public ProtobufDecoder getDecoder() { 18 | return decoder; 19 | } 20 | 21 | public ProtobufEncoder getEncoder() { 22 | return encoder; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/utils/ByteUtils.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.utils; 2 | /** 3 | * Created by Li.shangzhi on 17/1/10. 4 | */ 5 | public class ByteUtils { 6 | 7 | /** 8 | * byte数组转换成16进制字符串 9 | * 10 | * @param src 11 | * @return 12 | */ 13 | public static String bytesToHexString(byte[] src) { 14 | StringBuilder stringBuilder = new StringBuilder(); 15 | if (src == null || src.length <= 0) { 16 | return null; 17 | } 18 | for (int i = 0; i < src.length; i++) { 19 | int v = src[i] & 0xFF; 20 | String hv = Integer.toHexString(v); 21 | if (hv.length() < 2) { 22 | } 23 | stringBuilder.append(hv); 24 | stringBuilder.append(0); 25 | } 26 | return stringBuilder.toString(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/listener/SessionEvent.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api.listener; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | 5 | import java.util.EventObject; 6 | 7 | /** 8 | * This is the class representing event notifications for changes to sessions 9 | * within a TSM application. 10 | */ 11 | public class SessionEvent extends EventObject { 12 | 13 | /** 14 | * Constructs a prototypical Event. 15 | * 16 | * @param source The object on which the Event initially occurred. 17 | * @throws IllegalArgumentException if source is null. 18 | */ 19 | public SessionEvent(Object source) { 20 | super(source); 21 | } 22 | 23 | /** 24 | * Return the session that changed. 25 | */ 26 | public Session getSession() { 27 | return (Session) super.getSource(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/client/TcpClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.client; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.ChannelInboundHandlerAdapter; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | //public class TcpClientHandler extends ChannelHandlerAdapter { 10 | public class TcpClientHandler extends ChannelInboundHandlerAdapter { 11 | 12 | private final static Logger logger = LoggerFactory.getLogger(TcpClientHandler.class); 13 | 14 | public void channelRead(ChannelHandlerContext ctx, Object o) throws Exception { 15 | MessageBuf.JMTransfer message = (MessageBuf.JMTransfer) o; 16 | 17 | logger.info("Client Received Msg :" + message); 18 | System.out.println("Client Received Msg :" + message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/listener/SessionListener.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api.listener; 2 | 3 | import java.util.EventListener; 4 | 5 | /** 6 | * Implementations of this interface are notified of changes to the list of 7 | * active sessions in a TSM application. To receive notification events, the 8 | * implementation class must be configured in the deployment descriptor for the 9 | * TSM application. 10 | */ 11 | public interface SessionListener extends EventListener { 12 | 13 | /** 14 | * Notification that a session was created. 15 | * 16 | * @param se the notification event 17 | */ 18 | void sessionCreated(SessionEvent se); 19 | 20 | /** 21 | * Notification that a session is about to be invalidated. 22 | * 23 | * @param se the notification event 24 | */ 25 | void sessionDestroyed(SessionEvent se); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/Session.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector; 2 | 3 | import com.ibyte.iot.tcp.common.Endpoint; 4 | 5 | /** 6 | * Created by Li.shangzhi on 17/1/10. 7 | */ 8 | public interface Session extends Endpoint { 9 | 10 | /** 11 | * Update the accessed time information for this session. This method 12 | * should be called by the context when a request comes in for a particular 13 | * session, even if the application does not reference it. 14 | */ 15 | void access(); 16 | 17 | /** 18 | * Inform the listeners about the new session and open connection. 19 | */ 20 | void connect(); 21 | 22 | /** 23 | * Perform the internal processing required to invalidate this session, 24 | * without triggering an exception if the session has already expired. 25 | * then close the connection. 26 | */ 27 | void close(); 28 | 29 | /** 30 | * Release all object references, and initialize instance variables, in 31 | * preparation for reuse of this object. 32 | */ 33 | void recycle(); 34 | 35 | boolean expire(); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/ExchangeConnection.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api; 2 | 3 | import com.ibyte.iot.tcp.connector.Connection; 4 | import com.ibyte.iot.tcp.connector.Session; 5 | 6 | /** 7 | * Created by Li.shangzhi on 17/1/10. 8 | */ 9 | public abstract class ExchangeConnection implements Connection { 10 | 11 | protected Session session = null; 12 | protected String connectionId = null; 13 | 14 | protected volatile boolean close = false; 15 | protected int connectTimeout = 60 * 60 * 1000; // ms 16 | 17 | public void fireError(RuntimeException e) { 18 | throw e; 19 | } 20 | 21 | public boolean isClosed() { 22 | return close; 23 | } 24 | 25 | public void setConnectionId(String connectionId) { 26 | this.connectionId = connectionId; 27 | } 28 | 29 | public String getConnectionId() { 30 | return connectionId; 31 | } 32 | 33 | public void setSession(Session session) { 34 | this.session = session; 35 | } 36 | 37 | public Session getSession() { 38 | return session; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/config/ServerTransportConfig.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.config; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.TcpConnector; 4 | import com.ibyte.iot.tcp.invoke.ApiProxy; 5 | import com.ibyte.iot.tcp.notify.NotifyProxy; 6 | 7 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 8 | 9 | public class ServerTransportConfig { 10 | 11 | // handler 12 | private TcpConnector tcpConnector = null; 13 | // codec 14 | private ProtobufDecoder decoder = null; 15 | // invoke 16 | private ApiProxy proxy = null; 17 | private NotifyProxy notify = null; 18 | 19 | public ServerTransportConfig(TcpConnector tcpConnector, ApiProxy proxy, NotifyProxy notify) { 20 | this.tcpConnector = tcpConnector; 21 | this.proxy = proxy; 22 | this.notify = notify; 23 | } 24 | 25 | public TcpConnector getTcpConnector() { 26 | return tcpConnector; 27 | } 28 | 29 | public ProtobufDecoder getDecoder() { 30 | return decoder; 31 | } 32 | 33 | public ApiProxy getProxy() { 34 | return proxy; 35 | } 36 | 37 | public NotifyProxy getNotify() { 38 | return notify; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/common/Endpoint.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.common; 2 | import com.ibyte.iot.tcp.connector.Connection; 3 | import com.ibyte.iot.tcp.connector.SessionManager; 4 | import com.ibyte.iot.tcp.connector.api.listener.SessionListener; 5 | /** 6 | * @FileName Endpoint.java 7 | * @Description: 8 | * 9 | * @Date Jan 15, 2019 11:02:35 AM 10 | * @author Li.shangzhi 11 | * @version 1.0 12 | */ 13 | public interface Endpoint extends Node { 14 | 15 | /** 16 | * @param connection 17 | */ 18 | void setConnection(Connection connection); 19 | 20 | Connection getConnection(); 21 | 22 | /** 23 | * @param sessionId 24 | */ 25 | void setSessionId(String sessionId); 26 | 27 | String getSessionId(); 28 | 29 | /** 30 | * @param sessionManager 31 | */ 32 | void setSessionManager(SessionManager sessionManager); 33 | 34 | SessionManager getSessionManager(); 35 | 36 | /** 37 | * Add a session event listener to this component. 38 | */ 39 | void addSessionListener(SessionListener listener); 40 | 41 | /** 42 | * Remove a session event listener from this component. 43 | */ 44 | void removeSessionListener(SessionListener listener); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/remoting/TcpSender.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.remoting; 2 | 3 | import com.ibyte.iot.tcp.connector.Connector; 4 | import com.ibyte.iot.tcp.message.MessageWrapper; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class TcpSender implements Sender { 10 | 11 | private final static Logger logger = LoggerFactory.getLogger(TcpSender.class); 12 | 13 | private Connector tcpConnector; 14 | 15 | public TcpSender(Connector tcpConnector) { 16 | this.tcpConnector = tcpConnector; 17 | } 18 | 19 | public void sendMessage(MessageWrapper wrapper) throws RuntimeException { 20 | try { 21 | tcpConnector.send(wrapper.getSessionId(), wrapper.getBody()); 22 | } catch (Exception e) { 23 | logger.error("TcpSender sendMessage occur Exception!", e); 24 | throw new RuntimeException(e.getCause()); 25 | } 26 | } 27 | 28 | public boolean existSession(MessageWrapper wrapper) throws RuntimeException { 29 | try { 30 | return tcpConnector.exist(wrapper.getSessionId()); 31 | } catch (Exception e) { 32 | logger.error("TcpSender sendMessage occur Exception!", e); 33 | throw new RuntimeException(e.getCause()); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/common/Node.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.common; 2 | /** 3 | * @FileName Node.java 4 | * @Description: 5 | * 6 | * @Date Jan 15, 2019 11:03:17 AM 7 | * @author Li.shangzhi 8 | * @version 1.0 9 | */ 10 | public interface Node { 11 | 12 | /** 13 | * @param isValid 14 | */ 15 | void setValid(boolean isValid); 16 | 17 | boolean isValid(); 18 | 19 | /** 20 | * @param creationTime 21 | */ 22 | void setCreationTime(long creationTime); 23 | 24 | long getCreationTime(); 25 | 26 | /** 27 | * @param lastAccessedTime 28 | */ 29 | void setLastAccessedTime(long lastAccessedTime); 30 | 31 | long getLastAccessedTime(); 32 | 33 | /** 34 | * @param maxInactiveInterval 35 | */ 36 | void setMaxInactiveInterval(int maxInactiveInterval); 37 | 38 | int getMaxInactiveInterval(); 39 | 40 | /** 41 | * @param name 42 | * @param value 43 | */ 44 | void setAttribute(String name, Object value); 45 | 46 | /** 47 | * Return the object bound with the specified name in this session, or 48 | * null if no object is bound with that name. 49 | * 50 | * @param name Name of the attribute to be returned 51 | * @throws IllegalStateException if this method is called on an invalidated session 52 | */ 53 | Object getAttribute(String name); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/ExchangeConnector.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api; 2 | 3 | import com.ibyte.iot.tcp.connector.Connector; 4 | import com.ibyte.iot.tcp.connector.Session; 5 | import com.ibyte.iot.tcp.connector.SessionManager; 6 | import com.ibyte.iot.tcp.exception.DispatchException; 7 | import com.ibyte.iot.tcp.exception.PushException; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * Created by Li.shangzhi on 17/1/10. 14 | */ 15 | public abstract class ExchangeConnector implements Connector { 16 | 17 | private final static Logger logger = LoggerFactory.getLogger(ExchangeConnector.class); 18 | 19 | public void send(SessionManager sessionManager, String sessionId, T message) throws Exception { 20 | Session session = sessionManager.getSession(sessionId); 21 | if (session == null) { 22 | throw new Exception(String.format("session %s no exist.", sessionId)); 23 | } 24 | try { 25 | session.getConnection().send(message); 26 | session.access(); 27 | } catch (PushException e) { 28 | logger.error("ExchangeConnector send occur PushException.", e); 29 | session.close(); 30 | throw new DispatchException(e); 31 | } catch (Exception e) { 32 | logger.error("ExchangeConnector send occur Exception.", e); 33 | session.close(); 34 | throw new DispatchException(e); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/server/ServerChannelInitializer.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.server; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.codec.ProtobufAdapter; 4 | import com.ibyte.iot.tcp.connector.tcp.config.ServerTransportConfig; 5 | 6 | import io.netty.channel.ChannelHandler; 7 | import io.netty.channel.ChannelInitializer; 8 | import io.netty.channel.ChannelPipeline; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; 11 | import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; 12 | 13 | @ChannelHandler.Sharable 14 | public class ServerChannelInitializer extends ChannelInitializer { 15 | 16 | private ServerTransportConfig config; 17 | 18 | public ServerChannelInitializer(ServerTransportConfig config) { 19 | this.config = config; 20 | } 21 | 22 | @Override 23 | protected void initChannel(SocketChannel socketChannel) throws Exception { 24 | ProtobufAdapter adapter = new ProtobufAdapter(config); 25 | 26 | ChannelPipeline pipeline = socketChannel.pipeline(); 27 | pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder()); 28 | pipeline.addLast("decoder", adapter.getDecoder()); 29 | pipeline.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender()); 30 | pipeline.addLast("encoder", adapter.getEncoder()); 31 | pipeline.addLast("handler", new TcpServerHandler(config)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/ExchangeTcpConnector.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | import com.ibyte.iot.tcp.connector.api.ExchangeConnector; 5 | import com.ibyte.iot.tcp.message.MessageWrapper; 6 | 7 | import io.netty.channel.ChannelHandlerContext; 8 | 9 | public abstract class ExchangeTcpConnector extends ExchangeConnector { 10 | 11 | protected TcpSessionManager tcpSessionManager = null; 12 | 13 | public abstract void connect(ChannelHandlerContext ctx, MessageWrapper wrapper); 14 | 15 | public abstract void close(MessageWrapper wrapper); 16 | 17 | /** 18 | * 会话心跳 19 | * 20 | * @param wrapper 21 | */ 22 | public abstract void heartbeatClient(MessageWrapper wrapper); 23 | 24 | /** 25 | * 接收客户端消息通知响应 26 | * 27 | * @param wrapper 28 | */ 29 | public abstract void responseSendMessage(MessageWrapper wrapper); 30 | 31 | public abstract void responseNoKeepAliveMessage(ChannelHandlerContext ctx, MessageWrapper wrapper); 32 | 33 | public void send(String sessionId, T message) throws Exception { 34 | super.send(tcpSessionManager, sessionId, message); 35 | } 36 | 37 | public boolean exist(String sessionId) throws Exception { 38 | Session session = tcpSessionManager.getSession(sessionId); 39 | return session != null ? true : false; 40 | } 41 | 42 | public void setTcpSessionManager(TcpSessionManager tcpSessionManager) { 43 | this.tcpSessionManager = tcpSessionManager; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/SessionManager.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * Created by Li.shangzhi on 17/1/10. 7 | */ 8 | public interface SessionManager { 9 | 10 | /** 11 | * 添加指定session 12 | * 13 | * @param session 14 | */ 15 | void addSession(Session session); 16 | 17 | void updateSession(String sessionId); 18 | 19 | /** 20 | * 删除指定session 21 | * 22 | * @param session 23 | */ 24 | void removeSession(Session session); 25 | 26 | /** 27 | * 删除指定session 28 | * 29 | * @param sessionId 30 | */ 31 | void removeSession(String sessionId); 32 | 33 | /** 34 | * 根据指定sessionId获取session 35 | * 36 | * @param sessionId 37 | * @return 38 | */ 39 | Session getSession(String sessionId); 40 | 41 | /** 42 | * 获取所有的session 43 | * 44 | * @return 45 | */ 46 | Session[] getSessions(); 47 | 48 | /** 49 | * 获取所有的session的id集合 50 | * 51 | * @return 52 | */ 53 | Set getSessionKeys(); 54 | 55 | /** 56 | * 获取所有的session数目 57 | * 58 | * @return 59 | */ 60 | int getSessionCount(); 61 | 62 | /** 63 | * Return the default maximum inactive interval (in seconds) 64 | * for Sessions created by this Manager. 65 | */ 66 | int getMaxInactiveInterval(); 67 | 68 | /** 69 | * Set the default maximum inactive interval (in seconds) 70 | * for Sessions created by this Manager. 71 | * 72 | * @param interval The new default value 73 | */ 74 | void setMaxInactiveInterval(int interval); 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/data/Login.proto: -------------------------------------------------------------------------------- 1 | message MessageBufPro { 2 | enum ProtocolField { 3 | HEART_BEAT = 0; 4 | NOTIFY_HAS_MESSAGE = 2; 5 | ORIGINAL_MESSAGE =3; 6 | } 7 | enum CMD { 8 | CONNECT = 10000; 9 | CLOSE = 10001; 10 | HEARTBEAT = 10002; 11 | SEND = 11000; 12 | } 13 | enum EncryptField { 14 | TRUE = 1; 15 | FALSE = 0; 16 | } 17 | enum CodeField { 18 | SUCCESS = 1; 19 | FAILURE = 0; 20 | } 21 | message MessageReq { 22 | required string method = 1; 23 | required string token = 2; 24 | required string sign = 3; 25 | required string time = 4; 26 | required string v = 5; 27 | required string param = 6; 28 | required CMD cmd = 7; 29 | required string device = 8; 30 | required string app = 9; 31 | } 32 | message MessageResp { 33 | required CodeField code = 1; 34 | required ProtocolField protocol = 2; 35 | required EncryptField encrypt = 3; 36 | optional string notice = 4; 37 | optional MessageBody body = 5; 38 | required CMD cmd = 6; 39 | required float time = 7; 40 | required string callback = 8; 41 | required string msg = 9; 42 | } 43 | message MessageBody { 44 | required int32 source = 41; 45 | required MessageForm form = 42; 46 | required MessageContent content = 43; 47 | } 48 | message MessageForm { 49 | required string source = 421; 50 | required string type = 422; 51 | } 52 | message MessageContent { 53 | required float id = 431; 54 | required string title = 432; 55 | required string content = 433; 56 | required string time = 434; 57 | required string extend1 = 435; 58 | required string extend2 = 436; 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/server/TestSimpleProxy.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.server; 2 | 3 | import com.google.protobuf.ByteString; 4 | import com.google.protobuf.InvalidProtocolBufferException; 5 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 6 | import com.ibyte.iot.tcp.invoke.ApiProxy; 7 | import com.ibyte.iot.tcp.message.MessageWrapper; 8 | import com.ibyte.iot.tcp.message.SystemMessage; 9 | import com.ibyte.iot.test.data.Login; 10 | import com.ibyte.iot.test.data.Protocol; 11 | 12 | public class TestSimpleProxy implements ApiProxy { 13 | 14 | public MessageWrapper invoke(SystemMessage sMsg, MessageBuf.JMTransfer message) { 15 | ByteString body = message.getBody(); 16 | 17 | if (message.getCmd() == 1000) { 18 | try { 19 | Login.MessageBufPro.MessageReq messageReq = Login.MessageBufPro.MessageReq.parseFrom(body); 20 | if (messageReq.getCmd().equals(Login.MessageBufPro.CMD.CONNECT)) { 21 | return new MessageWrapper(MessageWrapper.MessageProtocol.CONNECT, message.getToken(), null); 22 | } 23 | } catch (InvalidProtocolBufferException e) { 24 | e.printStackTrace(); 25 | } 26 | } else if (message.getCmd() == 1002) { 27 | try { 28 | Login.MessageBufPro.MessageReq messageReq = Login.MessageBufPro.MessageReq.parseFrom(body); 29 | if (messageReq.getCmd().equals(Login.MessageBufPro.CMD.HEARTBEAT)) { 30 | MessageBuf.JMTransfer.Builder resp = Protocol.generateHeartbeat(); 31 | return new MessageWrapper(MessageWrapper.MessageProtocol.HEART_BEAT, message.getToken(), resp); 32 | } 33 | } catch (InvalidProtocolBufferException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/spring-tcp-server.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/message/MessageWrapper.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.message; 2 | 3 | import java.io.Serializable; 4 | 5 | public class MessageWrapper implements Serializable { 6 | 7 | private MessageProtocol protocol; 8 | private String sessionId; 9 | private Object body; 10 | 11 | private MessageWrapper() { 12 | } 13 | 14 | public MessageWrapper(MessageProtocol protocol, String sessionId, Object body) { 15 | this.protocol = protocol; 16 | this.sessionId = sessionId; 17 | this.body = body; 18 | } 19 | 20 | public enum MessageProtocol { 21 | CONNECT, CLOSE, HEART_BEAT, SEND, RECEIVE, NOTIFY, REPLY, NO_CONNECT 22 | } 23 | 24 | public boolean isConnect() { 25 | return MessageProtocol.CONNECT.equals(this.protocol); 26 | } 27 | 28 | public boolean isClose() { 29 | return MessageProtocol.CLOSE.equals(this.protocol); 30 | } 31 | 32 | public boolean isHeartbeat() { 33 | return MessageProtocol.HEART_BEAT.equals(this.protocol); 34 | } 35 | 36 | public boolean isSend() { 37 | return MessageProtocol.SEND.equals(this.protocol); 38 | } 39 | 40 | public boolean isNotify() { 41 | return MessageProtocol.NOTIFY.equals(this.protocol); 42 | } 43 | 44 | public boolean isReply() { 45 | return MessageProtocol.REPLY.equals(this.protocol); 46 | } 47 | 48 | public boolean isNoKeepAliveMessage() { 49 | return MessageProtocol.NO_CONNECT.equals(this.protocol); 50 | } 51 | 52 | public void setProtocol(MessageProtocol protocol) { 53 | this.protocol = protocol; 54 | } 55 | 56 | public String getSessionId() { 57 | return sessionId; 58 | } 59 | 60 | public void setSessionId(String sessionId) { 61 | this.sessionId = sessionId; 62 | } 63 | 64 | public Object getBody() { 65 | return body; 66 | } 67 | 68 | public void setBody(Object body) { 69 | this.body = body; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/NoKeepAliveTcpConnection.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.exception.LostConnectException; 4 | import com.ibyte.iot.tcp.exception.PushException; 5 | 6 | import io.netty.channel.ChannelFuture; 7 | import io.netty.channel.ChannelHandlerContext; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class NoKeepAliveTcpConnection { 13 | 14 | private final static Logger logger = LoggerFactory.getLogger(NoKeepAliveTcpConnection.class); 15 | 16 | private ChannelHandlerContext cxt; 17 | 18 | public NoKeepAliveTcpConnection(ChannelHandlerContext cxt) { 19 | this.cxt = cxt; 20 | } 21 | 22 | public void close() { 23 | cxt.close(); 24 | logger.info("the connection have been destroyed!"); 25 | } 26 | 27 | public void send(T message) { 28 | sendMessage(message); 29 | } 30 | 31 | private void sendMessage(T message) { 32 | pushMessage(message); 33 | } 34 | 35 | private void pushMessage(T message) { 36 | boolean success = true; 37 | boolean sent = true; 38 | int timeout = 60; 39 | try { 40 | ChannelFuture cf = cxt.write(message); 41 | cxt.flush(); 42 | if (sent) { 43 | success = cf.await(timeout); 44 | } 45 | if (cf.isSuccess()) { 46 | logger.info("send success."); 47 | } 48 | Throwable cause = cf.cause(); 49 | if (cause != null) { 50 | throw new PushException(cause); 51 | } 52 | } catch (LostConnectException e) { 53 | logger.error("NoKeepAliveTcpConnection pushMessage occur LostConnectException.", e); 54 | throw new PushException(e); 55 | } catch (Exception e) { 56 | logger.error("NoKeepAliveTcpConnection pushMessage occur Exception.", e); 57 | throw new PushException(e); 58 | } catch (Throwable e) { 59 | logger.error("NoKeepAliveTcpConnection pushMessage occur Throwable.", e); 60 | throw new PushException("Failed to send message, cause: " + e.getMessage(), e); 61 | } 62 | if (!success) { 63 | throw new PushException("Failed to send message, in timeout(" + timeout + "ms) limit"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/TcpSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.connector.Connection; 4 | import com.ibyte.iot.tcp.connector.Session; 5 | import com.ibyte.iot.tcp.connector.api.ExchangeSession; 6 | import com.ibyte.iot.tcp.connector.api.listener.SessionListener; 7 | 8 | import io.netty.channel.ChannelHandlerContext; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class TcpSessionManager extends ExchangeTcpSessionManager { 14 | 15 | private final static Logger logger = LoggerFactory.getLogger(TcpSessionManager.class); 16 | 17 | @Override 18 | public synchronized Session createSession(String sessionId, ChannelHandlerContext ctx) { 19 | Session session = sessions.get(sessionId); 20 | if (session != null) { 21 | logger.info("session " + sessionId + " exist!"); 22 | /** 23 | * 如果在已经建立Connection(1)的Channel上,再建立Connection(2) 24 | * session.close会将ctx关闭, Connection(2)和Connection(1)的Channel都将会关闭 25 | * 断线之后再建立连接Connection(3),由于Session是有一点延迟 26 | * Connection(3)和Connection(1/2)的Channel不是同一个 27 | * **/ 28 | // 如果session已经存在则销毁session 29 | session.close(); 30 | logger.info("session " + sessionId + " have been closed!"); 31 | } 32 | logger.info("create new session " + sessionId + ", ctx -> " + ctx.toString()); 33 | 34 | session = new ExchangeSession(); 35 | session.setSessionId(sessionId); 36 | session.setValid(true); 37 | session.setMaxInactiveInterval(this.getMaxInactiveInterval()); 38 | session.setCreationTime(System.currentTimeMillis()); 39 | session.setLastAccessedTime(System.currentTimeMillis()); 40 | session.setSessionManager(this); 41 | session.setConnection(createTcpConnection(session, ctx)); 42 | logger.info("create new session " + sessionId + " successful!"); 43 | 44 | for (SessionListener listener : sessionListeners) { 45 | session.addSessionListener(listener); 46 | } 47 | logger.debug("add listeners to session " + sessionId + " successful! " + sessionListeners); 48 | 49 | return session; 50 | } 51 | 52 | protected Connection createTcpConnection(Session session, ChannelHandlerContext ctx) { 53 | Connection conn = new TcpConnection(ctx); 54 | conn.setConnectionId(session.getSessionId()); 55 | conn.setSession(session); 56 | return conn; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/exception/DispatchException.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.exception; 2 | 3 | public class DispatchException extends Exception { 4 | 5 | /** 6 | * Constructs a new exception with null as its detail message. 7 | * The cause is not initialized, and may subsequently be initialized by a 8 | * call to {@link #initCause}. 9 | */ 10 | public DispatchException() { 11 | super(); 12 | } 13 | 14 | /** 15 | * Constructs a new exception with the specified detail message. The 16 | * cause is not initialized, and may subsequently be initialized by 17 | * a call to {@link #initCause}. 18 | * 19 | * @param message the detail message. The detail message is saved for 20 | * later retrieval by the {@link #getMessage()} method. 21 | */ 22 | public DispatchException(String message) { 23 | super(message); 24 | } 25 | 26 | /** 27 | * Constructs a new exception with the specified detail message and 28 | * cause.

Note that the detail message associated with 29 | * cause is not automatically incorporated in 30 | * this exception's detail message. 31 | * 32 | * @param message the detail message (which is saved for later retrieval 33 | * by the {@link #getMessage()} method). 34 | * @param cause the cause (which is saved for later retrieval by the 35 | * {@link #getCause()} method). (A null value is 36 | * permitted, and indicates that the cause is nonexistent or 37 | * unknown.) 38 | * @since 1.4 39 | */ 40 | public DispatchException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | * Constructs a new exception with the specified cause and a detail 46 | * message of (cause==null ? null : cause.toString()) (which 47 | * typically contains the class and detail message of cause). 48 | * This constructor is useful for exceptions that are little more than 49 | * wrappers for other throwables (for example, {@link 50 | * java.security.PrivilegedActionException}). 51 | * 52 | * @param cause the cause (which is saved for later retrieval by the 53 | * {@link #getCause()} method). (A null value is 54 | * permitted, and indicates that the cause is nonexistent or 55 | * unknown.) 56 | * @since 1.4 57 | */ 58 | public DispatchException(Throwable cause) { 59 | super(cause); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/exception/CommunicationException.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.exception; 2 | 3 | public class CommunicationException extends RuntimeException { 4 | 5 | /** 6 | * Constructs a new exception with null as its detail message. 7 | * The cause is not initialized, and may subsequently be initialized by a 8 | * call to {@link #initCause}. 9 | */ 10 | public CommunicationException() { 11 | super(); 12 | } 13 | 14 | /** 15 | * Constructs a new exception with the specified detail message. The 16 | * cause is not initialized, and may subsequently be initialized by 17 | * a call to {@link #initCause}. 18 | * 19 | * @param message the detail message. The detail message is saved for 20 | * later retrieval by the {@link #getMessage()} method. 21 | */ 22 | public CommunicationException(String message) { 23 | super(message); 24 | } 25 | 26 | /** 27 | * Constructs a new exception with the specified detail message and 28 | * cause.

Note that the detail message associated with 29 | * cause is not automatically incorporated in 30 | * this exception's detail message. 31 | * 32 | * @param message the detail message (which is saved for later retrieval 33 | * by the {@link #getMessage()} method). 34 | * @param cause the cause (which is saved for later retrieval by the 35 | * {@link #getCause()} method). (A null value is 36 | * permitted, and indicates that the cause is nonexistent or 37 | * unknown.) 38 | * @since 1.4 39 | */ 40 | public CommunicationException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | * Constructs a new exception with the specified cause and a detail 46 | * message of (cause==null ? null : cause.toString()) (which 47 | * typically contains the class and detail message of cause). 48 | * This constructor is useful for exceptions that are little more than 49 | * wrappers for other throwables (for example, {@link 50 | * java.security.PrivilegedActionException}). 51 | * 52 | * @param cause the cause (which is saved for later retrieval by the 53 | * {@link #getCause()} method). (A null value is 54 | * permitted, and indicates that the cause is nonexistent or 55 | * unknown.) 56 | * @since 1.4 57 | */ 58 | public CommunicationException(Throwable cause) { 59 | super(cause); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/exception/LostConnectException.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.exception; 2 | 3 | public class LostConnectException extends CommunicationException { 4 | 5 | /** 6 | * Constructs a new exception with null as its detail message. 7 | * The cause is not initialized, and may subsequently be initialized by a 8 | * call to {@link #initCause}. 9 | */ 10 | public LostConnectException() { 11 | super(); 12 | } 13 | 14 | /** 15 | * Constructs a new exception with the specified detail message. The 16 | * cause is not initialized, and may subsequently be initialized by 17 | * a call to {@link #initCause}. 18 | * 19 | * @param message the detail message. The detail message is saved for 20 | * later retrieval by the {@link #getMessage()} method. 21 | */ 22 | public LostConnectException(String message) { 23 | super(message); 24 | } 25 | 26 | /** 27 | * Constructs a new exception with the specified detail message and 28 | * cause.

Note that the detail message associated with 29 | * cause is not automatically incorporated in 30 | * this exception's detail message. 31 | * 32 | * @param message the detail message (which is saved for later retrieval 33 | * by the {@link #getMessage()} method). 34 | * @param cause the cause (which is saved for later retrieval by the 35 | * {@link #getCause()} method). (A null value is 36 | * permitted, and indicates that the cause is nonexistent or 37 | * unknown.) 38 | * @since 1.4 39 | */ 40 | public LostConnectException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | * Constructs a new exception with the specified cause and a detail 46 | * message of (cause==null ? null : cause.toString()) (which 47 | * typically contains the class and detail message of cause). 48 | * This constructor is useful for exceptions that are little more than 49 | * wrappers for other throwables (for example, {@link 50 | * java.security.PrivilegedActionException}). 51 | * 52 | * @param cause the cause (which is saved for later retrieval by the 53 | * {@link #getCause()} method). (A null value is 54 | * permitted, and indicates that the cause is nonexistent or 55 | * unknown.) 56 | * @since 1.4 57 | */ 58 | public LostConnectException(Throwable cause) { 59 | super(cause); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/server/TestNotify.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.server; 2 | 3 | import com.google.protobuf.ByteString; 4 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 5 | import com.ibyte.iot.tcp.constant.Constants; 6 | import com.ibyte.iot.tcp.message.MessageWrapper; 7 | import com.ibyte.iot.tcp.notify.NotifyProxy; 8 | 9 | import java.util.Map; 10 | 11 | public class TestNotify { 12 | 13 | private NotifyProxy notify; 14 | 15 | final int timeout = 10 * 1000; 16 | final int NOTIFY = 3; 17 | 18 | public boolean send(long seq, String sessionId, int cmd, ByteString body) throws Exception { 19 | boolean success = false; 20 | MessageBuf.JMTransfer.Builder builder = generateNotify(sessionId, seq, cmd, body); 21 | if (builder != null) { 22 | MessageWrapper wrapper = new MessageWrapper(MessageWrapper.MessageProtocol.NOTIFY, sessionId, builder); 23 | int ret = notify.notify(seq, wrapper, timeout); 24 | if (ret == Constants.NOTIFY_SUCCESS) { 25 | success = true; 26 | } else if (ret == Constants.NOTIFY_NO_SESSION) { 27 | /** no session on this machine **/ 28 | success = true; 29 | } 30 | } 31 | return success; 32 | } 33 | 34 | /** 35 | * session 36 | */ 37 | final String VERSION = "version"; 38 | final String DEVICE_ID = "deviceId"; 39 | final String PLATFORM = "platform"; 40 | final String PLATFORM_VERSION = "platformVersion"; 41 | final String TOKEN = "token"; 42 | final String APP_KEY = "appKey"; 43 | final String TIMESTAMP = "timestamp"; 44 | final String SIGN = "sign"; 45 | 46 | final Map> testSessionMap = null; 47 | 48 | protected MessageBuf.JMTransfer.Builder generateNotify(String sessionId, long seq, int cmd, ByteString body) throws Exception { 49 | Map map = testSessionMap.get(sessionId); 50 | 51 | MessageBuf.JMTransfer.Builder builder = MessageBuf.JMTransfer.newBuilder(); 52 | builder.setVersion(String.valueOf(map.get(VERSION))); 53 | builder.setDeviceId(String.valueOf(map.get(DEVICE_ID))); 54 | builder.setCmd(cmd); 55 | builder.setSeq(seq); 56 | builder.setFormat(NOTIFY); 57 | builder.setFlag(0); 58 | builder.setPlatform(String.valueOf(map.get(PLATFORM))); 59 | builder.setPlatformVersion(String.valueOf(map.get(PLATFORM_VERSION))); 60 | builder.setToken(String.valueOf(map.get(TOKEN))); 61 | builder.setAppKey(String.valueOf(map.get(APP_KEY))); 62 | builder.setTimeStamp(String.valueOf(map.get(TIMESTAMP))); 63 | builder.setSign(String.valueOf(map.get(SIGN))); 64 | builder.setBody(body); 65 | 66 | return builder; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/data/Protocol.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.data; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 4 | import org.apache.commons.lang.time.DateFormatUtils; 5 | 6 | import java.util.Date; 7 | 8 | public class Protocol { 9 | 10 | public static MessageBuf.JMTransfer.Builder generateConnect() { 11 | MessageBuf.JMTransfer.Builder builder = MessageBuf.JMTransfer.newBuilder(); 12 | builder.setVersion("1.0"); 13 | builder.setDeviceId("test"); 14 | builder.setCmd(1000); 15 | builder.setSeq(1234); 16 | builder.setFormat(1); 17 | builder.setFlag(1); 18 | builder.setPlatform("pc"); 19 | builder.setPlatformVersion("1.0"); 20 | builder.setToken("abc"); 21 | builder.setAppKey("123"); 22 | builder.setTimeStamp("123456"); 23 | builder.setSign("123"); 24 | 25 | Login.MessageBufPro.MessageReq.Builder logReq = Login.MessageBufPro.MessageReq.newBuilder(); 26 | logReq.setMethod("connect"); 27 | logReq.setToken("iosaaa"); 28 | logReq.setParam("123"); 29 | logReq.setSign("ios333"); 30 | logReq.setTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")); 31 | logReq.setV("1.0"); 32 | logReq.setDevice("tcp test"); 33 | logReq.setApp("server"); 34 | logReq.setCmd(Login.MessageBufPro.CMD.CONNECT); // 连接 35 | 36 | builder.setBody(logReq.build().toByteString()); 37 | 38 | return builder; 39 | } 40 | 41 | public static MessageBuf.JMTransfer.Builder generateHeartbeat() { 42 | MessageBuf.JMTransfer.Builder builder = MessageBuf.JMTransfer.newBuilder(); 43 | builder.setVersion("1.0"); 44 | builder.setDeviceId("test"); 45 | builder.setCmd(1002); 46 | builder.setSeq(1234); 47 | builder.setFormat(1); 48 | builder.setFlag(1); 49 | builder.setPlatform("pc"); 50 | builder.setPlatformVersion("1.0"); 51 | builder.setToken("abc"); 52 | builder.setAppKey("123"); 53 | builder.setTimeStamp("123456"); 54 | builder.setSign("123"); 55 | 56 | Login.MessageBufPro.MessageReq.Builder heartbeatReq = Login.MessageBufPro.MessageReq.newBuilder(); 57 | heartbeatReq.setMethod("123"); 58 | heartbeatReq.setToken("iosaaa"); 59 | heartbeatReq.setParam("123"); 60 | heartbeatReq.setSign("ios333"); 61 | heartbeatReq.setTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss")); 62 | heartbeatReq.setV("1.0"); 63 | heartbeatReq.setDevice("tcp test"); 64 | heartbeatReq.setApp("server"); 65 | heartbeatReq.setCmd(Login.MessageBufPro.CMD.HEARTBEAT); // 心跳 66 | 67 | builder.setBody(heartbeatReq.build().toByteString()); 68 | 69 | return builder; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/ExchangeSessionManager.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | import com.ibyte.iot.tcp.connector.SessionManager; 5 | import com.ibyte.iot.tcp.connector.api.listener.SessionListener; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | /** 16 | * Created by Li.shangzhi on 17/1/10. 17 | */ 18 | public abstract class ExchangeSessionManager implements SessionManager { 19 | 20 | private final static Logger logger = LoggerFactory.getLogger(ExchangeSessionManager.class); 21 | 22 | protected List sessionListeners = null; 23 | 24 | public void setSessionListeners(List sessionListeners) { 25 | this.sessionListeners = sessionListeners; 26 | } 27 | 28 | /** 29 | * The set of currently active Sessions for this Manager, keyed by session 30 | * identifier. 31 | */ 32 | protected Map sessions = new ConcurrentHashMap(); 33 | 34 | public synchronized void addSession(Session session) { 35 | if (null == session) { 36 | return; 37 | } 38 | sessions.put(session.getSessionId(), session); 39 | logger.debug("put a session " + session.getSessionId() + " to sessions!"); 40 | } 41 | 42 | public synchronized void updateSession(String sessionId) { 43 | Session session = sessions.get(sessionId); 44 | session.setLastAccessedTime(System.currentTimeMillis()); 45 | 46 | sessions.put(sessionId, session); 47 | } 48 | 49 | /** 50 | * Remove this Session from the active Sessions for this Manager. 51 | */ 52 | public synchronized void removeSession(Session session) { 53 | if (session == null) { 54 | throw new IllegalArgumentException("session is null!"); 55 | } 56 | removeSession(session.getSessionId()); 57 | } 58 | 59 | public synchronized void removeSession(String sessionId) { 60 | sessions.remove(sessionId); 61 | logger.debug("remove the session " + sessionId + " from sessions!"); 62 | } 63 | 64 | public Session getSession(String sessionId) { 65 | return sessions.get(sessionId); 66 | } 67 | 68 | public Session[] getSessions() { 69 | return sessions.values().toArray(new Session[0]); 70 | } 71 | 72 | public Set getSessionKeys() { 73 | return sessions.keySet(); 74 | } 75 | 76 | public int getSessionCount() { 77 | return sessions.size(); 78 | } 79 | 80 | /** 81 | * define timeout 5min 82 | */ 83 | private int maxInactiveInterval = 5 * 60; 84 | 85 | public int getMaxInactiveInterval() { 86 | return maxInactiveInterval; 87 | } 88 | 89 | public void setMaxInactiveInterval(int maxInactiveInterval) { 90 | this.maxInactiveInterval = maxInactiveInterval; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/server/TcpServer.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.server; 2 | import com.ibyte.iot.tcp.connector.tcp.config.ServerTransportConfig; 3 | import com.ibyte.iot.tcp.exception.InitErrorException; 4 | 5 | import io.netty.bootstrap.ServerBootstrap; 6 | import io.netty.channel.ChannelFuture; 7 | import io.netty.channel.ChannelFutureListener; 8 | import io.netty.channel.ChannelOption; 9 | import io.netty.channel.EventLoopGroup; 10 | import io.netty.channel.nio.NioEventLoopGroup; 11 | import io.netty.channel.socket.nio.NioServerSocketChannel; 12 | 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | public class TcpServer { 16 | 17 | private final static Logger logger = LoggerFactory.getLogger(TcpServer.class); 18 | 19 | private ServerTransportConfig serverConfig; 20 | 21 | private int port; 22 | 23 | private static final int BIZ_GROUP_SIZE = Runtime.getRuntime().availableProcessors() * 2; 24 | private static final int BIZ_THREAD_SIZE = 4; 25 | 26 | private final EventLoopGroup bossGroup = new NioEventLoopGroup(BIZ_GROUP_SIZE); 27 | private final EventLoopGroup workerGroup = new NioEventLoopGroup(BIZ_THREAD_SIZE); 28 | 29 | public void init() throws Exception { 30 | boolean flag = Boolean.FALSE; 31 | 32 | 33 | 34 | logger.info("start tcp server ..."); 35 | 36 | Class clazz = NioServerSocketChannel.class; 37 | // Server 服务启动 38 | ServerBootstrap bootstrap = new ServerBootstrap(); 39 | 40 | bootstrap.group(bossGroup, workerGroup); 41 | bootstrap.channel(clazz); 42 | bootstrap.childHandler(new ServerChannelInitializer(serverConfig)); 43 | // 可选参数 44 | bootstrap.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 32 * 1024); 45 | 46 | // 绑定接口,同步等待成功 47 | logger.info("start tcp server at port[" + port + "]."); 48 | ChannelFuture future = bootstrap.bind(port).sync(); 49 | ChannelFuture channelFuture = future.addListener(new ChannelFutureListener() { 50 | public void operationComplete(ChannelFuture future) throws Exception { 51 | if (future.isSuccess()) { 52 | logger.info("Server have success bind to " + port); 53 | } else { 54 | logger.error("Server fail bind to " + port); 55 | throw new InitErrorException("Server start fail !", future.cause()); 56 | } 57 | } 58 | }); 59 | } 60 | 61 | public void shutdown() { 62 | logger.info("shutdown tcp server ..."); 63 | // 释放线程池资源 64 | bossGroup.shutdownGracefully(); 65 | workerGroup.shutdownGracefully(); 66 | logger.info("shutdown tcp server end."); 67 | } 68 | 69 | //------------------ set && get -------------------- 70 | 71 | 72 | public void setServerConfig(ServerTransportConfig serverConfig) { 73 | this.serverConfig = serverConfig; 74 | } 75 | 76 | public void setPort(int port) { 77 | this.port = port; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/test/client/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.test.client; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 4 | import com.ibyte.iot.test.data.Protocol; 5 | import io.netty.bootstrap.Bootstrap; 6 | import io.netty.channel.*; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 10 | import io.netty.handler.codec.protobuf.ProtobufEncoder; 11 | import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; 12 | import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; 13 | 14 | public class TcpClient { 15 | 16 | public static String host = "iot-open.icloud.com"; 17 | public static int port = 2000; 18 | 19 | public static Bootstrap bootstrap = getBootstrap(); 20 | public static Channel channel = getChannel(host, port); 21 | 22 | /** 23 | * Init Bootstrap 24 | */ 25 | public static final Bootstrap getBootstrap() { 26 | EventLoopGroup group = new NioEventLoopGroup(); 27 | Bootstrap b = new Bootstrap(); 28 | b.group(group); 29 | b.channel(NioSocketChannel.class); 30 | b.handler(new ChannelInitializer() { 31 | @Override 32 | protected void initChannel(Channel ch) throws Exception { 33 | ChannelPipeline pipeline = ch.pipeline(); 34 | pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder()); 35 | pipeline.addLast("decoder", new ProtobufDecoder(MessageBuf.JMTransfer.getDefaultInstance())); 36 | pipeline.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender()); 37 | pipeline.addLast("encoder", new ProtobufEncoder()); 38 | pipeline.addLast("handler", new TcpClientHandler()); 39 | } 40 | }); 41 | 42 | 43 | b.option(ChannelOption.SO_KEEPALIVE, true); 44 | return b; 45 | } 46 | 47 | public static final Channel getChannel(String host, int port) { 48 | Channel channel; 49 | try { 50 | channel = bootstrap.connect(host, port).sync().channel(); 51 | } catch (Exception e) { 52 | System.out.println("Connect Server (host[" + host + "]:port[" + port + "]) Failure." + e); 53 | return null; 54 | } 55 | return channel; 56 | } 57 | 58 | public static void connect(Object msg) throws Exception { 59 | if (channel != null) { 60 | channel.writeAndFlush(msg).sync(); 61 | } 62 | } 63 | 64 | /** 65 | * 程序启动 Client 66 | * @param args 67 | * @throws Exception 68 | */ 69 | public static void main(String[] args) throws Exception { 70 | try { 71 | TcpClient.connect(Protocol.generateConnect()); 72 | for (; ; ) { 73 | TcpClient.connect(Protocol.generateHeartbeat()); 74 | Thread.sleep(3000); 75 | } 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/notify/NotifyProxy.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.notify; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.TcpConnector; 4 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 5 | import com.ibyte.iot.tcp.constant.Constants; 6 | import com.ibyte.iot.tcp.message.MessageWrapper; 7 | import com.ibyte.iot.tcp.utils.ByteUtils; 8 | 9 | import org.apache.commons.lang.StringUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.util.concurrent.ConcurrentHashMap; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | public class NotifyProxy { 17 | 18 | private final static Logger logger = LoggerFactory.getLogger(NotifyProxy.class); 19 | 20 | private TcpConnector tcpConnector; 21 | 22 | public NotifyProxy(TcpConnector tcpConnector) { 23 | this.tcpConnector = tcpConnector; 24 | } 25 | 26 | private final ConcurrentHashMap futureMap = new ConcurrentHashMap(); 27 | 28 | public int notify(long seq, MessageWrapper wrapper, int timeout) throws Exception { 29 | try { 30 | NotifyFuture future = doSendAsync(seq, wrapper, timeout); 31 | if (future == null) { 32 | return Constants.NOTIFY_NO_SESSION; 33 | } else { 34 | return future.get(timeout, TimeUnit.MILLISECONDS) ? Constants.NOTIFY_SUCCESS : Constants.NOTIFY_FAILURE; 35 | } 36 | } catch (Exception e) { 37 | throw e; 38 | } 39 | } 40 | 41 | public void reply(MessageBuf.JMTransfer message) throws Exception { 42 | try { 43 | long seq = message.getSeq(); 44 | logger.info("reply seq -> " + seq + ", message -> " + ByteUtils.bytesToHexString(message.toByteArray())); 45 | final NotifyFuture future = this.futureMap.get(seq); 46 | if (future != null) { 47 | future.setSuccess(true); 48 | futureMap.remove(seq); 49 | logger.info("reply seq -> " + seq + " success."); 50 | } else { 51 | logger.info("reply seq -> " + seq + " expire."); 52 | } 53 | } catch (Exception e) { 54 | throw e; 55 | } 56 | } 57 | 58 | private NotifyFuture doSendAsync(long seq, MessageWrapper wrapper, int timeout) throws Exception { 59 | if (wrapper == null) { 60 | throw new Exception("wrapper cannot be null."); 61 | } 62 | String sessionId = wrapper.getSessionId(); 63 | if (StringUtils.isBlank(sessionId)) { 64 | throw new Exception("sessionId cannot be null."); 65 | } 66 | if (tcpConnector.exist(sessionId)) { 67 | // start. 68 | final NotifyFuture future = new NotifyFuture(timeout); 69 | this.futureMap.put(seq, future); 70 | 71 | logger.info("notify seq -> " + seq + ", sessionId -> " + sessionId); 72 | tcpConnector.send(sessionId, wrapper.getBody()); 73 | 74 | future.setSentTime(System.currentTimeMillis()); // 置为已发送 75 | return future; 76 | } else { 77 | // tcpConnector not exist sessionId 78 | return null; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## icloud-tcp-gateway 2 |

3 | 4 | 5 | 6 | 7 | 8 | 9 |

10 | 11 | #### 介绍 12 | 物联网设备网关技术架构设计(Session 管理、心跳管理、数据上行、数据下行) 13 | 14 | ![](https://images.gitee.com/uploads/images/2019/0116/150139_4377424a_1468963.png "屏幕截图.png") 15 | 16 | #### 说明 17 | 18 | NioEventLoop 是 Netty 的 Reactor 线程,其角色: 19 | 20 | 1. *Boss Group*:作为服务端 Acceptor 线程,用于 accept 客户端链接,并转发给 WorkerGroup 中的线程。 21 | 2. *Worker Group*:作为 IO 线程,负责 IO 的读写,从 SocketChannel 中读取报文或向 SocketChannel 写入报文。 22 | 3. *Task Queue/Delay Task Queue*:作为定时任务线程,执行定时任务,例如链路空闲检测和发送心跳消息等。 23 | 24 | ##### 概要说明 25 | - TcpServer :提供TCP连接服务 26 | - TcpSessionManager: 你可以添加监听事件,用于监听TCP会话创建、销毁等 27 | - LogSessionListener:一个日志监听器,它和tcpSessionManager关联,监听器必须事先 SessionListener 28 | - TcpSender:TCP发送者,用户向客户端发送消息通知、实现下行逻辑 29 | - ServerConfig: TCP 的配置管理类 30 | - TcpConnector: TCP 容器,用于管理服务和客户端的连接 31 | - NotifyProxy: 发送通知到代理类 32 | 33 | > 以上都是默认配置,你可以不修改,但是你可能需要换个TCP端口 34 | 35 | ### .TCP网关的网络结构 36 | 基于Netty构建TCP网关的长连接容器,作为网关接入层提供服务API请求调用。 37 | 38 | 客户端通过域名+端口访问TCP网关,域名不同的运营商对应不同的VIP,VIP发布在LVS上,LVS将请求转发给后端的HAProxy,再由HAProxy把请求转发给后端的Netty的IP+Port。 39 | 40 | LVS转发给后端的HAProxy,请求经过LVS,但是响应是HAProxy直接反馈给客户端的,这也就是LVS的DR模式。 41 | ![输入图片说明](https://images.gitee.com/uploads/images/2019/0926/103319_0f13ca35_1468963.png "c5da1236f6d6c151081a215ab3a3170c.png") 42 | #### TCP网关执行时序图 43 | ![输入图片说明](https://images.gitee.com/uploads/images/2019/0116/150230_e846b0a7_1468963.png "屏幕截图.png") 44 | 45 | 其中步骤一至步骤九是 Netty 服务端的创建时序,步骤十至步骤十三是 TCP 网关容器创建的时序。 46 | - **步骤一**:创建 ServerBootstrap 实例,ServerBootstrap 是 Netty 服务端的启动辅助类。 47 | - **步骤二**:设置并绑定 Reactor 线程池,EventLoopGroup 是 Netty 的 Reactor 线程池,EventLoop 负责所有注册到本线程的 Channel。 48 | - **步骤三**:设置并绑定服务器 Channel,Netty Server 需要创建 NioServerSocketChannel 对象。 49 | - **步骤四**:TCP 链接建立时创建 ChannelPipeline,ChannelPipeline 本质上是一个负责和执行 ChannelHandler 的职责链。 50 | - **步骤五**:添加并设置 ChannelHandler,ChannelHandler 串行的加入 ChannelPipeline 中。 51 | - **步骤六**:绑定监听端口并启动服务端,将 NioServerSocketChannel 注册到 Selector 上。 52 | - **步骤七**:Selector 轮训,由 EventLoop 负责调度和执行 Selector 轮询操作。 53 | - **步骤八**:执行网络请求事件通知,轮询准备就绪的 Channel,由 EventLoop 执行 ChannelPipeline。 54 | - **步骤九**:执行 Netty 系统和业务 ChannelHandler,依次调度并执行 ChannelPipeline 的 ChannelHandler。 55 | - **步骤十**:通过 Proxy 代理调用后端服务,ChannelRead 事件后,通过发射调度后端 Service。 56 | - **步骤十一**:创建 Session,Session 与 Connection 是相互依赖关系。 57 | - **步骤十二**:创建 Connection,Connection 保存 ChannelHandlerContext。 58 | - **步骤十三**:添加 SessionListener,SessionListener 监听 SessionCreate 和 SessionDestory 等事件。 59 | 60 | 61 | ### 程序运行案例步骤 62 | > 测试案例,三秒心跳包上传数据包 63 | 64 | ![输入图片说明](https://images.gitee.com/uploads/images/2019/0925/185216_0aa0fe1c_1468963.jpeg "icloud-tcp-gateway.jpg") 65 | #### 1.配置本地Host 66 | Window 地址 // C:\Windows\System32\drivers\etc\hosts 67 | 68 | 添加 69 | `` 127.0.0.1 iot-open.icloud.com `` 70 | 71 | #### 2.启动Server 72 | 位置: ``com.ibyte.iot.test.server.TestTcpServer`` 73 | 74 | #### 2.启动Client 75 | 位置: ``com.ibyte.iot.test.client.TcpClient`` 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/TcpConnector.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | import com.ibyte.iot.tcp.connector.tcp.listener.TcpHeartbeatListener; 5 | import com.ibyte.iot.tcp.message.MessageWrapper; 6 | 7 | import io.netty.channel.ChannelHandlerContext; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class TcpConnector extends ExchangeTcpConnector { 13 | 14 | private final static Logger logger = LoggerFactory.getLogger(TcpConnector.class); 15 | 16 | private TcpHeartbeatListener tcpHeartbeatListener = null; 17 | 18 | public void init() { 19 | tcpHeartbeatListener = new TcpHeartbeatListener(tcpSessionManager); 20 | 21 | Thread heartbeatThread = new Thread(tcpHeartbeatListener, "tcpHeartbeatListener"); 22 | heartbeatThread.setDaemon(true); 23 | heartbeatThread.start(); 24 | } 25 | 26 | public void destroy() { 27 | tcpHeartbeatListener.stop(); 28 | 29 | for (Session session : tcpSessionManager.getSessions()) { 30 | session.close(); 31 | } 32 | tcpSessionManager = null; 33 | } 34 | 35 | @Override 36 | public void connect(ChannelHandlerContext ctx, MessageWrapper wrapper) { 37 | try { 38 | Session session = tcpSessionManager.createSession(wrapper.getSessionId(), ctx); 39 | session.addSessionListener(tcpHeartbeatListener); 40 | session.connect(); 41 | 42 | tcpSessionManager.addSession(session); 43 | /** send **/ 44 | session.getConnection().send(wrapper.getBody()); 45 | } catch (Exception e) { 46 | logger.error("TcpConnector connect occur Exception.", e); 47 | } 48 | } 49 | 50 | @Override 51 | public void close(MessageWrapper wrapper) { 52 | Session session = tcpSessionManager.getSession(wrapper.getSessionId()); 53 | session.getConnection().send(wrapper.getBody()); 54 | session.close(); 55 | } 56 | 57 | @Override 58 | public void heartbeatClient(MessageWrapper wrapper) { 59 | try { 60 | tcpSessionManager.updateSession(wrapper.getSessionId()); 61 | Session session = tcpSessionManager.getSession(wrapper.getSessionId()); 62 | session.getConnection().send(wrapper.getBody()); 63 | } catch (Exception e) { 64 | logger.error("TcpConnector heartbeatClient occur Exception.", e); 65 | } 66 | } 67 | 68 | @Override 69 | public void responseSendMessage(MessageWrapper wrapper) { 70 | try { 71 | Session session = tcpSessionManager.getSession(wrapper.getSessionId()); 72 | session.getConnection().send(wrapper.getBody()); 73 | } catch (Exception e) { 74 | logger.error("TcpConnector responseSendMessage occur Exception.", e); 75 | } 76 | } 77 | 78 | @Override 79 | public void responseNoKeepAliveMessage(ChannelHandlerContext ctx, MessageWrapper wrapper) { 80 | try { 81 | NoKeepAliveTcpConnection connection = new NoKeepAliveTcpConnection(ctx); 82 | connection.send(wrapper.getBody()); 83 | } catch (Exception e) { 84 | logger.error("TcpConnector responseNoKeepAliveMessage occur Exception.", e); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/SessionValid.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * Created by Li.shangzhi on 17/1/10. 10 | */ 11 | public abstract class SessionValid implements Session { 12 | 13 | /** 14 | * We are currently processing a session create, so bypass certain 15 | * IllegalStateException tests. NOTE: This value is not included in the 16 | * serialized version of this object. 17 | */ 18 | protected transient volatile boolean connecting = false; 19 | 20 | /** 21 | * We are currently processing a session expiration, so bypass certain 22 | * IllegalStateException tests. NOTE: This value is not included in the 23 | * serialized version of this object. 24 | */ 25 | protected transient volatile boolean closing = false; 26 | 27 | /** 28 | * The time this session was created, in milliseconds since midnight, 29 | * January 1, 1970 GMT. 30 | */ 31 | protected long creationTime = 0L; 32 | 33 | /** 34 | * The last accessed time for this Session. 35 | */ 36 | protected volatile long lastAccessedTime = creationTime; 37 | 38 | /** 39 | * Flag indicating whether this session is valid or not. 40 | */ 41 | protected volatile boolean isValid = false; 42 | 43 | /** 44 | * The maximum time interval, in seconds, between client requests before the 45 | * container may invalidate this session. A negative time indicates that the 46 | * session should never time out. 47 | */ 48 | protected int maxInactiveInterval = 5 * 60; 49 | 50 | /** 51 | * The collection of user data attributes associated with this Session. 52 | */ 53 | protected Map attributes = new ConcurrentHashMap(); 54 | 55 | public boolean isValid() { 56 | if (closing) { 57 | return true; 58 | } 59 | return (isValid); 60 | } 61 | 62 | public void setValid(boolean isValid) { 63 | this.isValid = isValid; 64 | } 65 | 66 | public void setCreationTime(long creationTime) { 67 | this.creationTime = creationTime; 68 | } 69 | 70 | public long getCreationTime() { 71 | return creationTime; 72 | } 73 | 74 | public void setLastAccessedTime(long lastAccessedTime) { 75 | this.lastAccessedTime = lastAccessedTime; 76 | } 77 | 78 | public long getLastAccessedTime() { 79 | return lastAccessedTime; 80 | } 81 | 82 | public void setMaxInactiveInterval(int maxInactiveInterval) { 83 | this.maxInactiveInterval = maxInactiveInterval; 84 | } 85 | 86 | public int getMaxInactiveInterval() { 87 | return maxInactiveInterval; 88 | } 89 | 90 | public void setAttribute(String name, Object value) { 91 | if (!isValid()) { 92 | throw new IllegalStateException("[setAttribute]Session already invalidated"); 93 | } 94 | 95 | if (name == null) 96 | return; 97 | 98 | attributes.put(name, value); 99 | } 100 | 101 | public Object getAttribute(String name) { 102 | if (!isValid()) { 103 | throw new IllegalStateException("[getAttribute]Session already invalidated"); 104 | } 105 | 106 | if (name == null) 107 | return null; 108 | 109 | return (attributes.get(name)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/listener/TcpHeartbeatListener.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.listener; 2 | 3 | import com.ibyte.iot.tcp.connector.Session; 4 | import com.ibyte.iot.tcp.connector.api.listener.SessionEvent; 5 | import com.ibyte.iot.tcp.connector.api.listener.SessionListener; 6 | import com.ibyte.iot.tcp.connector.tcp.TcpSessionManager; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.concurrent.locks.Condition; 13 | import java.util.concurrent.locks.ReentrantLock; 14 | 15 | public class TcpHeartbeatListener implements Runnable, SessionListener { 16 | 17 | private final static Logger logger = LoggerFactory.getLogger(TcpHeartbeatListener.class); 18 | 19 | private TcpSessionManager tcpSessionManager = null; 20 | 21 | private ReentrantLock lock = new ReentrantLock(); 22 | private Condition notEmpty = lock.newCondition(); 23 | 24 | private int checkPeriod = 30 * 1000; 25 | private volatile boolean stop = false; 26 | 27 | public TcpHeartbeatListener(TcpSessionManager tcpSessionManager) { 28 | this.tcpSessionManager = tcpSessionManager; 29 | } 30 | 31 | public void run() { 32 | while (!stop) { 33 | if (isEmpty()) { 34 | awaitQueue(); 35 | } 36 | logger.info("TcpHeartbeatListener/online session count : " + tcpSessionManager.getSessionCount()); 37 | // sleep period 38 | try { 39 | Thread.sleep(checkPeriod); 40 | } catch (InterruptedException e) { 41 | logger.error("TcpHeartbeatListener run occur InterruptedException!", e); 42 | } 43 | // is stop 44 | if (stop) { 45 | break; 46 | } 47 | // 检测在线用户,多久没有发送心跳,超过规定时间的删除掉 48 | checkHeartBeat(); 49 | } 50 | } 51 | 52 | public void checkHeartBeat() { 53 | Session[] sessions = tcpSessionManager.getSessions(); 54 | for (Session session : sessions) { 55 | if (session.expire()) { 56 | session.close(); 57 | logger.info("heart is expire,clear sessionId:" + session.getSessionId()); 58 | } 59 | } 60 | } 61 | 62 | private boolean isEmpty() { 63 | return tcpSessionManager.getSessionCount() == 0; 64 | } 65 | 66 | private void awaitQueue() { 67 | boolean flag = lock.tryLock(); 68 | if (flag) { 69 | try { 70 | notEmpty.await(); 71 | } catch (InterruptedException e) { 72 | logger.error("TcpHeartbeatListener awaitQueue occur InterruptedException!", e); 73 | } catch (Exception e) { 74 | logger.error("await Thread Queue error!", e); 75 | } finally { 76 | lock.unlock(); 77 | } 78 | } 79 | } 80 | 81 | private void signalQueue() { 82 | boolean flag = false; 83 | try { 84 | flag = lock.tryLock(100, TimeUnit.MILLISECONDS); 85 | if (flag) 86 | notEmpty.signalAll(); 87 | } catch (InterruptedException e) { 88 | logger.error("TcpHeartbeatListener signalQueue occur InterruptedException!", e); 89 | } catch (Exception e) { 90 | logger.error("signal Thread Queue error!", e); 91 | } finally { 92 | if (flag) 93 | lock.unlock(); 94 | } 95 | } 96 | 97 | public void stop() { 98 | this.stop = true; 99 | } 100 | 101 | public void sessionCreated(SessionEvent se) { 102 | signalQueue(); 103 | } 104 | 105 | public void sessionDestroyed(SessionEvent se) { 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/TcpConnection.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp; 2 | 3 | import com.ibyte.iot.tcp.connector.api.ExchangeConnection; 4 | import com.ibyte.iot.tcp.exception.LostConnectException; 5 | import com.ibyte.iot.tcp.exception.PushException; 6 | 7 | import io.netty.channel.ChannelFuture; 8 | import io.netty.channel.ChannelFutureListener; 9 | import io.netty.channel.ChannelHandlerContext; 10 | import io.netty.channel.ChannelPromise; 11 | 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class TcpConnection extends ExchangeConnection { 16 | 17 | private final static Logger logger = LoggerFactory.getLogger(TcpConnection.class); 18 | 19 | private ChannelHandlerContext cxt; 20 | 21 | public TcpConnection(ChannelHandlerContext cxt) { 22 | this.cxt = cxt; 23 | } 24 | 25 | public void connect() { 26 | } 27 | 28 | public void close() { 29 | this.close = true; 30 | 31 | cxt.close(); 32 | logger.debug("the connection have been destroyed! ctx -> " + cxt.toString()); 33 | } 34 | 35 | public void send(T message) { 36 | if (message == null) 37 | return; 38 | 39 | sendMessage(message); 40 | } 41 | 42 | private void sendMessage(T message) { 43 | if (isClosed()) { 44 | PushException e = new PushException("Use a closed pushSocked!"); 45 | this.fireError(e); 46 | return; 47 | } 48 | pushMessage0(message); 49 | } 50 | 51 | private void pushMessage0(T message) { 52 | try { 53 | ChannelFuture cf = cxt.writeAndFlush(message); 54 | cf.addListener(new ChannelFutureListener() { 55 | @Override 56 | public void operationComplete(ChannelFuture future) throws PushException { 57 | if (future.isSuccess()) { 58 | logger.debug("send success."); 59 | } else { 60 | throw new PushException("Failed to send message."); 61 | } 62 | Throwable cause = future.cause(); 63 | if (cause != null) { 64 | throw new PushException(cause); 65 | } 66 | } 67 | }); 68 | } catch (LostConnectException e) { 69 | logger.error("TcpConnection pushMessage occur LostConnectException.", e); 70 | this.fireError(new PushException(e)); 71 | } catch (Exception e) { 72 | logger.error("TcpConnection pushMessage occur Exception.", e); 73 | this.fireError(new PushException("ChannelFuture " + connectionId + " ", e)); 74 | } catch (Throwable e) { 75 | logger.error("TcpConnection pushMessage occur Throwable.", e); 76 | this.fireError(new PushException("Failed to send message, cause: " + e.getMessage(), e)); 77 | } 78 | } 79 | 80 | private void pushMessage(T message) { 81 | boolean success = true; 82 | boolean sent = true; 83 | int timeout = 60; 84 | try { 85 | ChannelFuture cf = cxt.write(message); 86 | cxt.flush(); 87 | if (sent) { 88 | success = cf.await(timeout); 89 | } 90 | if (cf.isSuccess()) { 91 | logger.debug("send success."); 92 | } 93 | Throwable cause = cf.cause(); 94 | if (cause != null) { 95 | this.fireError(new PushException(cause)); 96 | } 97 | } catch (LostConnectException e) { 98 | logger.error("TcpConnection pushMessage occur LostConnectException.", e); 99 | this.fireError(new PushException(e)); 100 | } catch (Exception e) { 101 | logger.error("TcpConnection pushMessage occur Exception.", e); 102 | this.fireError(new PushException("ChannelFuture " + connectionId + " ", e)); 103 | } catch (Throwable e) { 104 | logger.error("TcpConnection pushMessage occur Throwable.", e); 105 | this.fireError(new PushException("Failed to send message, cause: " + e.getMessage(), e)); 106 | } 107 | if (!success) { 108 | this.fireError(new PushException("Failed to send message, in timeout(" + timeout + "ms) limit")); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.icloud.iot 6 | icloud-tcp-gateway 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | icloud-tcp-gateway 11 | 12 | 13 | UTF-8 14 | 3.2.1.RELEASE 15 | 16 | 17 | 18 | 19 | org.springframework 20 | spring-core 21 | ${org.springframework.version} 22 | 23 | 24 | org.springframework 25 | spring-expression 26 | ${org.springframework.version} 27 | 28 | 29 | org.springframework 30 | spring-beans 31 | ${org.springframework.version} 32 | 33 | 34 | org.springframework 35 | spring-aop 36 | ${org.springframework.version} 37 | 38 | 39 | org.springframework 40 | spring-context 41 | ${org.springframework.version} 42 | 43 | 44 | org.springframework 45 | spring-context-support 46 | ${org.springframework.version} 47 | 48 | 49 | org.springframework 50 | spring-tx 51 | ${org.springframework.version} 52 | 53 | 54 | org.springframework 55 | spring-jdbc 56 | ${org.springframework.version} 57 | 58 | 59 | org.springframework 60 | spring-orm 61 | ${org.springframework.version} 62 | 63 | 64 | org.springframework 65 | spring-oxm 66 | ${org.springframework.version} 67 | 68 | 69 | org.springframework 70 | spring-web 71 | ${org.springframework.version} 72 | 73 | 74 | org.springframework 75 | spring-aspects 76 | ${org.springframework.version} 77 | 78 | 79 | 80 | io.netty 81 | netty-all 82 | 83 | 4.0.24.Final 84 | 85 | 86 | 87 | com.google.protobuf 88 | protobuf-java 89 | 2.6.1 90 | 91 | 92 | 93 | ch.qos.logback 94 | logback-core 95 | 1.1.3 96 | 97 | 98 | ch.qos.logback 99 | logback-classic 100 | 1.1.3 101 | 102 | 103 | 104 | org.slf4j 105 | slf4j-api 106 | 1.7.13 107 | 108 | 109 | 110 | 111 | 112 | 113 | src/test/resources 114 | true 115 | 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-compiler-plugin 121 | 3.1 122 | 123 | 1.7 124 | 1.7 125 | 126 | 127 | 128 | org.apache.maven.plugins 129 | maven-source-plugin 130 | 2.2.1 131 | 132 | 133 | attach-sources 134 | 135 | jar 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/notify/NotifyFuture.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.notify; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | public class NotifyFuture implements java.util.concurrent.Future { 6 | 7 | private final int timeout; 8 | 9 | private volatile Object result; 10 | 11 | private short waiters; 12 | 13 | /** 14 | * Future生成时间 15 | */ 16 | private final long genTime = System.currentTimeMillis(); 17 | /** 18 | * Future已发送时间 19 | */ 20 | private volatile long sentTime; 21 | 22 | public NotifyFuture(int timeout) { 23 | this.timeout = timeout; 24 | } 25 | 26 | public boolean cancel(boolean mayInterruptIfRunning) { 27 | Object result = this.result; 28 | if (isDone0(result)) { 29 | return false; 30 | } 31 | synchronized (this) { 32 | // Allow only once 33 | result = this.result; 34 | if (isDone0(result)) { 35 | return false; 36 | } 37 | if (hasWaiters()) { 38 | notifyAll(); 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | public boolean isCancelled() { 45 | return false; 46 | } 47 | 48 | public boolean isDone() { 49 | return isDone0(result); 50 | } 51 | 52 | public boolean isDone0(Object result) { 53 | return result != null && (Boolean) result; 54 | } 55 | 56 | public V get() throws InterruptedException { 57 | return get(timeout, TimeUnit.MILLISECONDS); 58 | } 59 | 60 | public V get(long timeout, TimeUnit unit) throws InterruptedException { 61 | timeout = unit.toMillis(timeout); // Turn to milliseconds 62 | long remainTime = timeout - (sentTime - genTime); // Residual time 63 | if (remainTime <= 0) { // There is no time to wait 64 | if (isDone()) { // Directly to see if it has been returned 65 | return getNow(); 66 | } 67 | } else { // Waiting for the rest of time 68 | if (await(remainTime, TimeUnit.MILLISECONDS)) { 69 | return getNow(); 70 | } 71 | } 72 | throw new InterruptedException("wait reply timeout."); 73 | } 74 | 75 | public V getNow() { 76 | Object result = this.result; 77 | return (V) result; 78 | } 79 | 80 | public boolean isSuccess() { 81 | Object result = this.result; 82 | if (result == null) { 83 | return false; 84 | } 85 | return (Boolean) result; 86 | } 87 | 88 | public boolean await(long timeout, TimeUnit unit) throws InterruptedException { 89 | return await0(unit.toNanos(timeout), true); 90 | } 91 | 92 | private boolean await0(long timeoutNanos, boolean interruptAble) throws InterruptedException { 93 | if (isDone()) { 94 | return true; 95 | } 96 | if (timeoutNanos <= 0) { 97 | return isDone(); 98 | } 99 | if (interruptAble && Thread.interrupted()) { 100 | throw new InterruptedException(toString()); 101 | } 102 | 103 | long startTime = System.nanoTime(); 104 | long waitTime = timeoutNanos; 105 | boolean interrupted = false; 106 | 107 | try { 108 | synchronized (this) { 109 | if (isDone()) { 110 | return true; 111 | } 112 | if (waitTime <= 0) { 113 | return isDone(); 114 | } 115 | 116 | incWaiters(); 117 | try { 118 | for (; ; ) { 119 | try { 120 | wait(waitTime / 1000000, (int) (waitTime % 1000000)); 121 | } catch (InterruptedException e) { 122 | if (interruptAble) { 123 | throw e; 124 | } else { 125 | interrupted = true; 126 | } 127 | } 128 | if (isDone()) { 129 | return true; 130 | } else { 131 | waitTime = timeoutNanos - (System.nanoTime() - startTime); 132 | if (waitTime <= 0) { 133 | return isDone(); 134 | } 135 | } 136 | } 137 | } finally { 138 | decWaiters(); 139 | } 140 | } 141 | } finally { 142 | if (interrupted) { 143 | Thread.currentThread().interrupt(); 144 | } 145 | } 146 | } 147 | 148 | public NotifyFuture setSuccess(V result) { 149 | if (setSuccess0(result)) { 150 | return this; 151 | } 152 | throw new IllegalStateException("complete already: " + this); 153 | } 154 | 155 | private boolean setSuccess0(V result) { 156 | if (isDone()) { 157 | return false; 158 | } 159 | synchronized (this) { 160 | // Allow only once 161 | if (isDone()) { 162 | return false; 163 | } 164 | if (this.result == null) { 165 | this.result = result; 166 | } 167 | if (hasWaiters()) { 168 | notifyAll(); 169 | } 170 | } 171 | return true; 172 | } 173 | 174 | public NotifyFuture setFailure(Throwable cause) { 175 | if (setFailure0(cause)) { 176 | return this; 177 | } 178 | throw new IllegalStateException("complete already: " + this, cause); 179 | } 180 | 181 | private boolean setFailure0(Throwable cause) { 182 | if (isDone()) { 183 | return false; 184 | } 185 | synchronized (this) { 186 | // Allow only once 187 | if (isDone()) { 188 | return false; 189 | } 190 | result = false; 191 | if (hasWaiters()) { 192 | notifyAll(); 193 | } 194 | } 195 | return true; 196 | } 197 | 198 | private boolean hasWaiters() { 199 | return waiters > 0; 200 | } 201 | 202 | private void incWaiters() { 203 | if (waiters == Short.MAX_VALUE) { 204 | throw new IllegalStateException("too many waiters:" + this); 205 | } 206 | waiters++; 207 | } 208 | 209 | private void decWaiters() { 210 | waiters--; 211 | } 212 | 213 | public int getTimeout() { 214 | return timeout; 215 | } 216 | 217 | /** 218 | * 设置已发送时间 219 | * 220 | * @param sentTime 已发送时间 221 | */ 222 | public void setSentTime(long sentTime) { 223 | this.sentTime = sentTime; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/api/ExchangeSession.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.api; 2 | 3 | import com.ibyte.iot.tcp.connector.Connection; 4 | import com.ibyte.iot.tcp.connector.SessionManager; 5 | import com.ibyte.iot.tcp.connector.api.listener.SessionEvent; 6 | import com.ibyte.iot.tcp.connector.api.listener.SessionListener; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.List; 12 | import java.util.concurrent.CopyOnWriteArrayList; 13 | 14 | /** 15 | * Created by Li.shangzhi on 17/1/10. 16 | */ 17 | public class ExchangeSession extends SessionValid { 18 | 19 | private final static Logger logger = LoggerFactory.getLogger(ExchangeSession.class); 20 | 21 | /** 22 | * The session identifier of this Session. 23 | */ 24 | private String sessionId = null; 25 | 26 | private transient List listeners = new CopyOnWriteArrayList(); 27 | 28 | private transient Connection connection = null; 29 | 30 | /** 31 | * The Manager with which this Session is associated. 32 | */ 33 | private transient SessionManager sessionManager = null; 34 | 35 | public void access() { 36 | // Check to see if access is in progress or has previously been called 37 | if (!isValid) { 38 | return; 39 | } 40 | lastAccessedTime = System.currentTimeMillis(); 41 | } 42 | 43 | public void connect() { 44 | // Check to see if tellNew is in progress or has previously been called 45 | if (connecting || !isValid) { 46 | logger.debug("the session " + sessionId + " is connecting or isValid = false!"); 47 | return; 48 | } 49 | connecting = true; 50 | connection.connect(); 51 | addSessionEvent(); 52 | 53 | connecting = false; 54 | logger.debug("the session " + sessionId + " is ready!"); 55 | } 56 | 57 | private void addSessionEvent() { 58 | SessionEvent event = new SessionEvent(this); 59 | for (SessionListener listener : listeners) { 60 | try { 61 | listener.sessionCreated(event); 62 | logger.info("SessionListener " + listener + " .sessionCreated() is invoked successfully!"); 63 | } catch (Exception e) { 64 | logger.error("addSessionEvent error.", e); 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Perform the internal processing required to invalidate this session, 71 | * without triggering an exception if the session has already expired. 72 | */ 73 | public void close() { 74 | close(true); 75 | } 76 | 77 | /** 78 | * Perform the internal processing required to invalidate this session, 79 | * without triggering an exception if the session has already expired. 80 | * 81 | * @param notify Should we notify listeners about the demise of this session? 82 | */ 83 | void close(boolean notify) { 84 | // Check to see if close is in progress or has previously been called 85 | if (closing || !isValid) { 86 | logger.debug("the session " + sessionId + " is closing or isValid = false!"); 87 | return; 88 | } 89 | synchronized (this) { 90 | // Check again, now we are inside the sync so this code only runs 91 | // once 92 | // Double check locking - closing and isValid need to be volatile 93 | if (closing || !isValid) { 94 | logger.debug("the session " + sessionId + " is closing or isValid = false!"); 95 | return; 96 | } 97 | // Mark this session as "being closed" 98 | closing = true; 99 | if (notify) { 100 | SessionEvent event = new SessionEvent(this); 101 | for (SessionListener listener : listeners) { 102 | try { 103 | listener.sessionDestroyed(event); 104 | logger.debug("SessionListener " + listener + " .sessionDestroyed() is invoked successfully!"); 105 | } catch (Exception e) { 106 | logger.error("sessionDestroyed error! " + e); 107 | } 108 | } 109 | } 110 | setValid(false); 111 | 112 | connection.close(); 113 | 114 | recycle(); 115 | // We have completed close of this session 116 | closing = false; 117 | logger.debug("the session " + sessionId + " have been destroyed!"); 118 | } 119 | } 120 | 121 | /** 122 | * Release all object references, and initialize instance variables, in 123 | * preparation for reuse of this object. 124 | */ 125 | public void recycle() { 126 | logger.debug("the session " + sessionId + " is recycled!"); 127 | // Remove this session from our manager's active sessions 128 | sessionManager.removeSession(this); 129 | 130 | // Reset the instance variables associated with this Session 131 | listeners.clear(); 132 | listeners = null; 133 | creationTime = 0L; 134 | connecting = false; 135 | closing = false; 136 | sessionId = null; 137 | lastAccessedTime = 0L; 138 | maxInactiveInterval = -1; 139 | isValid = false; 140 | sessionManager = null; 141 | } 142 | 143 | public boolean expire() { 144 | //A negative time indicates that the session should never time out. 145 | if (maxInactiveInterval < 0) 146 | return false; 147 | 148 | long timeNow = System.currentTimeMillis(); 149 | int timeIdle = (int) ((timeNow - lastAccessedTime) / 1000L); 150 | if (timeIdle >= maxInactiveInterval) { 151 | return true; 152 | } 153 | return false; 154 | } 155 | 156 | /** 157 | * Add a session event listener to this component. 158 | */ 159 | public void addSessionListener(SessionListener listener) { 160 | if (null == listener) { 161 | throw new IllegalArgumentException("addSessionListener listener"); 162 | } 163 | listeners.add(listener); 164 | } 165 | 166 | /** 167 | * Remove a session event listener from this component. 168 | */ 169 | public void removeSessionListener(SessionListener listener) { 170 | if (listener == null) { 171 | throw new IllegalArgumentException("removeSessionListener listener"); 172 | } 173 | listeners.remove(listener); 174 | } 175 | 176 | public void setSessionId(String sessionId) { 177 | this.sessionId = sessionId; 178 | } 179 | 180 | public String getSessionId() { 181 | return sessionId; 182 | } 183 | 184 | public void setSessionManager(SessionManager sessionManager) { 185 | this.sessionManager = sessionManager; 186 | } 187 | 188 | public SessionManager getSessionManager() { 189 | return sessionManager; 190 | } 191 | 192 | public void setConnection(Connection connection) { 193 | this.connection = connection; 194 | } 195 | 196 | public Connection getConnection() { 197 | return this.connection; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/server/TcpServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.server; 2 | 3 | import com.ibyte.iot.tcp.connector.tcp.TcpConnector; 4 | import com.ibyte.iot.tcp.connector.tcp.codec.MessageBuf; 5 | import com.ibyte.iot.tcp.connector.tcp.config.ServerTransportConfig; 6 | import com.ibyte.iot.tcp.constant.Constants; 7 | import com.ibyte.iot.tcp.invoke.ApiProxy; 8 | import com.ibyte.iot.tcp.message.MessageWrapper; 9 | import com.ibyte.iot.tcp.message.SystemMessage; 10 | import com.ibyte.iot.tcp.notify.NotifyProxy; 11 | import com.ibyte.iot.tcp.utils.NetUtils; 12 | 13 | import io.netty.channel.ChannelHandler; 14 | import io.netty.channel.ChannelHandlerContext; 15 | import io.netty.channel.ChannelInboundHandlerAdapter; 16 | 17 | import org.apache.commons.lang.StringUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.net.InetSocketAddress; 22 | import java.net.SocketAddress; 23 | 24 | //public class TcpServerHandler extends ChannelHandlerAdapter { 25 | @ChannelHandler.Sharable 26 | public class TcpServerHandler extends ChannelInboundHandlerAdapter { 27 | 28 | private final static Logger logger = LoggerFactory.getLogger(TcpServerHandler.class); 29 | 30 | private TcpConnector tcpConnector = null; 31 | private ApiProxy proxy = null; 32 | private NotifyProxy notify = null; 33 | 34 | public TcpServerHandler(ServerTransportConfig config) { 35 | this.tcpConnector = config.getTcpConnector(); 36 | this.proxy = config.getProxy(); 37 | this.notify = config.getNotify(); 38 | } 39 | 40 | public void channelRead(ChannelHandlerContext ctx, Object o) throws Exception { 41 | try { 42 | if (o instanceof MessageBuf.JMTransfer) { 43 | SystemMessage sMsg = generateSystemMessage(ctx); 44 | MessageBuf.JMTransfer message = (MessageBuf.JMTransfer) o; 45 | // inbound 46 | if (message.getFormat() == SEND) { 47 | MessageWrapper wrapper = proxy.invoke(sMsg, message); 48 | if (wrapper != null) 49 | this.receive(ctx, wrapper); 50 | } 51 | // outbound 52 | if (message.getFormat() == REPLY) { 53 | notify.reply(message); 54 | } 55 | } else { 56 | logger.warn("TcpServerHandler channelRead message is not proto."); 57 | } 58 | } catch (Exception e) { 59 | logger.error("TcpServerHandler TcpServerHandler handler error.", e); 60 | throw e; 61 | } 62 | } 63 | 64 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 65 | logger.debug("TcpServerHandler Connected from {" + 66 | NetUtils.channelToString(ctx.channel().remoteAddress(), ctx.channel().localAddress()) + "}"); 67 | } 68 | 69 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 70 | logger.debug("TcpServerHandler Disconnected from {" + 71 | NetUtils.channelToString(ctx.channel().remoteAddress(), ctx.channel().localAddress()) + "}"); 72 | } 73 | 74 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 75 | super.channelActive(ctx); 76 | logger.debug("TcpServerHandler channelActive from (" + getRemoteAddress(ctx) + ")"); 77 | } 78 | 79 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 80 | super.channelInactive(ctx); 81 | logger.debug("TcpServerHandler channelInactive from (" + getRemoteAddress(ctx) + ")"); 82 | String sessionId0 = getChannelSessionHook(ctx); 83 | if (StringUtils.isNotBlank(sessionId0)) { 84 | tcpConnector.close(new MessageWrapper(MessageWrapper.MessageProtocol.CLOSE, sessionId0, null)); 85 | logger.warn("TcpServerHandler channelInactive, close channel sessionId0 -> " + sessionId0 + ", ctx -> " + ctx.toString()); 86 | } 87 | } 88 | 89 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 90 | logger.warn("TcpServerHandler (" + getRemoteAddress(ctx) + ") -> Unexpected exception from downstream." + cause); 91 | String sessionId0 = getChannelSessionHook(ctx); 92 | if (StringUtils.isNotBlank(sessionId0)) { 93 | logger.error("TcpServerHandler exceptionCaught (sessionId0 -> " + sessionId0 + ", ctx -> " + ctx.toString() + ") -> Unexpected exception from downstream." + cause); 94 | } 95 | } 96 | 97 | private String getChannelSessionHook(ChannelHandlerContext ctx) { 98 | return ctx.channel().attr(Constants.SERVER_SESSION_HOOK).get(); 99 | } 100 | 101 | private void setChannelSessionHook(ChannelHandlerContext ctx, String sessionId) { 102 | ctx.channel().attr(Constants.SERVER_SESSION_HOOK).set(sessionId); 103 | } 104 | 105 | final int SEND = 1; 106 | final int RECEIVE = 2; 107 | final int NOTIFY = 3; 108 | final int REPLY = 4; 109 | 110 | /** 111 | * to send client and receive the message 112 | * 113 | * @param ctx 114 | * @param wrapper 115 | */ 116 | private void receive(ChannelHandlerContext ctx, MessageWrapper wrapper) { 117 | if (wrapper.isConnect()) { 118 | isConnect0(ctx, wrapper); 119 | } else if (wrapper.isClose()) { 120 | tcpConnector.close(wrapper); 121 | } else if (wrapper.isHeartbeat()) { 122 | tcpConnector.heartbeatClient(wrapper); 123 | } else if (wrapper.isSend()) { 124 | tcpConnector.responseSendMessage(wrapper); 125 | } else if (wrapper.isNoKeepAliveMessage()) { 126 | tcpConnector.responseNoKeepAliveMessage(ctx, wrapper); 127 | } 128 | } 129 | 130 | private void isConnect0(ChannelHandlerContext ctx, MessageWrapper wrapper) { 131 | String sessionId = wrapper.getSessionId(); 132 | String sessionId0 = getChannelSessionHook(ctx); 133 | if (sessionId.equals(sessionId0)) { 134 | logger.info("tcpConnector reconnect sessionId -> " + sessionId + ", ctx -> " + ctx.toString()); 135 | tcpConnector.responseSendMessage(wrapper); 136 | } else { 137 | logger.info("tcpConnector connect sessionId -> " + sessionId + ", sessionId0 -> " + sessionId0 + ", ctx -> " + ctx.toString()); 138 | tcpConnector.connect(ctx, wrapper); 139 | setChannelSessionHook(ctx, sessionId); 140 | logger.info("create channel attr sessionId " + sessionId + " successful, ctx -> " + ctx.toString()); 141 | } 142 | } 143 | 144 | private SystemMessage generateSystemMessage(ChannelHandlerContext ctx) { 145 | SystemMessage systemMessage = new SystemMessage(); 146 | systemMessage.setRemoteAddress(getRemoteAddress(ctx)); 147 | systemMessage.setLocalAddress(getLocalAddress(ctx)); 148 | 149 | return systemMessage; 150 | } 151 | 152 | private String getRemoteAddress(ChannelHandlerContext ctx) { 153 | SocketAddress remote1 = ctx.channel().remoteAddress(); 154 | InetSocketAddress remote = (InetSocketAddress) remote1; 155 | return NetUtils.toAddressString(remote); 156 | } 157 | 158 | private String getLocalAddress(ChannelHandlerContext ctx) { 159 | SocketAddress local1 = ctx.channel().localAddress(); 160 | InetSocketAddress local = (InetSocketAddress) local1; 161 | return NetUtils.toAddressString(local); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/utils/NetUtils.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.utils; 2 | 3 | import com.ibyte.iot.tcp.constant.Constants; 4 | import com.ibyte.iot.tcp.exception.InitErrorException; 5 | 6 | import io.netty.channel.Channel; 7 | 8 | import org.apache.commons.lang.StringUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.io.IOException; 13 | import java.net.*; 14 | import java.util.ArrayList; 15 | import java.util.Enumeration; 16 | import java.util.List; 17 | import java.util.regex.Pattern; 18 | 19 | public class NetUtils { 20 | 21 | private final static Logger logger = LoggerFactory.getLogger(NetUtils.class); 22 | 23 | /** 24 | * 最小端口 25 | */ 26 | private static final int MIN_PORT = 0; 27 | /** 28 | * 最大端口 29 | */ 30 | private static final int MAX_PORT = 65535; 31 | 32 | /** 33 | * 判断端口是否有效 0-65535 34 | * 35 | * @param port 端口 36 | * @return 是否有效 37 | */ 38 | public static boolean isInvalidPort(int port) { 39 | return port > MAX_PORT || port < MIN_PORT; 40 | } 41 | 42 | /** 43 | * 判断端口是否随机端口 小于0表示随机 44 | * 45 | * @param port 端口 46 | * @return 是否随机端口 47 | */ 48 | public static boolean isRandomPort(int port) { 49 | return port < 0; 50 | } 51 | 52 | /** 53 | * 检查当前指定端口是否可用,不可用则自动+1再试(随机端口从默认端口开始检查) 54 | * 55 | * @param host 当前ip地址 56 | * @param port 当前指定端口 57 | * @return 从指定端口开始后第一个可用的端口 58 | */ 59 | public static int getAvailablePort(String host, int port) { 60 | if (isAnyHost(host) 61 | || isLocalHost(host) 62 | || isHostInNetworkCard(host)) { 63 | } else { 64 | throw new InitErrorException("The host " + host 65 | + " is not found in network cards, please check config"); 66 | } 67 | if (port < MIN_PORT) { 68 | port = Constants.DEFAULT_SERVER_PORT; 69 | } 70 | for (int i = port; i <= MAX_PORT; i++) { 71 | ServerSocket ss = null; 72 | try { 73 | ss = new ServerSocket(); 74 | ss.bind(new InetSocketAddress(host, i)); 75 | logger.debug("ip:{} port:{" + host + "} is available" + i); 76 | return i; 77 | } catch (IOException e) { 78 | // continue 79 | logger.warn("Can't bind to address [{" + host + "}:{" + i + "}], " + 80 | "Maybe 1) The port has been bound. " + 81 | "2) The network card of this host is not exists or disable. " + 82 | "3) The host is wrong."); 83 | logger.info("Begin try next port(auto +1):{" + i + 1 + "}"); 84 | } finally { 85 | if (ss != null) { 86 | try { 87 | ss.close(); 88 | } catch (IOException e) { 89 | } 90 | } 91 | } 92 | } 93 | throw new InitErrorException("Can't bind to ANY port of " + host + ", please check config"); 94 | } 95 | 96 | /** 97 | * 任意地址 98 | */ 99 | public static final String ANYHOST = "0.0.0.0"; 100 | 101 | private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); 102 | 103 | /** 104 | * IPv4地址 105 | */ 106 | public static final Pattern IPV4_PATTERN = Pattern.compile( 107 | "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$"); 108 | 109 | /** 110 | * 是否本地地址 127.x.x.x 或者 localhost 111 | * 112 | * @param host 地址 113 | * @return 是否本地地址 114 | */ 115 | public static boolean isLocalHost(String host) { 116 | return StringUtils.isNotBlank(host) 117 | && (LOCAL_IP_PATTERN.matcher(host).matches() || "localhost".equalsIgnoreCase(host)); 118 | } 119 | 120 | /** 121 | * 是否默认地址 0.0.0.0 122 | * 123 | * @param host 地址 124 | * @return 是否默认地址 125 | */ 126 | public static boolean isAnyHost(String host) { 127 | return ANYHOST.equals(host); 128 | } 129 | 130 | /** 131 | * 是否IPv4地址 0.0.0.0 132 | * 133 | * @param host 地址 134 | * @return 是否默认地址 135 | */ 136 | public static boolean isIPv4Host(String host) { 137 | return StringUtils.isNotBlank(host) 138 | && IPV4_PATTERN.matcher(host).matches(); 139 | } 140 | 141 | /** 142 | * 是否非法地址(本地或默认) 143 | * 144 | * @param host 地址 145 | * @return 是否非法地址 146 | */ 147 | private static boolean isInvalidLocalHost(String host) { 148 | return StringUtils.isBlank(host) 149 | || isAnyHost(host) 150 | || isLocalHost(host); 151 | } 152 | 153 | /** 154 | * 是否合法地址(非本地,非默认的IPv4地址) 155 | * 156 | * @param address InetAddress 157 | * @return 是否合法 158 | */ 159 | private static boolean isValidAddress(InetAddress address) { 160 | if (address == null || address.isLoopbackAddress()) 161 | return false; 162 | String name = address.getHostAddress(); 163 | return (name != null 164 | && !isAnyHost(name) 165 | && !isLocalHost(name) 166 | && isIPv4Host(name)); 167 | } 168 | 169 | /** 170 | * 是否网卡上的地址 171 | * 172 | * @param host 地址 173 | * @return 是否默认地址 174 | */ 175 | public static boolean isHostInNetworkCard(String host) { 176 | try { 177 | InetAddress addr = InetAddress.getByName(host); 178 | return NetworkInterface.getByInetAddress(addr) != null; 179 | } catch (Exception e) { 180 | return false; 181 | } 182 | } 183 | 184 | /** 185 | * 得到本机IPv4地址 186 | * 187 | * @return ip地址 188 | */ 189 | public static String getLocalHost() { 190 | InetAddress address = getLocalAddress(); 191 | return address == null ? null : address.getHostAddress(); 192 | } 193 | 194 | /** 195 | * 遍历本地网卡,返回第一个合理的IP,保存到缓存中 196 | * 197 | * @return 本地网卡IP 198 | */ 199 | public static InetAddress getLocalAddress() { 200 | InetAddress localAddress = null; 201 | try { 202 | localAddress = InetAddress.getLocalHost(); 203 | if (isValidAddress(localAddress)) { 204 | return localAddress; 205 | } 206 | } catch (Throwable e) { 207 | logger.warn("Error when retriving ip address: " + e.getMessage(), e); 208 | } 209 | try { 210 | Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); 211 | if (interfaces != null) { 212 | while (interfaces.hasMoreElements()) { 213 | try { 214 | NetworkInterface network = interfaces.nextElement(); 215 | Enumeration addresses = network.getInetAddresses(); 216 | if (addresses != null) { 217 | while (addresses.hasMoreElements()) { 218 | try { 219 | InetAddress address = addresses.nextElement(); 220 | if (isValidAddress(address)) { 221 | return address; 222 | } 223 | } catch (Throwable e) { 224 | logger.warn("Error when retriving ip address: " + e.getMessage(), e); 225 | } 226 | } 227 | } 228 | } catch (Throwable e) { 229 | logger.warn("Error when retriving ip address: " + e.getMessage(), e); 230 | } 231 | } 232 | } 233 | } catch (Throwable e) { 234 | logger.warn("Error when retriving ip address: " + e.getMessage(), e); 235 | } 236 | logger.error("Can't get valid host, will use 127.0.0.1 instead."); 237 | return localAddress; 238 | } 239 | 240 | /** 241 | * InetSocketAddress转 host:port 字符串 242 | * 243 | * @param address InetSocketAddress转 244 | * @return host:port 字符串 245 | */ 246 | public static String toAddressString(InetSocketAddress address) { 247 | if (address == null) { 248 | return StringUtils.EMPTY; 249 | } else { 250 | return toIpString(address) + ":" + address.getPort(); 251 | } 252 | } 253 | 254 | /** 255 | * 得到ip地址 256 | * 257 | * @param address InetSocketAddress 258 | * @return ip地址 259 | */ 260 | public static String toIpString(InetSocketAddress address) { 261 | if (address == null) { 262 | return null; 263 | } else { 264 | InetAddress inetAddress = address.getAddress(); 265 | return inetAddress == null ? address.getHostName() : 266 | inetAddress.getHostAddress(); 267 | } 268 | } 269 | 270 | /** 271 | * 本地多ip情况下、连一下注册中心地址得到本地IP地址 272 | * 273 | * @param registryIp 注册中心地址 274 | * @return 本地多ip情况下得到本地能连上注册中心的IP地址 275 | */ 276 | public static String getLocalHostByRegistry(String registryIp) { 277 | String host = null; 278 | if (registryIp != null && registryIp.length() > 0) { 279 | List addrs = getIpListByRegistry(registryIp); 280 | for (int i = 0; i < addrs.size(); i++) { 281 | InetAddress address = getLocalHostBySocket(addrs.get(i)); 282 | if (address != null) { 283 | host = address.getHostAddress(); 284 | if (host != null && !NetUtils.isInvalidLocalHost(host)) { 285 | return host; 286 | } 287 | } 288 | } 289 | } 290 | if (NetUtils.isInvalidLocalHost(host)) { 291 | host = NetUtils.getLocalHost(); 292 | } 293 | return host; 294 | } 295 | 296 | /** 297 | * 通过连接远程地址得到本机内网地址 298 | * 299 | * @param remoteAddress 远程地址 300 | * @return 本机内网地址 301 | */ 302 | private static InetAddress getLocalHostBySocket(InetSocketAddress remoteAddress) { 303 | InetAddress host = null; 304 | try { 305 | // 去连一下远程地址 306 | Socket socket = new Socket(); 307 | try { 308 | socket.connect(remoteAddress, 1000); 309 | // 得到本地地址 310 | host = socket.getLocalAddress(); 311 | } finally { 312 | try { 313 | socket.close(); 314 | } catch (Throwable e) { 315 | logger.warn("NetUtils getLocalHostBySocket occur Exception!", e); 316 | } 317 | } 318 | } catch (Exception e) { 319 | logger.warn("Can not connect to host {" + remoteAddress.toString() + "}, cause by :{" + e.getMessage() + "}"); 320 | } 321 | return host; 322 | } 323 | 324 | /** 325 | * 解析注册中心地址配置为多个连接地址 326 | * 327 | * @param registryIp 注册中心地址 328 | * @return 329 | */ 330 | public static List getIpListByRegistry(String registryIp) { 331 | List ips = new ArrayList(); 332 | String defaultPort = null; 333 | 334 | String[] srcIps = registryIp.split(","); 335 | for (String add : srcIps) { 336 | int a = add.indexOf("://"); 337 | if (a > -1) { 338 | add = add.substring(a + 3); // 去掉协议头 339 | } 340 | String[] s1 = add.split(":"); 341 | if (s1.length > 1) { 342 | if (defaultPort == null && s1[1] != null && s1[1].length() > 0) { 343 | defaultPort = s1[1]; 344 | } 345 | ips.add(new String[]{s1[0], s1[1]}); // 得到ip和端口 346 | } else { 347 | ips.add(new String[]{s1[0], defaultPort}); 348 | } 349 | } 350 | 351 | List ads = new ArrayList(); 352 | for (int j = 0; j < ips.size(); j++) { 353 | String[] ip = ips.get(j); 354 | try { 355 | InetSocketAddress address = new InetSocketAddress(ip[0], 356 | Integer.parseInt(ip[1] == null ? defaultPort : ip[1])); 357 | ads.add(address); 358 | } catch (Exception e) { 359 | logger.warn("NetUtils getIpListByRegistry occur Exception!", e); 360 | } 361 | } 362 | 363 | return ads; 364 | } 365 | 366 | /** 367 | * 判断当前ip是否符合白名单 368 | * 369 | * @param whitelist 白名单,可以配置为* 370 | * @param localIP 当前地址 371 | * @return 372 | */ 373 | public static boolean isMatchIPByPattern(String whitelist, String localIP) { 374 | if (StringUtils.isNotBlank(whitelist)) { 375 | if ("*".equals(whitelist)) { 376 | return true; 377 | } 378 | for (String ips : whitelist.replace(',', ';').split(";", -1)) { 379 | try { 380 | if (ips.contains("*")) { // 带通配符 381 | String regex = ips.trim().replace(".", "\\.").replace("*", ".*"); 382 | Pattern pattern = Pattern.compile(regex); 383 | if (pattern.matcher(localIP).find()) { 384 | return true; 385 | } 386 | } else if (!isIPv4Host(ips)) { // 不带通配符的正则表达式 387 | String regex = ips.trim().replace(".", "\\."); 388 | Pattern pattern = Pattern.compile(regex); 389 | if (pattern.matcher(localIP).find()) { 390 | return true; 391 | } 392 | } else { 393 | if (ips.equals(localIP)) { 394 | return true; 395 | } 396 | } 397 | } catch (Exception e) { 398 | logger.warn("syntax of pattern {" + ips + "} is invalid"); 399 | } 400 | } 401 | } 402 | return false; 403 | } 404 | 405 | /** 406 | * 连接转字符串 407 | * 408 | * @param local 本地地址 409 | * @param remote 远程地址 410 | * @return 411 | */ 412 | public static String connectToString(InetSocketAddress local, InetSocketAddress remote) { 413 | return toAddressString(local) + " <-> " + toAddressString(remote); 414 | } 415 | 416 | /** 417 | * 连接转字符串 418 | * 419 | * @param local1 本地地址 420 | * @param remote1 远程地址 421 | * @return 422 | */ 423 | public static String channelToString(SocketAddress local1, SocketAddress remote1) { 424 | try { 425 | InetSocketAddress local = (InetSocketAddress) local1; 426 | InetSocketAddress remote = (InetSocketAddress) remote1; 427 | return toAddressString(local) + " -> " + toAddressString(remote); 428 | } catch (Exception e) { 429 | return local1 + "->" + remote1; 430 | } 431 | } 432 | 433 | /** 434 | * 是否可以telnet 435 | * 436 | * @param ip 远程地址 437 | * @param port 远程端口 438 | * @param timeout 连接超时 439 | * @return 是否可连接 440 | */ 441 | public static boolean canTelnet(String ip, int port, int timeout) { 442 | Socket socket = null; 443 | try { 444 | socket = new Socket(); 445 | socket.connect(new InetSocketAddress(ip, port), timeout); 446 | return socket.isConnected(); 447 | } catch (Exception e) { 448 | logger.warn("NetUtils canTelnet occur Exception!", e); 449 | return false; 450 | } finally { 451 | if (socket != null) { 452 | try { 453 | socket.close(); 454 | } catch (IOException e) { 455 | } 456 | } 457 | } 458 | } 459 | 460 | public static String getTransportKey(String ip, int port) { 461 | return ip + "::" + port; 462 | } 463 | 464 | public static String getClientTransportKey(String protocolName, String ip, int port) { 465 | return protocolName + "::" + ip + "::" + port; 466 | } 467 | 468 | public static String getTransportKey(Channel channel) { 469 | InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); 470 | String remoteIp = NetUtils.toIpString(address); 471 | int port = address.getPort(); 472 | return getTransportKey(remoteIp, port); 473 | } 474 | } -------------------------------------------------------------------------------- /src/main/java/com/ibyte/iot/tcp/connector/tcp/codec/MessageBuf.java: -------------------------------------------------------------------------------- 1 | package com.ibyte.iot.tcp.connector.tcp.codec;// Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: MessageBuf.proto 3 | 4 | public final class MessageBuf { 5 | private MessageBuf() {} 6 | public static void registerAllExtensions( 7 | com.google.protobuf.ExtensionRegistry registry) { 8 | } 9 | public interface JMTransferOrBuilder extends 10 | // @@protoc_insertion_point(interface_extends:JMTransfer) 11 | com.google.protobuf.MessageOrBuilder { 12 | 13 | /** 14 | * required string version = 1; 15 | */ 16 | boolean hasVersion(); 17 | /** 18 | * required string version = 1; 19 | */ 20 | String getVersion(); 21 | /** 22 | * required string version = 1; 23 | */ 24 | com.google.protobuf.ByteString 25 | getVersionBytes(); 26 | 27 | /** 28 | * required string deviceId = 2; 29 | */ 30 | boolean hasDeviceId(); 31 | /** 32 | * required string deviceId = 2; 33 | */ 34 | String getDeviceId(); 35 | /** 36 | * required string deviceId = 2; 37 | */ 38 | com.google.protobuf.ByteString 39 | getDeviceIdBytes(); 40 | 41 | /** 42 | * required uint32 cmd = 3; 43 | */ 44 | boolean hasCmd(); 45 | /** 46 | * required uint32 cmd = 3; 47 | */ 48 | int getCmd(); 49 | 50 | /** 51 | * required uint64 seq = 4; 52 | */ 53 | boolean hasSeq(); 54 | /** 55 | * required uint64 seq = 4; 56 | */ 57 | long getSeq(); 58 | 59 | /** 60 | * required uint32 format = 5; 61 | */ 62 | boolean hasFormat(); 63 | /** 64 | * required uint32 format = 5; 65 | */ 66 | int getFormat(); 67 | 68 | /** 69 | * required uint32 flag = 6; 70 | */ 71 | boolean hasFlag(); 72 | /** 73 | * required uint32 flag = 6; 74 | */ 75 | int getFlag(); 76 | 77 | /** 78 | * required string platform = 7; 79 | */ 80 | boolean hasPlatform(); 81 | /** 82 | * required string platform = 7; 83 | */ 84 | String getPlatform(); 85 | /** 86 | * required string platform = 7; 87 | */ 88 | com.google.protobuf.ByteString 89 | getPlatformBytes(); 90 | 91 | /** 92 | * required string platformVersion = 8; 93 | */ 94 | boolean hasPlatformVersion(); 95 | /** 96 | * required string platformVersion = 8; 97 | */ 98 | String getPlatformVersion(); 99 | /** 100 | * required string platformVersion = 8; 101 | */ 102 | com.google.protobuf.ByteString 103 | getPlatformVersionBytes(); 104 | 105 | /** 106 | * required string token = 9; 107 | */ 108 | boolean hasToken(); 109 | /** 110 | * required string token = 9; 111 | */ 112 | String getToken(); 113 | /** 114 | * required string token = 9; 115 | */ 116 | com.google.protobuf.ByteString 117 | getTokenBytes(); 118 | 119 | /** 120 | * required string appKey = 10; 121 | */ 122 | boolean hasAppKey(); 123 | /** 124 | * required string appKey = 10; 125 | */ 126 | String getAppKey(); 127 | /** 128 | * required string appKey = 10; 129 | */ 130 | com.google.protobuf.ByteString 131 | getAppKeyBytes(); 132 | 133 | /** 134 | * required string timeStamp = 11; 135 | */ 136 | boolean hasTimeStamp(); 137 | /** 138 | * required string timeStamp = 11; 139 | */ 140 | String getTimeStamp(); 141 | /** 142 | * required string timeStamp = 11; 143 | */ 144 | com.google.protobuf.ByteString 145 | getTimeStampBytes(); 146 | 147 | /** 148 | * required string sign = 12; 149 | */ 150 | boolean hasSign(); 151 | /** 152 | * required string sign = 12; 153 | */ 154 | String getSign(); 155 | /** 156 | * required string sign = 12; 157 | */ 158 | com.google.protobuf.ByteString 159 | getSignBytes(); 160 | 161 | /** 162 | * optional bytes body = 20; 163 | */ 164 | boolean hasBody(); 165 | /** 166 | * optional bytes body = 20; 167 | */ 168 | com.google.protobuf.ByteString getBody(); 169 | } 170 | /** 171 | * Protobuf type {@code JMTransfer} 172 | */ 173 | public static final class JMTransfer extends 174 | com.google.protobuf.GeneratedMessage implements 175 | // @@protoc_insertion_point(message_implements:JMTransfer) 176 | JMTransferOrBuilder { 177 | // Use JMTransfer.newBuilder() to construct. 178 | private JMTransfer(com.google.protobuf.GeneratedMessage.Builder builder) { 179 | super(builder); 180 | this.unknownFields = builder.getUnknownFields(); 181 | } 182 | private JMTransfer(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } 183 | 184 | private static final JMTransfer defaultInstance; 185 | public static JMTransfer getDefaultInstance() { 186 | return defaultInstance; 187 | } 188 | 189 | public JMTransfer getDefaultInstanceForType() { 190 | return defaultInstance; 191 | } 192 | 193 | private final com.google.protobuf.UnknownFieldSet unknownFields; 194 | @Override 195 | public final com.google.protobuf.UnknownFieldSet 196 | getUnknownFields() { 197 | return this.unknownFields; 198 | } 199 | private JMTransfer( 200 | com.google.protobuf.CodedInputStream input, 201 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 202 | throws com.google.protobuf.InvalidProtocolBufferException { 203 | initFields(); 204 | int mutable_bitField0_ = 0; 205 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 206 | com.google.protobuf.UnknownFieldSet.newBuilder(); 207 | try { 208 | boolean done = false; 209 | while (!done) { 210 | int tag = input.readTag(); 211 | switch (tag) { 212 | case 0: 213 | done = true; 214 | break; 215 | default: { 216 | if (!parseUnknownField(input, unknownFields, 217 | extensionRegistry, tag)) { 218 | done = true; 219 | } 220 | break; 221 | } 222 | case 10: { 223 | com.google.protobuf.ByteString bs = input.readBytes(); 224 | bitField0_ |= 0x00000001; 225 | version_ = bs; 226 | break; 227 | } 228 | case 18: { 229 | com.google.protobuf.ByteString bs = input.readBytes(); 230 | bitField0_ |= 0x00000002; 231 | deviceId_ = bs; 232 | break; 233 | } 234 | case 24: { 235 | bitField0_ |= 0x00000004; 236 | cmd_ = input.readUInt32(); 237 | break; 238 | } 239 | case 32: { 240 | bitField0_ |= 0x00000008; 241 | seq_ = input.readUInt64(); 242 | break; 243 | } 244 | case 40: { 245 | bitField0_ |= 0x00000010; 246 | format_ = input.readUInt32(); 247 | break; 248 | } 249 | case 48: { 250 | bitField0_ |= 0x00000020; 251 | flag_ = input.readUInt32(); 252 | break; 253 | } 254 | case 58: { 255 | com.google.protobuf.ByteString bs = input.readBytes(); 256 | bitField0_ |= 0x00000040; 257 | platform_ = bs; 258 | break; 259 | } 260 | case 66: { 261 | com.google.protobuf.ByteString bs = input.readBytes(); 262 | bitField0_ |= 0x00000080; 263 | platformVersion_ = bs; 264 | break; 265 | } 266 | case 74: { 267 | com.google.protobuf.ByteString bs = input.readBytes(); 268 | bitField0_ |= 0x00000100; 269 | token_ = bs; 270 | break; 271 | } 272 | case 82: { 273 | com.google.protobuf.ByteString bs = input.readBytes(); 274 | bitField0_ |= 0x00000200; 275 | appKey_ = bs; 276 | break; 277 | } 278 | case 90: { 279 | com.google.protobuf.ByteString bs = input.readBytes(); 280 | bitField0_ |= 0x00000400; 281 | timeStamp_ = bs; 282 | break; 283 | } 284 | case 98: { 285 | com.google.protobuf.ByteString bs = input.readBytes(); 286 | bitField0_ |= 0x00000800; 287 | sign_ = bs; 288 | break; 289 | } 290 | case 162: { 291 | bitField0_ |= 0x00001000; 292 | body_ = input.readBytes(); 293 | break; 294 | } 295 | } 296 | } 297 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 298 | throw e.setUnfinishedMessage(this); 299 | } catch (java.io.IOException e) { 300 | throw new com.google.protobuf.InvalidProtocolBufferException( 301 | e.getMessage()).setUnfinishedMessage(this); 302 | } finally { 303 | this.unknownFields = unknownFields.build(); 304 | makeExtensionsImmutable(); 305 | } 306 | } 307 | public static final com.google.protobuf.Descriptors.Descriptor 308 | getDescriptor() { 309 | return MessageBuf.internal_static_JMTransfer_descriptor; 310 | } 311 | 312 | protected FieldAccessorTable 313 | internalGetFieldAccessorTable() { 314 | return MessageBuf.internal_static_JMTransfer_fieldAccessorTable 315 | .ensureFieldAccessorsInitialized( 316 | JMTransfer.class, Builder.class); 317 | } 318 | 319 | public static com.google.protobuf.Parser PARSER = 320 | new com.google.protobuf.AbstractParser() { 321 | public JMTransfer parsePartialFrom( 322 | com.google.protobuf.CodedInputStream input, 323 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 324 | throws com.google.protobuf.InvalidProtocolBufferException { 325 | return new JMTransfer(input, extensionRegistry); 326 | } 327 | }; 328 | 329 | @Override 330 | public com.google.protobuf.Parser getParserForType() { 331 | return PARSER; 332 | } 333 | 334 | private int bitField0_; 335 | public static final int VERSION_FIELD_NUMBER = 1; 336 | private Object version_; 337 | /** 338 | * required string version = 1; 339 | */ 340 | public boolean hasVersion() { 341 | return ((bitField0_ & 0x00000001) == 0x00000001); 342 | } 343 | /** 344 | * required string version = 1; 345 | */ 346 | public String getVersion() { 347 | Object ref = version_; 348 | if (ref instanceof String) { 349 | return (String) ref; 350 | } else { 351 | com.google.protobuf.ByteString bs = 352 | (com.google.protobuf.ByteString) ref; 353 | String s = bs.toStringUtf8(); 354 | if (bs.isValidUtf8()) { 355 | version_ = s; 356 | } 357 | return s; 358 | } 359 | } 360 | /** 361 | * required string version = 1; 362 | */ 363 | public com.google.protobuf.ByteString 364 | getVersionBytes() { 365 | Object ref = version_; 366 | if (ref instanceof String) { 367 | com.google.protobuf.ByteString b = 368 | com.google.protobuf.ByteString.copyFromUtf8( 369 | (String) ref); 370 | version_ = b; 371 | return b; 372 | } else { 373 | return (com.google.protobuf.ByteString) ref; 374 | } 375 | } 376 | 377 | public static final int DEVICEID_FIELD_NUMBER = 2; 378 | private Object deviceId_; 379 | /** 380 | * required string deviceId = 2; 381 | */ 382 | public boolean hasDeviceId() { 383 | return ((bitField0_ & 0x00000002) == 0x00000002); 384 | } 385 | /** 386 | * required string deviceId = 2; 387 | */ 388 | public String getDeviceId() { 389 | Object ref = deviceId_; 390 | if (ref instanceof String) { 391 | return (String) ref; 392 | } else { 393 | com.google.protobuf.ByteString bs = 394 | (com.google.protobuf.ByteString) ref; 395 | String s = bs.toStringUtf8(); 396 | if (bs.isValidUtf8()) { 397 | deviceId_ = s; 398 | } 399 | return s; 400 | } 401 | } 402 | /** 403 | * required string deviceId = 2; 404 | */ 405 | public com.google.protobuf.ByteString 406 | getDeviceIdBytes() { 407 | Object ref = deviceId_; 408 | if (ref instanceof String) { 409 | com.google.protobuf.ByteString b = 410 | com.google.protobuf.ByteString.copyFromUtf8( 411 | (String) ref); 412 | deviceId_ = b; 413 | return b; 414 | } else { 415 | return (com.google.protobuf.ByteString) ref; 416 | } 417 | } 418 | 419 | public static final int CMD_FIELD_NUMBER = 3; 420 | private int cmd_; 421 | /** 422 | * required uint32 cmd = 3; 423 | */ 424 | public boolean hasCmd() { 425 | return ((bitField0_ & 0x00000004) == 0x00000004); 426 | } 427 | /** 428 | * required uint32 cmd = 3; 429 | */ 430 | public int getCmd() { 431 | return cmd_; 432 | } 433 | 434 | public static final int SEQ_FIELD_NUMBER = 4; 435 | private long seq_; 436 | /** 437 | * required uint64 seq = 4; 438 | */ 439 | public boolean hasSeq() { 440 | return ((bitField0_ & 0x00000008) == 0x00000008); 441 | } 442 | /** 443 | * required uint64 seq = 4; 444 | */ 445 | public long getSeq() { 446 | return seq_; 447 | } 448 | 449 | public static final int FORMAT_FIELD_NUMBER = 5; 450 | private int format_; 451 | /** 452 | * required uint32 format = 5; 453 | */ 454 | public boolean hasFormat() { 455 | return ((bitField0_ & 0x00000010) == 0x00000010); 456 | } 457 | /** 458 | * required uint32 format = 5; 459 | */ 460 | public int getFormat() { 461 | return format_; 462 | } 463 | 464 | public static final int FLAG_FIELD_NUMBER = 6; 465 | private int flag_; 466 | /** 467 | * required uint32 flag = 6; 468 | */ 469 | public boolean hasFlag() { 470 | return ((bitField0_ & 0x00000020) == 0x00000020); 471 | } 472 | /** 473 | * required uint32 flag = 6; 474 | */ 475 | public int getFlag() { 476 | return flag_; 477 | } 478 | 479 | public static final int PLATFORM_FIELD_NUMBER = 7; 480 | private Object platform_; 481 | /** 482 | * required string platform = 7; 483 | */ 484 | public boolean hasPlatform() { 485 | return ((bitField0_ & 0x00000040) == 0x00000040); 486 | } 487 | /** 488 | * required string platform = 7; 489 | */ 490 | public String getPlatform() { 491 | Object ref = platform_; 492 | if (ref instanceof String) { 493 | return (String) ref; 494 | } else { 495 | com.google.protobuf.ByteString bs = 496 | (com.google.protobuf.ByteString) ref; 497 | String s = bs.toStringUtf8(); 498 | if (bs.isValidUtf8()) { 499 | platform_ = s; 500 | } 501 | return s; 502 | } 503 | } 504 | /** 505 | * required string platform = 7; 506 | */ 507 | public com.google.protobuf.ByteString 508 | getPlatformBytes() { 509 | Object ref = platform_; 510 | if (ref instanceof String) { 511 | com.google.protobuf.ByteString b = 512 | com.google.protobuf.ByteString.copyFromUtf8( 513 | (String) ref); 514 | platform_ = b; 515 | return b; 516 | } else { 517 | return (com.google.protobuf.ByteString) ref; 518 | } 519 | } 520 | 521 | public static final int PLATFORMVERSION_FIELD_NUMBER = 8; 522 | private Object platformVersion_; 523 | /** 524 | * required string platformVersion = 8; 525 | */ 526 | public boolean hasPlatformVersion() { 527 | return ((bitField0_ & 0x00000080) == 0x00000080); 528 | } 529 | /** 530 | * required string platformVersion = 8; 531 | */ 532 | public String getPlatformVersion() { 533 | Object ref = platformVersion_; 534 | if (ref instanceof String) { 535 | return (String) ref; 536 | } else { 537 | com.google.protobuf.ByteString bs = 538 | (com.google.protobuf.ByteString) ref; 539 | String s = bs.toStringUtf8(); 540 | if (bs.isValidUtf8()) { 541 | platformVersion_ = s; 542 | } 543 | return s; 544 | } 545 | } 546 | /** 547 | * required string platformVersion = 8; 548 | */ 549 | public com.google.protobuf.ByteString 550 | getPlatformVersionBytes() { 551 | Object ref = platformVersion_; 552 | if (ref instanceof String) { 553 | com.google.protobuf.ByteString b = 554 | com.google.protobuf.ByteString.copyFromUtf8( 555 | (String) ref); 556 | platformVersion_ = b; 557 | return b; 558 | } else { 559 | return (com.google.protobuf.ByteString) ref; 560 | } 561 | } 562 | 563 | public static final int TOKEN_FIELD_NUMBER = 9; 564 | private Object token_; 565 | /** 566 | * required string token = 9; 567 | */ 568 | public boolean hasToken() { 569 | return ((bitField0_ & 0x00000100) == 0x00000100); 570 | } 571 | /** 572 | * required string token = 9; 573 | */ 574 | public String getToken() { 575 | Object ref = token_; 576 | if (ref instanceof String) { 577 | return (String) ref; 578 | } else { 579 | com.google.protobuf.ByteString bs = 580 | (com.google.protobuf.ByteString) ref; 581 | String s = bs.toStringUtf8(); 582 | if (bs.isValidUtf8()) { 583 | token_ = s; 584 | } 585 | return s; 586 | } 587 | } 588 | /** 589 | * required string token = 9; 590 | */ 591 | public com.google.protobuf.ByteString 592 | getTokenBytes() { 593 | Object ref = token_; 594 | if (ref instanceof String) { 595 | com.google.protobuf.ByteString b = 596 | com.google.protobuf.ByteString.copyFromUtf8( 597 | (String) ref); 598 | token_ = b; 599 | return b; 600 | } else { 601 | return (com.google.protobuf.ByteString) ref; 602 | } 603 | } 604 | 605 | public static final int APPKEY_FIELD_NUMBER = 10; 606 | private Object appKey_; 607 | /** 608 | * required string appKey = 10; 609 | */ 610 | public boolean hasAppKey() { 611 | return ((bitField0_ & 0x00000200) == 0x00000200); 612 | } 613 | /** 614 | * required string appKey = 10; 615 | */ 616 | public String getAppKey() { 617 | Object ref = appKey_; 618 | if (ref instanceof String) { 619 | return (String) ref; 620 | } else { 621 | com.google.protobuf.ByteString bs = 622 | (com.google.protobuf.ByteString) ref; 623 | String s = bs.toStringUtf8(); 624 | if (bs.isValidUtf8()) { 625 | appKey_ = s; 626 | } 627 | return s; 628 | } 629 | } 630 | /** 631 | * required string appKey = 10; 632 | */ 633 | public com.google.protobuf.ByteString 634 | getAppKeyBytes() { 635 | Object ref = appKey_; 636 | if (ref instanceof String) { 637 | com.google.protobuf.ByteString b = 638 | com.google.protobuf.ByteString.copyFromUtf8( 639 | (String) ref); 640 | appKey_ = b; 641 | return b; 642 | } else { 643 | return (com.google.protobuf.ByteString) ref; 644 | } 645 | } 646 | 647 | public static final int TIMESTAMP_FIELD_NUMBER = 11; 648 | private Object timeStamp_; 649 | /** 650 | * required string timeStamp = 11; 651 | */ 652 | public boolean hasTimeStamp() { 653 | return ((bitField0_ & 0x00000400) == 0x00000400); 654 | } 655 | /** 656 | * required string timeStamp = 11; 657 | */ 658 | public String getTimeStamp() { 659 | Object ref = timeStamp_; 660 | if (ref instanceof String) { 661 | return (String) ref; 662 | } else { 663 | com.google.protobuf.ByteString bs = 664 | (com.google.protobuf.ByteString) ref; 665 | String s = bs.toStringUtf8(); 666 | if (bs.isValidUtf8()) { 667 | timeStamp_ = s; 668 | } 669 | return s; 670 | } 671 | } 672 | /** 673 | * required string timeStamp = 11; 674 | */ 675 | public com.google.protobuf.ByteString 676 | getTimeStampBytes() { 677 | Object ref = timeStamp_; 678 | if (ref instanceof String) { 679 | com.google.protobuf.ByteString b = 680 | com.google.protobuf.ByteString.copyFromUtf8( 681 | (String) ref); 682 | timeStamp_ = b; 683 | return b; 684 | } else { 685 | return (com.google.protobuf.ByteString) ref; 686 | } 687 | } 688 | 689 | public static final int SIGN_FIELD_NUMBER = 12; 690 | private Object sign_; 691 | /** 692 | * required string sign = 12; 693 | */ 694 | public boolean hasSign() { 695 | return ((bitField0_ & 0x00000800) == 0x00000800); 696 | } 697 | /** 698 | * required string sign = 12; 699 | */ 700 | public String getSign() { 701 | Object ref = sign_; 702 | if (ref instanceof String) { 703 | return (String) ref; 704 | } else { 705 | com.google.protobuf.ByteString bs = 706 | (com.google.protobuf.ByteString) ref; 707 | String s = bs.toStringUtf8(); 708 | if (bs.isValidUtf8()) { 709 | sign_ = s; 710 | } 711 | return s; 712 | } 713 | } 714 | /** 715 | * required string sign = 12; 716 | */ 717 | public com.google.protobuf.ByteString 718 | getSignBytes() { 719 | Object ref = sign_; 720 | if (ref instanceof String) { 721 | com.google.protobuf.ByteString b = 722 | com.google.protobuf.ByteString.copyFromUtf8( 723 | (String) ref); 724 | sign_ = b; 725 | return b; 726 | } else { 727 | return (com.google.protobuf.ByteString) ref; 728 | } 729 | } 730 | 731 | public static final int BODY_FIELD_NUMBER = 20; 732 | private com.google.protobuf.ByteString body_; 733 | /** 734 | * optional bytes body = 20; 735 | */ 736 | public boolean hasBody() { 737 | return ((bitField0_ & 0x00001000) == 0x00001000); 738 | } 739 | /** 740 | * optional bytes body = 20; 741 | */ 742 | public com.google.protobuf.ByteString getBody() { 743 | return body_; 744 | } 745 | 746 | private void initFields() { 747 | version_ = ""; 748 | deviceId_ = ""; 749 | cmd_ = 0; 750 | seq_ = 0L; 751 | format_ = 0; 752 | flag_ = 0; 753 | platform_ = ""; 754 | platformVersion_ = ""; 755 | token_ = ""; 756 | appKey_ = ""; 757 | timeStamp_ = ""; 758 | sign_ = ""; 759 | body_ = com.google.protobuf.ByteString.EMPTY; 760 | } 761 | private byte memoizedIsInitialized = -1; 762 | public final boolean isInitialized() { 763 | byte isInitialized = memoizedIsInitialized; 764 | if (isInitialized == 1) return true; 765 | if (isInitialized == 0) return false; 766 | 767 | if (!hasVersion()) { 768 | memoizedIsInitialized = 0; 769 | return false; 770 | } 771 | if (!hasDeviceId()) { 772 | memoizedIsInitialized = 0; 773 | return false; 774 | } 775 | if (!hasCmd()) { 776 | memoizedIsInitialized = 0; 777 | return false; 778 | } 779 | if (!hasSeq()) { 780 | memoizedIsInitialized = 0; 781 | return false; 782 | } 783 | if (!hasFormat()) { 784 | memoizedIsInitialized = 0; 785 | return false; 786 | } 787 | if (!hasFlag()) { 788 | memoizedIsInitialized = 0; 789 | return false; 790 | } 791 | if (!hasPlatform()) { 792 | memoizedIsInitialized = 0; 793 | return false; 794 | } 795 | if (!hasPlatformVersion()) { 796 | memoizedIsInitialized = 0; 797 | return false; 798 | } 799 | if (!hasToken()) { 800 | memoizedIsInitialized = 0; 801 | return false; 802 | } 803 | if (!hasAppKey()) { 804 | memoizedIsInitialized = 0; 805 | return false; 806 | } 807 | if (!hasTimeStamp()) { 808 | memoizedIsInitialized = 0; 809 | return false; 810 | } 811 | if (!hasSign()) { 812 | memoizedIsInitialized = 0; 813 | return false; 814 | } 815 | memoizedIsInitialized = 1; 816 | return true; 817 | } 818 | 819 | public void writeTo(com.google.protobuf.CodedOutputStream output) 820 | throws java.io.IOException { 821 | getSerializedSize(); 822 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 823 | output.writeBytes(1, getVersionBytes()); 824 | } 825 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 826 | output.writeBytes(2, getDeviceIdBytes()); 827 | } 828 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 829 | output.writeUInt32(3, cmd_); 830 | } 831 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 832 | output.writeUInt64(4, seq_); 833 | } 834 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 835 | output.writeUInt32(5, format_); 836 | } 837 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 838 | output.writeUInt32(6, flag_); 839 | } 840 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 841 | output.writeBytes(7, getPlatformBytes()); 842 | } 843 | if (((bitField0_ & 0x00000080) == 0x00000080)) { 844 | output.writeBytes(8, getPlatformVersionBytes()); 845 | } 846 | if (((bitField0_ & 0x00000100) == 0x00000100)) { 847 | output.writeBytes(9, getTokenBytes()); 848 | } 849 | if (((bitField0_ & 0x00000200) == 0x00000200)) { 850 | output.writeBytes(10, getAppKeyBytes()); 851 | } 852 | if (((bitField0_ & 0x00000400) == 0x00000400)) { 853 | output.writeBytes(11, getTimeStampBytes()); 854 | } 855 | if (((bitField0_ & 0x00000800) == 0x00000800)) { 856 | output.writeBytes(12, getSignBytes()); 857 | } 858 | if (((bitField0_ & 0x00001000) == 0x00001000)) { 859 | output.writeBytes(20, body_); 860 | } 861 | getUnknownFields().writeTo(output); 862 | } 863 | 864 | private int memoizedSerializedSize = -1; 865 | public int getSerializedSize() { 866 | int size = memoizedSerializedSize; 867 | if (size != -1) return size; 868 | 869 | size = 0; 870 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 871 | size += com.google.protobuf.CodedOutputStream 872 | .computeBytesSize(1, getVersionBytes()); 873 | } 874 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 875 | size += com.google.protobuf.CodedOutputStream 876 | .computeBytesSize(2, getDeviceIdBytes()); 877 | } 878 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 879 | size += com.google.protobuf.CodedOutputStream 880 | .computeUInt32Size(3, cmd_); 881 | } 882 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 883 | size += com.google.protobuf.CodedOutputStream 884 | .computeUInt64Size(4, seq_); 885 | } 886 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 887 | size += com.google.protobuf.CodedOutputStream 888 | .computeUInt32Size(5, format_); 889 | } 890 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 891 | size += com.google.protobuf.CodedOutputStream 892 | .computeUInt32Size(6, flag_); 893 | } 894 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 895 | size += com.google.protobuf.CodedOutputStream 896 | .computeBytesSize(7, getPlatformBytes()); 897 | } 898 | if (((bitField0_ & 0x00000080) == 0x00000080)) { 899 | size += com.google.protobuf.CodedOutputStream 900 | .computeBytesSize(8, getPlatformVersionBytes()); 901 | } 902 | if (((bitField0_ & 0x00000100) == 0x00000100)) { 903 | size += com.google.protobuf.CodedOutputStream 904 | .computeBytesSize(9, getTokenBytes()); 905 | } 906 | if (((bitField0_ & 0x00000200) == 0x00000200)) { 907 | size += com.google.protobuf.CodedOutputStream 908 | .computeBytesSize(10, getAppKeyBytes()); 909 | } 910 | if (((bitField0_ & 0x00000400) == 0x00000400)) { 911 | size += com.google.protobuf.CodedOutputStream 912 | .computeBytesSize(11, getTimeStampBytes()); 913 | } 914 | if (((bitField0_ & 0x00000800) == 0x00000800)) { 915 | size += com.google.protobuf.CodedOutputStream 916 | .computeBytesSize(12, getSignBytes()); 917 | } 918 | if (((bitField0_ & 0x00001000) == 0x00001000)) { 919 | size += com.google.protobuf.CodedOutputStream 920 | .computeBytesSize(20, body_); 921 | } 922 | size += getUnknownFields().getSerializedSize(); 923 | memoizedSerializedSize = size; 924 | return size; 925 | } 926 | 927 | private static final long serialVersionUID = 0L; 928 | @Override 929 | protected Object writeReplace() 930 | throws java.io.ObjectStreamException { 931 | return super.writeReplace(); 932 | } 933 | 934 | public static JMTransfer parseFrom( 935 | com.google.protobuf.ByteString data) 936 | throws com.google.protobuf.InvalidProtocolBufferException { 937 | return PARSER.parseFrom(data); 938 | } 939 | public static JMTransfer parseFrom( 940 | com.google.protobuf.ByteString data, 941 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 942 | throws com.google.protobuf.InvalidProtocolBufferException { 943 | return PARSER.parseFrom(data, extensionRegistry); 944 | } 945 | public static JMTransfer parseFrom(byte[] data) 946 | throws com.google.protobuf.InvalidProtocolBufferException { 947 | return PARSER.parseFrom(data); 948 | } 949 | public static JMTransfer parseFrom( 950 | byte[] data, 951 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 952 | throws com.google.protobuf.InvalidProtocolBufferException { 953 | return PARSER.parseFrom(data, extensionRegistry); 954 | } 955 | public static JMTransfer parseFrom(java.io.InputStream input) 956 | throws java.io.IOException { 957 | return PARSER.parseFrom(input); 958 | } 959 | public static JMTransfer parseFrom( 960 | java.io.InputStream input, 961 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 962 | throws java.io.IOException { 963 | return PARSER.parseFrom(input, extensionRegistry); 964 | } 965 | public static JMTransfer parseDelimitedFrom(java.io.InputStream input) 966 | throws java.io.IOException { 967 | return PARSER.parseDelimitedFrom(input); 968 | } 969 | public static JMTransfer parseDelimitedFrom( 970 | java.io.InputStream input, 971 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 972 | throws java.io.IOException { 973 | return PARSER.parseDelimitedFrom(input, extensionRegistry); 974 | } 975 | public static JMTransfer parseFrom( 976 | com.google.protobuf.CodedInputStream input) 977 | throws java.io.IOException { 978 | return PARSER.parseFrom(input); 979 | } 980 | public static JMTransfer parseFrom( 981 | com.google.protobuf.CodedInputStream input, 982 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 983 | throws java.io.IOException { 984 | return PARSER.parseFrom(input, extensionRegistry); 985 | } 986 | 987 | public static Builder newBuilder() { return Builder.create(); } 988 | public Builder newBuilderForType() { return newBuilder(); } 989 | public static Builder newBuilder(JMTransfer prototype) { 990 | return newBuilder().mergeFrom(prototype); 991 | } 992 | public Builder toBuilder() { return newBuilder(this); } 993 | 994 | @Override 995 | protected Builder newBuilderForType( 996 | BuilderParent parent) { 997 | Builder builder = new Builder(parent); 998 | return builder; 999 | } 1000 | /** 1001 | * Protobuf type {@code JMTransfer} 1002 | */ 1003 | public static final class Builder extends 1004 | com.google.protobuf.GeneratedMessage.Builder implements 1005 | // @@protoc_insertion_point(builder_implements:JMTransfer) 1006 | JMTransferOrBuilder { 1007 | public static final com.google.protobuf.Descriptors.Descriptor 1008 | getDescriptor() { 1009 | return MessageBuf.internal_static_JMTransfer_descriptor; 1010 | } 1011 | 1012 | protected FieldAccessorTable 1013 | internalGetFieldAccessorTable() { 1014 | return MessageBuf.internal_static_JMTransfer_fieldAccessorTable 1015 | .ensureFieldAccessorsInitialized( 1016 | JMTransfer.class, Builder.class); 1017 | } 1018 | 1019 | // Construct using MessageBuf.JMTransfer.newBuilder() 1020 | private Builder() { 1021 | maybeForceBuilderInitialization(); 1022 | } 1023 | 1024 | private Builder( 1025 | BuilderParent parent) { 1026 | super(parent); 1027 | maybeForceBuilderInitialization(); 1028 | } 1029 | private void maybeForceBuilderInitialization() { 1030 | if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { 1031 | } 1032 | } 1033 | private static Builder create() { 1034 | return new Builder(); 1035 | } 1036 | 1037 | public Builder clear() { 1038 | super.clear(); 1039 | version_ = ""; 1040 | bitField0_ = (bitField0_ & ~0x00000001); 1041 | deviceId_ = ""; 1042 | bitField0_ = (bitField0_ & ~0x00000002); 1043 | cmd_ = 0; 1044 | bitField0_ = (bitField0_ & ~0x00000004); 1045 | seq_ = 0L; 1046 | bitField0_ = (bitField0_ & ~0x00000008); 1047 | format_ = 0; 1048 | bitField0_ = (bitField0_ & ~0x00000010); 1049 | flag_ = 0; 1050 | bitField0_ = (bitField0_ & ~0x00000020); 1051 | platform_ = ""; 1052 | bitField0_ = (bitField0_ & ~0x00000040); 1053 | platformVersion_ = ""; 1054 | bitField0_ = (bitField0_ & ~0x00000080); 1055 | token_ = ""; 1056 | bitField0_ = (bitField0_ & ~0x00000100); 1057 | appKey_ = ""; 1058 | bitField0_ = (bitField0_ & ~0x00000200); 1059 | timeStamp_ = ""; 1060 | bitField0_ = (bitField0_ & ~0x00000400); 1061 | sign_ = ""; 1062 | bitField0_ = (bitField0_ & ~0x00000800); 1063 | body_ = com.google.protobuf.ByteString.EMPTY; 1064 | bitField0_ = (bitField0_ & ~0x00001000); 1065 | return this; 1066 | } 1067 | 1068 | public Builder clone() { 1069 | return create().mergeFrom(buildPartial()); 1070 | } 1071 | 1072 | public com.google.protobuf.Descriptors.Descriptor 1073 | getDescriptorForType() { 1074 | return MessageBuf.internal_static_JMTransfer_descriptor; 1075 | } 1076 | 1077 | public JMTransfer getDefaultInstanceForType() { 1078 | return JMTransfer.getDefaultInstance(); 1079 | } 1080 | 1081 | public JMTransfer build() { 1082 | JMTransfer result = buildPartial(); 1083 | if (!result.isInitialized()) { 1084 | throw newUninitializedMessageException(result); 1085 | } 1086 | return result; 1087 | } 1088 | 1089 | public JMTransfer buildPartial() { 1090 | JMTransfer result = new JMTransfer(this); 1091 | int from_bitField0_ = bitField0_; 1092 | int to_bitField0_ = 0; 1093 | if (((from_bitField0_ & 0x00000001) == 0x00000001)) { 1094 | to_bitField0_ |= 0x00000001; 1095 | } 1096 | result.version_ = version_; 1097 | if (((from_bitField0_ & 0x00000002) == 0x00000002)) { 1098 | to_bitField0_ |= 0x00000002; 1099 | } 1100 | result.deviceId_ = deviceId_; 1101 | if (((from_bitField0_ & 0x00000004) == 0x00000004)) { 1102 | to_bitField0_ |= 0x00000004; 1103 | } 1104 | result.cmd_ = cmd_; 1105 | if (((from_bitField0_ & 0x00000008) == 0x00000008)) { 1106 | to_bitField0_ |= 0x00000008; 1107 | } 1108 | result.seq_ = seq_; 1109 | if (((from_bitField0_ & 0x00000010) == 0x00000010)) { 1110 | to_bitField0_ |= 0x00000010; 1111 | } 1112 | result.format_ = format_; 1113 | if (((from_bitField0_ & 0x00000020) == 0x00000020)) { 1114 | to_bitField0_ |= 0x00000020; 1115 | } 1116 | result.flag_ = flag_; 1117 | if (((from_bitField0_ & 0x00000040) == 0x00000040)) { 1118 | to_bitField0_ |= 0x00000040; 1119 | } 1120 | result.platform_ = platform_; 1121 | if (((from_bitField0_ & 0x00000080) == 0x00000080)) { 1122 | to_bitField0_ |= 0x00000080; 1123 | } 1124 | result.platformVersion_ = platformVersion_; 1125 | if (((from_bitField0_ & 0x00000100) == 0x00000100)) { 1126 | to_bitField0_ |= 0x00000100; 1127 | } 1128 | result.token_ = token_; 1129 | if (((from_bitField0_ & 0x00000200) == 0x00000200)) { 1130 | to_bitField0_ |= 0x00000200; 1131 | } 1132 | result.appKey_ = appKey_; 1133 | if (((from_bitField0_ & 0x00000400) == 0x00000400)) { 1134 | to_bitField0_ |= 0x00000400; 1135 | } 1136 | result.timeStamp_ = timeStamp_; 1137 | if (((from_bitField0_ & 0x00000800) == 0x00000800)) { 1138 | to_bitField0_ |= 0x00000800; 1139 | } 1140 | result.sign_ = sign_; 1141 | if (((from_bitField0_ & 0x00001000) == 0x00001000)) { 1142 | to_bitField0_ |= 0x00001000; 1143 | } 1144 | result.body_ = body_; 1145 | result.bitField0_ = to_bitField0_; 1146 | onBuilt(); 1147 | return result; 1148 | } 1149 | 1150 | public Builder mergeFrom(com.google.protobuf.Message other) { 1151 | if (other instanceof JMTransfer) { 1152 | return mergeFrom((JMTransfer)other); 1153 | } else { 1154 | super.mergeFrom(other); 1155 | return this; 1156 | } 1157 | } 1158 | 1159 | public Builder mergeFrom(JMTransfer other) { 1160 | if (other == JMTransfer.getDefaultInstance()) return this; 1161 | if (other.hasVersion()) { 1162 | bitField0_ |= 0x00000001; 1163 | version_ = other.version_; 1164 | onChanged(); 1165 | } 1166 | if (other.hasDeviceId()) { 1167 | bitField0_ |= 0x00000002; 1168 | deviceId_ = other.deviceId_; 1169 | onChanged(); 1170 | } 1171 | if (other.hasCmd()) { 1172 | setCmd(other.getCmd()); 1173 | } 1174 | if (other.hasSeq()) { 1175 | setSeq(other.getSeq()); 1176 | } 1177 | if (other.hasFormat()) { 1178 | setFormat(other.getFormat()); 1179 | } 1180 | if (other.hasFlag()) { 1181 | setFlag(other.getFlag()); 1182 | } 1183 | if (other.hasPlatform()) { 1184 | bitField0_ |= 0x00000040; 1185 | platform_ = other.platform_; 1186 | onChanged(); 1187 | } 1188 | if (other.hasPlatformVersion()) { 1189 | bitField0_ |= 0x00000080; 1190 | platformVersion_ = other.platformVersion_; 1191 | onChanged(); 1192 | } 1193 | if (other.hasToken()) { 1194 | bitField0_ |= 0x00000100; 1195 | token_ = other.token_; 1196 | onChanged(); 1197 | } 1198 | if (other.hasAppKey()) { 1199 | bitField0_ |= 0x00000200; 1200 | appKey_ = other.appKey_; 1201 | onChanged(); 1202 | } 1203 | if (other.hasTimeStamp()) { 1204 | bitField0_ |= 0x00000400; 1205 | timeStamp_ = other.timeStamp_; 1206 | onChanged(); 1207 | } 1208 | if (other.hasSign()) { 1209 | bitField0_ |= 0x00000800; 1210 | sign_ = other.sign_; 1211 | onChanged(); 1212 | } 1213 | if (other.hasBody()) { 1214 | setBody(other.getBody()); 1215 | } 1216 | this.mergeUnknownFields(other.getUnknownFields()); 1217 | return this; 1218 | } 1219 | 1220 | public final boolean isInitialized() { 1221 | if (!hasVersion()) { 1222 | 1223 | return false; 1224 | } 1225 | if (!hasDeviceId()) { 1226 | 1227 | return false; 1228 | } 1229 | if (!hasCmd()) { 1230 | 1231 | return false; 1232 | } 1233 | if (!hasSeq()) { 1234 | 1235 | return false; 1236 | } 1237 | if (!hasFormat()) { 1238 | 1239 | return false; 1240 | } 1241 | if (!hasFlag()) { 1242 | 1243 | return false; 1244 | } 1245 | if (!hasPlatform()) { 1246 | 1247 | return false; 1248 | } 1249 | if (!hasPlatformVersion()) { 1250 | 1251 | return false; 1252 | } 1253 | if (!hasToken()) { 1254 | 1255 | return false; 1256 | } 1257 | if (!hasAppKey()) { 1258 | 1259 | return false; 1260 | } 1261 | if (!hasTimeStamp()) { 1262 | 1263 | return false; 1264 | } 1265 | if (!hasSign()) { 1266 | 1267 | return false; 1268 | } 1269 | return true; 1270 | } 1271 | 1272 | public Builder mergeFrom( 1273 | com.google.protobuf.CodedInputStream input, 1274 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1275 | throws java.io.IOException { 1276 | JMTransfer parsedMessage = null; 1277 | try { 1278 | parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); 1279 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 1280 | parsedMessage = (JMTransfer) e.getUnfinishedMessage(); 1281 | throw e; 1282 | } finally { 1283 | if (parsedMessage != null) { 1284 | mergeFrom(parsedMessage); 1285 | } 1286 | } 1287 | return this; 1288 | } 1289 | private int bitField0_; 1290 | 1291 | private Object version_ = ""; 1292 | /** 1293 | * required string version = 1; 1294 | */ 1295 | public boolean hasVersion() { 1296 | return ((bitField0_ & 0x00000001) == 0x00000001); 1297 | } 1298 | /** 1299 | * required string version = 1; 1300 | */ 1301 | public String getVersion() { 1302 | Object ref = version_; 1303 | if (!(ref instanceof String)) { 1304 | com.google.protobuf.ByteString bs = 1305 | (com.google.protobuf.ByteString) ref; 1306 | String s = bs.toStringUtf8(); 1307 | if (bs.isValidUtf8()) { 1308 | version_ = s; 1309 | } 1310 | return s; 1311 | } else { 1312 | return (String) ref; 1313 | } 1314 | } 1315 | /** 1316 | * required string version = 1; 1317 | */ 1318 | public com.google.protobuf.ByteString 1319 | getVersionBytes() { 1320 | Object ref = version_; 1321 | if (ref instanceof String) { 1322 | com.google.protobuf.ByteString b = 1323 | com.google.protobuf.ByteString.copyFromUtf8( 1324 | (String) ref); 1325 | version_ = b; 1326 | return b; 1327 | } else { 1328 | return (com.google.protobuf.ByteString) ref; 1329 | } 1330 | } 1331 | /** 1332 | * required string version = 1; 1333 | */ 1334 | public Builder setVersion( 1335 | String value) { 1336 | if (value == null) { 1337 | throw new NullPointerException(); 1338 | } 1339 | bitField0_ |= 0x00000001; 1340 | version_ = value; 1341 | onChanged(); 1342 | return this; 1343 | } 1344 | /** 1345 | * required string version = 1; 1346 | */ 1347 | public Builder clearVersion() { 1348 | bitField0_ = (bitField0_ & ~0x00000001); 1349 | version_ = getDefaultInstance().getVersion(); 1350 | onChanged(); 1351 | return this; 1352 | } 1353 | /** 1354 | * required string version = 1; 1355 | */ 1356 | public Builder setVersionBytes( 1357 | com.google.protobuf.ByteString value) { 1358 | if (value == null) { 1359 | throw new NullPointerException(); 1360 | } 1361 | bitField0_ |= 0x00000001; 1362 | version_ = value; 1363 | onChanged(); 1364 | return this; 1365 | } 1366 | 1367 | private Object deviceId_ = ""; 1368 | /** 1369 | * required string deviceId = 2; 1370 | */ 1371 | public boolean hasDeviceId() { 1372 | return ((bitField0_ & 0x00000002) == 0x00000002); 1373 | } 1374 | /** 1375 | * required string deviceId = 2; 1376 | */ 1377 | public String getDeviceId() { 1378 | Object ref = deviceId_; 1379 | if (!(ref instanceof String)) { 1380 | com.google.protobuf.ByteString bs = 1381 | (com.google.protobuf.ByteString) ref; 1382 | String s = bs.toStringUtf8(); 1383 | if (bs.isValidUtf8()) { 1384 | deviceId_ = s; 1385 | } 1386 | return s; 1387 | } else { 1388 | return (String) ref; 1389 | } 1390 | } 1391 | /** 1392 | * required string deviceId = 2; 1393 | */ 1394 | public com.google.protobuf.ByteString 1395 | getDeviceIdBytes() { 1396 | Object ref = deviceId_; 1397 | if (ref instanceof String) { 1398 | com.google.protobuf.ByteString b = 1399 | com.google.protobuf.ByteString.copyFromUtf8( 1400 | (String) ref); 1401 | deviceId_ = b; 1402 | return b; 1403 | } else { 1404 | return (com.google.protobuf.ByteString) ref; 1405 | } 1406 | } 1407 | /** 1408 | * required string deviceId = 2; 1409 | */ 1410 | public Builder setDeviceId( 1411 | String value) { 1412 | if (value == null) { 1413 | throw new NullPointerException(); 1414 | } 1415 | bitField0_ |= 0x00000002; 1416 | deviceId_ = value; 1417 | onChanged(); 1418 | return this; 1419 | } 1420 | /** 1421 | * required string deviceId = 2; 1422 | */ 1423 | public Builder clearDeviceId() { 1424 | bitField0_ = (bitField0_ & ~0x00000002); 1425 | deviceId_ = getDefaultInstance().getDeviceId(); 1426 | onChanged(); 1427 | return this; 1428 | } 1429 | /** 1430 | * required string deviceId = 2; 1431 | */ 1432 | public Builder setDeviceIdBytes( 1433 | com.google.protobuf.ByteString value) { 1434 | if (value == null) { 1435 | throw new NullPointerException(); 1436 | } 1437 | bitField0_ |= 0x00000002; 1438 | deviceId_ = value; 1439 | onChanged(); 1440 | return this; 1441 | } 1442 | 1443 | private int cmd_ ; 1444 | /** 1445 | * required uint32 cmd = 3; 1446 | */ 1447 | public boolean hasCmd() { 1448 | return ((bitField0_ & 0x00000004) == 0x00000004); 1449 | } 1450 | /** 1451 | * required uint32 cmd = 3; 1452 | */ 1453 | public int getCmd() { 1454 | return cmd_; 1455 | } 1456 | /** 1457 | * required uint32 cmd = 3; 1458 | */ 1459 | public Builder setCmd(int value) { 1460 | bitField0_ |= 0x00000004; 1461 | cmd_ = value; 1462 | onChanged(); 1463 | return this; 1464 | } 1465 | /** 1466 | * required uint32 cmd = 3; 1467 | */ 1468 | public Builder clearCmd() { 1469 | bitField0_ = (bitField0_ & ~0x00000004); 1470 | cmd_ = 0; 1471 | onChanged(); 1472 | return this; 1473 | } 1474 | 1475 | private long seq_ ; 1476 | /** 1477 | * required uint64 seq = 4; 1478 | */ 1479 | public boolean hasSeq() { 1480 | return ((bitField0_ & 0x00000008) == 0x00000008); 1481 | } 1482 | /** 1483 | * required uint64 seq = 4; 1484 | */ 1485 | public long getSeq() { 1486 | return seq_; 1487 | } 1488 | /** 1489 | * required uint64 seq = 4; 1490 | */ 1491 | public Builder setSeq(long value) { 1492 | bitField0_ |= 0x00000008; 1493 | seq_ = value; 1494 | onChanged(); 1495 | return this; 1496 | } 1497 | /** 1498 | * required uint64 seq = 4; 1499 | */ 1500 | public Builder clearSeq() { 1501 | bitField0_ = (bitField0_ & ~0x00000008); 1502 | seq_ = 0L; 1503 | onChanged(); 1504 | return this; 1505 | } 1506 | 1507 | private int format_ ; 1508 | /** 1509 | * required uint32 format = 5; 1510 | */ 1511 | public boolean hasFormat() { 1512 | return ((bitField0_ & 0x00000010) == 0x00000010); 1513 | } 1514 | /** 1515 | * required uint32 format = 5; 1516 | */ 1517 | public int getFormat() { 1518 | return format_; 1519 | } 1520 | /** 1521 | * required uint32 format = 5; 1522 | */ 1523 | public Builder setFormat(int value) { 1524 | bitField0_ |= 0x00000010; 1525 | format_ = value; 1526 | onChanged(); 1527 | return this; 1528 | } 1529 | /** 1530 | * required uint32 format = 5; 1531 | */ 1532 | public Builder clearFormat() { 1533 | bitField0_ = (bitField0_ & ~0x00000010); 1534 | format_ = 0; 1535 | onChanged(); 1536 | return this; 1537 | } 1538 | 1539 | private int flag_ ; 1540 | /** 1541 | * required uint32 flag = 6; 1542 | */ 1543 | public boolean hasFlag() { 1544 | return ((bitField0_ & 0x00000020) == 0x00000020); 1545 | } 1546 | /** 1547 | * required uint32 flag = 6; 1548 | */ 1549 | public int getFlag() { 1550 | return flag_; 1551 | } 1552 | /** 1553 | * required uint32 flag = 6; 1554 | */ 1555 | public Builder setFlag(int value) { 1556 | bitField0_ |= 0x00000020; 1557 | flag_ = value; 1558 | onChanged(); 1559 | return this; 1560 | } 1561 | /** 1562 | * required uint32 flag = 6; 1563 | */ 1564 | public Builder clearFlag() { 1565 | bitField0_ = (bitField0_ & ~0x00000020); 1566 | flag_ = 0; 1567 | onChanged(); 1568 | return this; 1569 | } 1570 | 1571 | private Object platform_ = ""; 1572 | /** 1573 | * required string platform = 7; 1574 | */ 1575 | public boolean hasPlatform() { 1576 | return ((bitField0_ & 0x00000040) == 0x00000040); 1577 | } 1578 | /** 1579 | * required string platform = 7; 1580 | */ 1581 | public String getPlatform() { 1582 | Object ref = platform_; 1583 | if (!(ref instanceof String)) { 1584 | com.google.protobuf.ByteString bs = 1585 | (com.google.protobuf.ByteString) ref; 1586 | String s = bs.toStringUtf8(); 1587 | if (bs.isValidUtf8()) { 1588 | platform_ = s; 1589 | } 1590 | return s; 1591 | } else { 1592 | return (String) ref; 1593 | } 1594 | } 1595 | /** 1596 | * required string platform = 7; 1597 | */ 1598 | public com.google.protobuf.ByteString 1599 | getPlatformBytes() { 1600 | Object ref = platform_; 1601 | if (ref instanceof String) { 1602 | com.google.protobuf.ByteString b = 1603 | com.google.protobuf.ByteString.copyFromUtf8( 1604 | (String) ref); 1605 | platform_ = b; 1606 | return b; 1607 | } else { 1608 | return (com.google.protobuf.ByteString) ref; 1609 | } 1610 | } 1611 | /** 1612 | * required string platform = 7; 1613 | */ 1614 | public Builder setPlatform( 1615 | String value) { 1616 | if (value == null) { 1617 | throw new NullPointerException(); 1618 | } 1619 | bitField0_ |= 0x00000040; 1620 | platform_ = value; 1621 | onChanged(); 1622 | return this; 1623 | } 1624 | /** 1625 | * required string platform = 7; 1626 | */ 1627 | public Builder clearPlatform() { 1628 | bitField0_ = (bitField0_ & ~0x00000040); 1629 | platform_ = getDefaultInstance().getPlatform(); 1630 | onChanged(); 1631 | return this; 1632 | } 1633 | /** 1634 | * required string platform = 7; 1635 | */ 1636 | public Builder setPlatformBytes( 1637 | com.google.protobuf.ByteString value) { 1638 | if (value == null) { 1639 | throw new NullPointerException(); 1640 | } 1641 | bitField0_ |= 0x00000040; 1642 | platform_ = value; 1643 | onChanged(); 1644 | return this; 1645 | } 1646 | 1647 | private Object platformVersion_ = ""; 1648 | /** 1649 | * required string platformVersion = 8; 1650 | */ 1651 | public boolean hasPlatformVersion() { 1652 | return ((bitField0_ & 0x00000080) == 0x00000080); 1653 | } 1654 | /** 1655 | * required string platformVersion = 8; 1656 | */ 1657 | public String getPlatformVersion() { 1658 | Object ref = platformVersion_; 1659 | if (!(ref instanceof String)) { 1660 | com.google.protobuf.ByteString bs = 1661 | (com.google.protobuf.ByteString) ref; 1662 | String s = bs.toStringUtf8(); 1663 | if (bs.isValidUtf8()) { 1664 | platformVersion_ = s; 1665 | } 1666 | return s; 1667 | } else { 1668 | return (String) ref; 1669 | } 1670 | } 1671 | /** 1672 | * required string platformVersion = 8; 1673 | */ 1674 | public com.google.protobuf.ByteString 1675 | getPlatformVersionBytes() { 1676 | Object ref = platformVersion_; 1677 | if (ref instanceof String) { 1678 | com.google.protobuf.ByteString b = 1679 | com.google.protobuf.ByteString.copyFromUtf8( 1680 | (String) ref); 1681 | platformVersion_ = b; 1682 | return b; 1683 | } else { 1684 | return (com.google.protobuf.ByteString) ref; 1685 | } 1686 | } 1687 | /** 1688 | * required string platformVersion = 8; 1689 | */ 1690 | public Builder setPlatformVersion( 1691 | String value) { 1692 | if (value == null) { 1693 | throw new NullPointerException(); 1694 | } 1695 | bitField0_ |= 0x00000080; 1696 | platformVersion_ = value; 1697 | onChanged(); 1698 | return this; 1699 | } 1700 | /** 1701 | * required string platformVersion = 8; 1702 | */ 1703 | public Builder clearPlatformVersion() { 1704 | bitField0_ = (bitField0_ & ~0x00000080); 1705 | platformVersion_ = getDefaultInstance().getPlatformVersion(); 1706 | onChanged(); 1707 | return this; 1708 | } 1709 | /** 1710 | * required string platformVersion = 8; 1711 | */ 1712 | public Builder setPlatformVersionBytes( 1713 | com.google.protobuf.ByteString value) { 1714 | if (value == null) { 1715 | throw new NullPointerException(); 1716 | } 1717 | bitField0_ |= 0x00000080; 1718 | platformVersion_ = value; 1719 | onChanged(); 1720 | return this; 1721 | } 1722 | 1723 | private Object token_ = ""; 1724 | /** 1725 | * required string token = 9; 1726 | */ 1727 | public boolean hasToken() { 1728 | return ((bitField0_ & 0x00000100) == 0x00000100); 1729 | } 1730 | /** 1731 | * required string token = 9; 1732 | */ 1733 | public String getToken() { 1734 | Object ref = token_; 1735 | if (!(ref instanceof String)) { 1736 | com.google.protobuf.ByteString bs = 1737 | (com.google.protobuf.ByteString) ref; 1738 | String s = bs.toStringUtf8(); 1739 | if (bs.isValidUtf8()) { 1740 | token_ = s; 1741 | } 1742 | return s; 1743 | } else { 1744 | return (String) ref; 1745 | } 1746 | } 1747 | /** 1748 | * required string token = 9; 1749 | */ 1750 | public com.google.protobuf.ByteString 1751 | getTokenBytes() { 1752 | Object ref = token_; 1753 | if (ref instanceof String) { 1754 | com.google.protobuf.ByteString b = 1755 | com.google.protobuf.ByteString.copyFromUtf8( 1756 | (String) ref); 1757 | token_ = b; 1758 | return b; 1759 | } else { 1760 | return (com.google.protobuf.ByteString) ref; 1761 | } 1762 | } 1763 | /** 1764 | * required string token = 9; 1765 | */ 1766 | public Builder setToken( 1767 | String value) { 1768 | if (value == null) { 1769 | throw new NullPointerException(); 1770 | } 1771 | bitField0_ |= 0x00000100; 1772 | token_ = value; 1773 | onChanged(); 1774 | return this; 1775 | } 1776 | /** 1777 | * required string token = 9; 1778 | */ 1779 | public Builder clearToken() { 1780 | bitField0_ = (bitField0_ & ~0x00000100); 1781 | token_ = getDefaultInstance().getToken(); 1782 | onChanged(); 1783 | return this; 1784 | } 1785 | /** 1786 | * required string token = 9; 1787 | */ 1788 | public Builder setTokenBytes( 1789 | com.google.protobuf.ByteString value) { 1790 | if (value == null) { 1791 | throw new NullPointerException(); 1792 | } 1793 | bitField0_ |= 0x00000100; 1794 | token_ = value; 1795 | onChanged(); 1796 | return this; 1797 | } 1798 | 1799 | private Object appKey_ = ""; 1800 | /** 1801 | * required string appKey = 10; 1802 | */ 1803 | public boolean hasAppKey() { 1804 | return ((bitField0_ & 0x00000200) == 0x00000200); 1805 | } 1806 | /** 1807 | * required string appKey = 10; 1808 | */ 1809 | public String getAppKey() { 1810 | Object ref = appKey_; 1811 | if (!(ref instanceof String)) { 1812 | com.google.protobuf.ByteString bs = 1813 | (com.google.protobuf.ByteString) ref; 1814 | String s = bs.toStringUtf8(); 1815 | if (bs.isValidUtf8()) { 1816 | appKey_ = s; 1817 | } 1818 | return s; 1819 | } else { 1820 | return (String) ref; 1821 | } 1822 | } 1823 | /** 1824 | * required string appKey = 10; 1825 | */ 1826 | public com.google.protobuf.ByteString 1827 | getAppKeyBytes() { 1828 | Object ref = appKey_; 1829 | if (ref instanceof String) { 1830 | com.google.protobuf.ByteString b = 1831 | com.google.protobuf.ByteString.copyFromUtf8( 1832 | (String) ref); 1833 | appKey_ = b; 1834 | return b; 1835 | } else { 1836 | return (com.google.protobuf.ByteString) ref; 1837 | } 1838 | } 1839 | /** 1840 | * required string appKey = 10; 1841 | */ 1842 | public Builder setAppKey( 1843 | String value) { 1844 | if (value == null) { 1845 | throw new NullPointerException(); 1846 | } 1847 | bitField0_ |= 0x00000200; 1848 | appKey_ = value; 1849 | onChanged(); 1850 | return this; 1851 | } 1852 | /** 1853 | * required string appKey = 10; 1854 | */ 1855 | public Builder clearAppKey() { 1856 | bitField0_ = (bitField0_ & ~0x00000200); 1857 | appKey_ = getDefaultInstance().getAppKey(); 1858 | onChanged(); 1859 | return this; 1860 | } 1861 | /** 1862 | * required string appKey = 10; 1863 | */ 1864 | public Builder setAppKeyBytes( 1865 | com.google.protobuf.ByteString value) { 1866 | if (value == null) { 1867 | throw new NullPointerException(); 1868 | } 1869 | bitField0_ |= 0x00000200; 1870 | appKey_ = value; 1871 | onChanged(); 1872 | return this; 1873 | } 1874 | 1875 | private Object timeStamp_ = ""; 1876 | /** 1877 | * required string timeStamp = 11; 1878 | */ 1879 | public boolean hasTimeStamp() { 1880 | return ((bitField0_ & 0x00000400) == 0x00000400); 1881 | } 1882 | /** 1883 | * required string timeStamp = 11; 1884 | */ 1885 | public String getTimeStamp() { 1886 | Object ref = timeStamp_; 1887 | if (!(ref instanceof String)) { 1888 | com.google.protobuf.ByteString bs = 1889 | (com.google.protobuf.ByteString) ref; 1890 | String s = bs.toStringUtf8(); 1891 | if (bs.isValidUtf8()) { 1892 | timeStamp_ = s; 1893 | } 1894 | return s; 1895 | } else { 1896 | return (String) ref; 1897 | } 1898 | } 1899 | /** 1900 | * required string timeStamp = 11; 1901 | */ 1902 | public com.google.protobuf.ByteString 1903 | getTimeStampBytes() { 1904 | Object ref = timeStamp_; 1905 | if (ref instanceof String) { 1906 | com.google.protobuf.ByteString b = 1907 | com.google.protobuf.ByteString.copyFromUtf8( 1908 | (String) ref); 1909 | timeStamp_ = b; 1910 | return b; 1911 | } else { 1912 | return (com.google.protobuf.ByteString) ref; 1913 | } 1914 | } 1915 | /** 1916 | * required string timeStamp = 11; 1917 | */ 1918 | public Builder setTimeStamp( 1919 | String value) { 1920 | if (value == null) { 1921 | throw new NullPointerException(); 1922 | } 1923 | bitField0_ |= 0x00000400; 1924 | timeStamp_ = value; 1925 | onChanged(); 1926 | return this; 1927 | } 1928 | /** 1929 | * required string timeStamp = 11; 1930 | */ 1931 | public Builder clearTimeStamp() { 1932 | bitField0_ = (bitField0_ & ~0x00000400); 1933 | timeStamp_ = getDefaultInstance().getTimeStamp(); 1934 | onChanged(); 1935 | return this; 1936 | } 1937 | /** 1938 | * required string timeStamp = 11; 1939 | */ 1940 | public Builder setTimeStampBytes( 1941 | com.google.protobuf.ByteString value) { 1942 | if (value == null) { 1943 | throw new NullPointerException(); 1944 | } 1945 | bitField0_ |= 0x00000400; 1946 | timeStamp_ = value; 1947 | onChanged(); 1948 | return this; 1949 | } 1950 | 1951 | private Object sign_ = ""; 1952 | /** 1953 | * required string sign = 12; 1954 | */ 1955 | public boolean hasSign() { 1956 | return ((bitField0_ & 0x00000800) == 0x00000800); 1957 | } 1958 | /** 1959 | * required string sign = 12; 1960 | */ 1961 | public String getSign() { 1962 | Object ref = sign_; 1963 | if (!(ref instanceof String)) { 1964 | com.google.protobuf.ByteString bs = 1965 | (com.google.protobuf.ByteString) ref; 1966 | String s = bs.toStringUtf8(); 1967 | if (bs.isValidUtf8()) { 1968 | sign_ = s; 1969 | } 1970 | return s; 1971 | } else { 1972 | return (String) ref; 1973 | } 1974 | } 1975 | /** 1976 | * required string sign = 12; 1977 | */ 1978 | public com.google.protobuf.ByteString 1979 | getSignBytes() { 1980 | Object ref = sign_; 1981 | if (ref instanceof String) { 1982 | com.google.protobuf.ByteString b = 1983 | com.google.protobuf.ByteString.copyFromUtf8( 1984 | (String) ref); 1985 | sign_ = b; 1986 | return b; 1987 | } else { 1988 | return (com.google.protobuf.ByteString) ref; 1989 | } 1990 | } 1991 | /** 1992 | * required string sign = 12; 1993 | */ 1994 | public Builder setSign( 1995 | String value) { 1996 | if (value == null) { 1997 | throw new NullPointerException(); 1998 | } 1999 | bitField0_ |= 0x00000800; 2000 | sign_ = value; 2001 | onChanged(); 2002 | return this; 2003 | } 2004 | /** 2005 | * required string sign = 12; 2006 | */ 2007 | public Builder clearSign() { 2008 | bitField0_ = (bitField0_ & ~0x00000800); 2009 | sign_ = getDefaultInstance().getSign(); 2010 | onChanged(); 2011 | return this; 2012 | } 2013 | /** 2014 | * required string sign = 12; 2015 | */ 2016 | public Builder setSignBytes( 2017 | com.google.protobuf.ByteString value) { 2018 | if (value == null) { 2019 | throw new NullPointerException(); 2020 | } 2021 | bitField0_ |= 0x00000800; 2022 | sign_ = value; 2023 | onChanged(); 2024 | return this; 2025 | } 2026 | 2027 | private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY; 2028 | /** 2029 | * optional bytes body = 20; 2030 | */ 2031 | public boolean hasBody() { 2032 | return ((bitField0_ & 0x00001000) == 0x00001000); 2033 | } 2034 | /** 2035 | * optional bytes body = 20; 2036 | */ 2037 | public com.google.protobuf.ByteString getBody() { 2038 | return body_; 2039 | } 2040 | /** 2041 | * optional bytes body = 20; 2042 | */ 2043 | public Builder setBody(com.google.protobuf.ByteString value) { 2044 | if (value == null) { 2045 | throw new NullPointerException(); 2046 | } 2047 | bitField0_ |= 0x00001000; 2048 | body_ = value; 2049 | onChanged(); 2050 | return this; 2051 | } 2052 | /** 2053 | * optional bytes body = 20; 2054 | */ 2055 | public Builder clearBody() { 2056 | bitField0_ = (bitField0_ & ~0x00001000); 2057 | body_ = getDefaultInstance().getBody(); 2058 | onChanged(); 2059 | return this; 2060 | } 2061 | 2062 | // @@protoc_insertion_point(builder_scope:JMTransfer) 2063 | } 2064 | 2065 | static { 2066 | defaultInstance = new JMTransfer(true); 2067 | defaultInstance.initFields(); 2068 | } 2069 | 2070 | // @@protoc_insertion_point(class_scope:JMTransfer) 2071 | } 2072 | 2073 | private static final com.google.protobuf.Descriptors.Descriptor 2074 | internal_static_JMTransfer_descriptor; 2075 | private static 2076 | com.google.protobuf.GeneratedMessage.FieldAccessorTable 2077 | internal_static_JMTransfer_fieldAccessorTable; 2078 | 2079 | public static com.google.protobuf.Descriptors.FileDescriptor 2080 | getDescriptor() { 2081 | return descriptor; 2082 | } 2083 | private static com.google.protobuf.Descriptors.FileDescriptor 2084 | descriptor; 2085 | static { 2086 | String[] descriptorData = { 2087 | "\n\020MessageBuf.proto\"\340\001\n\nJMTransfer\022\017\n\007ver" + 2088 | "sion\030\001 \002(\t\022\020\n\010deviceId\030\002 \002(\t\022\013\n\003cmd\030\003 \002(" + 2089 | "\r\022\013\n\003seq\030\004 \002(\004\022\016\n\006format\030\005 \002(\r\022\014\n\004flag\030\006" + 2090 | " \002(\r\022\020\n\010platform\030\007 \002(\t\022\027\n\017platformVersio" + 2091 | "n\030\010 \002(\t\022\r\n\005token\030\t \002(\t\022\016\n\006appKey\030\n \002(\t\022\021" + 2092 | "\n\ttimeStamp\030\013 \002(\t\022\014\n\004sign\030\014 \002(\t\022\014\n\004body\030" + 2093 | "\024 \001(\014" 2094 | }; 2095 | com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = 2096 | new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { 2097 | public com.google.protobuf.ExtensionRegistry assignDescriptors( 2098 | com.google.protobuf.Descriptors.FileDescriptor root) { 2099 | descriptor = root; 2100 | return null; 2101 | } 2102 | }; 2103 | com.google.protobuf.Descriptors.FileDescriptor 2104 | .internalBuildGeneratedFileFrom(descriptorData, 2105 | new com.google.protobuf.Descriptors.FileDescriptor[] { 2106 | }, assigner); 2107 | internal_static_JMTransfer_descriptor = 2108 | getDescriptor().getMessageTypes().get(0); 2109 | internal_static_JMTransfer_fieldAccessorTable = new 2110 | com.google.protobuf.GeneratedMessage.FieldAccessorTable( 2111 | internal_static_JMTransfer_descriptor, 2112 | new String[] { "Version", "DeviceId", "Cmd", "Seq", "Format", "Flag", "Platform", "PlatformVersion", "Token", "AppKey", "TimeStamp", "Sign", "Body", }); 2113 | } 2114 | 2115 | // @@protoc_insertion_point(outer_class_scope) 2116 | } 2117 | --------------------------------------------------------------------------------