├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── interface ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── anyflow │ │ └── lannister │ │ └── plugin │ │ ├── Authenticator.java │ │ ├── Authorizer.java │ │ ├── ConnectEventArgs.java │ │ ├── ConnectEventListener.java │ │ ├── DeliveredEventArgs.java │ │ ├── DeliveredEventListener.java │ │ ├── DisconnectEventArgs.java │ │ ├── DisconnectEventListener.java │ │ ├── IMessage.java │ │ ├── ITopicSubscription.java │ │ ├── Plugin.java │ │ ├── PublishEventArgs.java │ │ ├── PublishEventListener.java │ │ ├── ServiceChecker.java │ │ ├── SubscribeEventArgs.java │ │ ├── SubscribeEventListener.java │ │ ├── UnsubscribeEventArgs.java │ │ └── UnsubscribeEventListener.java │ └── site │ └── site.xml ├── plugin-example ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── anyflow │ │ └── lannister │ │ └── pluginexample │ │ ├── ExampleAuthenticator.java │ │ ├── ExampleAuthorizer.java │ │ ├── ExampleConnectEventListener.java │ │ ├── ExampleDeliveredEventListener.java │ │ ├── ExampleDisconnectEventListener.java │ │ ├── ExamplePublishEventListener.java │ │ ├── ExampleServiceChecker.java │ │ ├── ExampleSubscribeEventListener.java │ │ └── ExampleUnsubscribeEventListener.java │ └── site │ └── site.xml ├── pom.xml ├── server ├── pom.xml └── src │ ├── main │ ├── assembly │ │ └── dep.xml │ ├── filters │ │ ├── default.properties │ │ └── docker.properties │ ├── java │ │ └── net │ │ │ └── anyflow │ │ │ └── lannister │ │ │ ├── AbnormalDisconnectEventArgs.java │ │ │ ├── Application.java │ │ │ ├── Literals.java │ │ │ ├── NettyUtil.java │ │ │ ├── Settings.java │ │ │ ├── Statistics.java │ │ │ ├── client │ │ │ ├── MessageReceiver.java │ │ │ ├── MqttClient.java │ │ │ ├── MqttPacketReceiver.java │ │ │ └── SharedObject.java │ │ │ ├── cluster │ │ │ ├── ClusterDataDisposer.java │ │ │ ├── ClusterDataFactory.java │ │ │ ├── Hazelcast.java │ │ │ ├── HazelcastMap.java │ │ │ ├── HazelcastSet.java │ │ │ ├── HazelcastSetValueMap.java │ │ │ ├── Ignite.java │ │ │ ├── IgniteMap.java │ │ │ ├── Map.java │ │ │ ├── Mode.java │ │ │ ├── NativeMap.java │ │ │ ├── NativeSet.java │ │ │ ├── NativeSetValueMap.java │ │ │ ├── SerializableIntegerSet.java │ │ │ ├── SerializableStringSet.java │ │ │ ├── Set.java │ │ │ ├── SingleIdGenerator.java │ │ │ └── SingleTopic.java │ │ │ ├── http │ │ │ ├── HtmlGenerator.java │ │ │ ├── HttpClient.java │ │ │ ├── HttpClientHandler.java │ │ │ ├── HttpConstants.java │ │ │ ├── HttpRequest.java │ │ │ ├── HttpRequestHandler.java │ │ │ ├── HttpRequestRouter.java │ │ │ ├── HttpResponse.java │ │ │ ├── IHttpClient.java │ │ │ ├── MessageReceiver.java │ │ │ ├── WebServer.java │ │ │ ├── WebServerChannelInitializer.java │ │ │ └── WebsocketFrameHandler.java │ │ │ ├── httphandler │ │ │ ├── Index.java │ │ │ ├── admin │ │ │ │ └── Index.java │ │ │ └── api │ │ │ │ ├── Clients.java │ │ │ │ ├── InboundMessageStatuses.java │ │ │ │ ├── MessageReferenceCounts.java │ │ │ │ ├── Messages.java │ │ │ │ ├── OutboundMessageStatuses.java │ │ │ │ ├── Sessions.java │ │ │ │ ├── Statistics.java │ │ │ │ ├── TopicSubscribers.java │ │ │ │ ├── TopicSubscriptions.java │ │ │ │ └── Topics.java │ │ │ ├── message │ │ │ ├── ConnectOptions.java │ │ │ ├── InboundMessageStatus.java │ │ │ ├── InboundMessageStatuses.java │ │ │ ├── Message.java │ │ │ ├── MessageReferenceCounts.java │ │ │ ├── MessageStatus.java │ │ │ ├── Messages.java │ │ │ ├── OutboundMessageStatus.java │ │ │ └── OutboundMessageStatuses.java │ │ │ ├── packetreceiver │ │ │ ├── ConnectReceiver.java │ │ │ ├── DisconnectReceiver.java │ │ │ ├── GenericReceiver.java │ │ │ ├── MqttMessageFactory.java │ │ │ ├── PingReqReceiver.java │ │ │ ├── PubAckReceiver.java │ │ │ ├── PubCompReceiver.java │ │ │ ├── PubRecReceiver.java │ │ │ ├── PubRelReceiver.java │ │ │ ├── PublishReceiver.java │ │ │ ├── SubscribeReceiver.java │ │ │ └── UnsubscribeReceiver.java │ │ │ ├── plugin │ │ │ ├── DefaultAuthenticator.java │ │ │ ├── DefaultAuthorizer.java │ │ │ ├── DefaultConnectEventListener.java │ │ │ ├── DefaultDeliveredEventListener.java │ │ │ ├── DefaultDisconnectEventListener.java │ │ │ ├── DefaultPublishEventListener.java │ │ │ ├── DefaultServiceChecker.java │ │ │ ├── DefaultSubscribeEventListener.java │ │ │ ├── DefaultUnsubscribeEventListener.java │ │ │ └── Plugins.java │ │ │ ├── serialization │ │ │ ├── ChannelIdSerializer.java │ │ │ ├── HazelcastSerializer.java │ │ │ ├── JsonSerializer.java │ │ │ ├── MapSerializer.java │ │ │ ├── SerializableFactory.java │ │ │ └── SysValueSerializer.java │ │ │ ├── server │ │ │ ├── ByteCounterCodec.java │ │ │ ├── MqttChannelInitializer.java │ │ │ ├── MqttServer.java │ │ │ ├── MqttWebSocketCodec.java │ │ │ └── ScheduledExecutor.java │ │ │ ├── session │ │ │ ├── MessageSender.java │ │ │ ├── Session.java │ │ │ └── Sessions.java │ │ │ └── topic │ │ │ ├── Notification.java │ │ │ ├── Topic.java │ │ │ ├── TopicMatcher.java │ │ │ ├── TopicSubscriber.java │ │ │ ├── TopicSubscribers.java │ │ │ ├── TopicSubscription.java │ │ │ ├── TopicSubscriptions.java │ │ │ └── Topics.java │ ├── resources │ │ ├── lannister.cluster.xml │ │ ├── lannister.log4j.xml │ │ ├── lannister.properties │ │ ├── mime_types.json │ │ ├── shutdown.sh │ │ └── startup.sh │ └── webapp │ │ └── index.html │ ├── site │ └── site.xml │ └── test │ ├── java │ └── net │ │ └── anyflow │ │ └── lannister │ │ ├── NettyUtilTest.java │ │ ├── TestSuite.java │ │ ├── TestUtil.java │ │ ├── httphandler │ │ ├── IndexTest.java │ │ └── api │ │ │ ├── ClientsTest.java │ │ │ ├── SessionsTest.java │ │ │ └── TopicsTest.java │ │ ├── packetreceiver │ │ └── ConnectReceiverTest.java │ │ ├── server │ │ ├── MqttServerTest.java │ │ └── SessionExpiratorTest.java │ │ ├── session │ │ ├── SessionTest.java │ │ └── WillTest.java │ │ └── topic │ │ ├── TopicMatcherTest.java │ │ └── TopicTest.java │ └── resources │ ├── lannister.cluster.xml │ ├── lannister.log4j.xml │ └── lannister.properties └── src └── site ├── markdown ├── clustering.md ├── configuration.md ├── dollarSys.md ├── gettingStarted.md ├── history.md ├── index.md ├── plugin.md ├── restapis.md ├── specification.md └── structure.md ├── resources └── images │ └── clustering_architecture.svg └── site.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Package Files # 2 | #*.jar 3 | .DS_Store 4 | .vscode 5 | # directories # 6 | **/target/ 7 | **/logs/ 8 | **/bin/ 9 | 10 | # eclipse related # 11 | **/.settings 12 | **/.classpath 13 | **/.project 14 | **/.pmd 15 | 16 | #buildinfo 17 | **/buildinfo.properties 18 | 19 | upload_coverage.sh 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: mvn clean install 3 | jdk: 4 | - oraclejdk8 5 | git: 6 | depth: 500 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 The Lannister Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # docker images 18 | # docker ps -a 19 | # docker rm 'container-name' 20 | # docker rmi 'image-name' 21 | 22 | # docker build -t lannister . 23 | # docker run -it -p 11883:1883 -p 18883:8883 -p 19001:9001 -p 19002:9002 -p 18090:8090 -p 18493:8493 --name lannister lannister 24 | 25 | FROM anyflow/javaserver 26 | MAINTAINER Park Hyunjeong 27 | 28 | RUN mkdir /opt/lannister/ 29 | RUN mkdir /opt/lannister/logs 30 | RUN touch /opt/lannister/logs/application.log 31 | RUN touch /opt/lannister/logs/output.log 32 | 33 | ADD server/target/bin/* /opt/lannister/bin/ 34 | ADD server/target/conf/* /opt/lannister/conf/ 35 | ADD server/target/lib/* /opt/lannister/lib/ 36 | ADD server/target/webapp/* /opt/lannister/webapp/ 37 | 38 | RUN chmod 700 /opt/lannister/bin/startup.sh 39 | RUN chmod 700 /opt/lannister/bin/shutdown.sh 40 | 41 | EXPOSE 1883 42 | EXPOSE 8883 43 | EXPOSE 9001 44 | EXPOSE 9002 45 | EXPOSE 8090 46 | EXPOSE 8493 47 | 48 | CMD /opt/lannister/bin/startup.sh && /bin/bash -------------------------------------------------------------------------------- /interface/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | lannister-interface 20 | Lannister interface 21 | Common interface and data structure for both lannister-server and lannister-plugin-example 22 | 23 | net.anyflow 24 | lannister 25 | 0.9.9-SNAPSHOT 26 | 27 | jar 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-project-info-reports-plugin 36 | 2.9 37 | 38 | false 39 | 40 | 41 | 42 | 43 | index 44 | summary 45 | dependencies 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/Authenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface Authenticator extends Plugin { 20 | boolean isValid(String clientId); 21 | 22 | boolean isValid(String clientId, String userName, String password); 23 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/Authorizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface Authorizer extends Plugin { 20 | boolean isAuthorized(String clientId, String username); 21 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/ConnectEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | import io.netty.handler.codec.mqtt.MqttConnectReturnCode; 20 | 21 | public interface ConnectEventArgs { 22 | String clientId(); 23 | 24 | IMessage will(); 25 | 26 | Boolean cleanSession(); 27 | 28 | MqttConnectReturnCode returnCode(); 29 | 30 | default public String log() { 31 | return (new StringBuilder()).append("clientId=").append(clientId()).append(", will=").append(will()) 32 | .append(", cleanSession=").append(cleanSession()).append(", returnCode=").append(returnCode()) 33 | .toString(); 34 | } 35 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/ConnectEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface ConnectEventListener extends Plugin { 20 | 21 | public void connectHandled(ConnectEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/DeliveredEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface DeliveredEventArgs { 20 | String clientId(); 21 | 22 | int messageId(); 23 | 24 | default public String log() { 25 | return (new StringBuilder()).append("clientId=").append(clientId()).append(", messageId=").append(messageId()) 26 | .toString(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/DeliveredEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface DeliveredEventListener extends Plugin { 20 | 21 | public void delivered(DeliveredEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/DisconnectEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface DisconnectEventArgs { 20 | String clientId(); 21 | 22 | Boolean cleanSession(); 23 | 24 | Boolean byDisconnectMessage(); 25 | 26 | default public String log() { 27 | return (new StringBuilder()).append("clientId=").append(clientId()).append(", cleanSession=") 28 | .append(cleanSession()).append(", byDisconnectMessage=").append(byDisconnectMessage()).toString(); 29 | } 30 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/DisconnectEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface DisconnectEventListener extends Plugin { 20 | 21 | public void disconnected(DisconnectEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/IMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | import java.util.Arrays; 20 | 21 | import io.netty.handler.codec.mqtt.MqttQoS; 22 | 23 | /** 24 | * Represent MQTT message. 25 | */ 26 | public interface IMessage { 27 | /** 28 | * @return message identifier(packet identifier in MQTT 3.1.1) 29 | */ 30 | int id(); 31 | 32 | /** 33 | * @return topic's name the message belongs to 34 | */ 35 | String topicName(); 36 | 37 | /** 38 | * @return client identifier whose client published the message 39 | */ 40 | String publisherId(); 41 | 42 | /** 43 | * @return message itself 44 | */ 45 | byte[] message(); 46 | 47 | /** 48 | * @return message QoS. The value can be used different in client publishing 49 | * time and broker publishing time 50 | */ 51 | MqttQoS qos(); 52 | 53 | /** 54 | * @return whether the message is retained or not 55 | */ 56 | boolean isRetain(); 57 | 58 | default String log() { 59 | return (new StringBuilder()).append("messageId=").append(id()).append(", topicName=").append(topicName()) 60 | .append(", publisherId=").append(publisherId()).append(", message=").append(Arrays.toString(message())) 61 | .append(", qos=").append(qos()).append(", isRetain=").append(isRetain()).toString(); 62 | } 63 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/ITopicSubscription.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | import io.netty.handler.codec.mqtt.MqttQoS; 20 | 21 | public interface ITopicSubscription { 22 | 23 | String clientId(); 24 | 25 | String topicFilter(); 26 | 27 | MqttQoS qos(); 28 | 29 | default String log() { 30 | return (new StringBuilder()).append("clientId=").append(clientId()).append("topicFilter=").append(topicFilter()) 31 | .append(", qos=").append(qos()).toString(); 32 | } 33 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/Plugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface Plugin extends Cloneable { 20 | Plugin clone(); 21 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/PublishEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface PublishEventArgs { 20 | IMessage message(); 21 | 22 | default String log() { 23 | return (new StringBuilder()).append(message().log()).toString(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/PublishEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface PublishEventListener extends Plugin { 20 | 21 | public boolean allowPublish(PublishEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/ServiceChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface ServiceChecker extends Plugin { 20 | boolean isServiceAvailable(); 21 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/SubscribeEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | import java.util.List; 20 | 21 | public interface SubscribeEventArgs { 22 | String clientId(); 23 | 24 | boolean cleanSession(); 25 | 26 | List topicSubscriptions(); 27 | 28 | default String log() { 29 | StringBuilder sb = new StringBuilder(); 30 | 31 | if (topicSubscriptions() == null) { return null; } 32 | 33 | topicSubscriptions().stream().forEach(ts -> sb.append("|").append(ts.log())); 34 | 35 | return sb.toString(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/SubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface SubscribeEventListener extends Plugin { 20 | 21 | public boolean allowSubscribe(SubscribeEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/UnsubscribeEventArgs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | import java.util.List; 20 | 21 | public interface UnsubscribeEventArgs { 22 | String clientId(); 23 | 24 | List topicFilters(); 25 | 26 | default String log() { 27 | if (topicFilters() == null) { return null; } 28 | 29 | StringBuilder sb = new StringBuilder(); 30 | sb.append("clientId=").append(clientId()); 31 | 32 | topicFilters().stream().forEach(t -> sb.append(", topicFilter=").append(t)); 33 | 34 | return sb.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /interface/src/main/java/net/anyflow/lannister/plugin/UnsubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public interface UnsubscribeEventListener extends Plugin { 20 | 21 | public void unsubscribed(UnsubscribeEventArgs args); 22 | } -------------------------------------------------------------------------------- /interface/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lannister 4 | 5 | 6 | org.apache.maven.skins 7 | maven-fluido-skin 8 | 1.5 9 | 10 | 11 | 12 | true 13 | true 14 | 15 | anyflow/lannister 16 | right 17 | darkblue 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /plugin-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | lannister-plugin-example 20 | Lannister plugin example 21 | Lannister Plug-In example 22 | 23 | net.anyflow 24 | lannister 25 | 0.9.9-SNAPSHOT 26 | 27 | jar 28 | 29 | 30 | net.anyflow 31 | lannister-interface 32 | ${project.version} 33 | 34 | 35 | 36 | 37 | 38 | org.apache.maven.plugins 39 | maven-antrun-plugin 40 | 1.7 41 | 42 | 43 | package 44 | 45 | run 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-project-info-reports-plugin 66 | 2.9 67 | 68 | false 69 | 70 | 71 | 72 | 73 | index 74 | summary 75 | dependencies 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleAuthenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Authenticator; 20 | import net.anyflow.lannister.plugin.Plugin; 21 | 22 | public class ExampleAuthenticator implements Authenticator { 23 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExampleAuthenticator.class); 24 | 25 | @Override 26 | public Plugin clone() { 27 | return new ExampleAuthenticator(); 28 | } 29 | 30 | @Override 31 | public boolean isValid(String clientId) { 32 | logger.debug("ExampleAuthenticator.isValid() called [clientId={}]", clientId); 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean isValid(String clientId, String userName, String password) { 38 | logger.debug("ExampleAuthenticator.isValid() called [clientId={}, userName={}, password={}]", clientId, 39 | userName, password); 40 | return true; 41 | } 42 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleAuthorizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Authorizer; 20 | import net.anyflow.lannister.plugin.Plugin; 21 | 22 | public class ExampleAuthorizer implements Authorizer { 23 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExampleAuthorizer.class); 24 | 25 | @Override 26 | public Plugin clone() { 27 | return new ExampleAuthorizer(); 28 | } 29 | 30 | @Override 31 | public boolean isAuthorized(String clientId, String userName) { 32 | logger.debug("ExampleAuthorizer.isAuthorized() called [clientId={}, userName={}]", clientId, userName); 33 | return true; 34 | } 35 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleConnectEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.ConnectEventArgs; 20 | import net.anyflow.lannister.plugin.ConnectEventListener; 21 | import net.anyflow.lannister.plugin.Plugin; 22 | 23 | public class ExampleConnectEventListener implements ConnectEventListener { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExampleConnectEventListener.class); 25 | 26 | @Override 27 | public Plugin clone() { 28 | return new ExampleConnectEventListener(); 29 | } 30 | 31 | @Override 32 | public void connectHandled(ConnectEventArgs args) { 33 | logger.debug("DefaultConnectEventListener.connectHandled() called [{}]", args.log()); 34 | } 35 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleDeliveredEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.DeliveredEventArgs; 20 | import net.anyflow.lannister.plugin.DeliveredEventListener; 21 | import net.anyflow.lannister.plugin.Plugin; 22 | 23 | public class ExampleDeliveredEventListener implements DeliveredEventListener { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 25 | .getLogger(ExampleDeliveredEventListener.class); 26 | 27 | @Override 28 | public Plugin clone() { 29 | return this; 30 | } 31 | 32 | @Override 33 | public void delivered(DeliveredEventArgs args) { 34 | logger.debug("ExampleDeliveredEventListener.delivered() called [{}]", args.log()); 35 | } 36 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleDisconnectEventListener.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.pluginexample; 2 | 3 | import net.anyflow.lannister.plugin.DisconnectEventArgs; 4 | import net.anyflow.lannister.plugin.DisconnectEventListener; 5 | import net.anyflow.lannister.plugin.Plugin; 6 | 7 | public class ExampleDisconnectEventListener implements DisconnectEventListener { 8 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 9 | .getLogger(ExampleDisconnectEventListener.class); 10 | 11 | @Override 12 | public Plugin clone() { 13 | return new ExampleDisconnectEventListener(); 14 | } 15 | 16 | @Override 17 | public void disconnected(DisconnectEventArgs args) { 18 | logger.debug("ExampleDisconnectEventListener.disconnected() called [{}]", args.log()); 19 | } 20 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExamplePublishEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Plugin; 20 | import net.anyflow.lannister.plugin.PublishEventArgs; 21 | import net.anyflow.lannister.plugin.PublishEventListener; 22 | 23 | public class ExamplePublishEventListener implements PublishEventListener { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExamplePublishEventListener.class); 25 | 26 | @Override 27 | public Plugin clone() { 28 | return new ExamplePublishEventListener(); 29 | } 30 | 31 | @Override 32 | public boolean allowPublish(PublishEventArgs args) { 33 | logger.debug("ExamplePublishEventListener.allowPublish() called [{}]", args.log()); 34 | return true; 35 | } 36 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleServiceChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Plugin; 20 | import net.anyflow.lannister.plugin.ServiceChecker; 21 | 22 | public class ExampleServiceChecker implements ServiceChecker { 23 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExampleServiceChecker.class); 24 | 25 | @Override 26 | public Plugin clone() { 27 | return new ExampleServiceChecker(); 28 | } 29 | 30 | @Override 31 | public boolean isServiceAvailable() { 32 | logger.debug("ExampleServiceStatus.isServiceAvailable() called"); 33 | return true; 34 | } 35 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleSubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Plugin; 20 | import net.anyflow.lannister.plugin.SubscribeEventArgs; 21 | import net.anyflow.lannister.plugin.SubscribeEventListener; 22 | 23 | public class ExampleSubscribeEventListener implements SubscribeEventListener { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 25 | .getLogger(ExampleSubscribeEventListener.class); 26 | 27 | @Override 28 | public Plugin clone() { 29 | return this; 30 | } 31 | 32 | @Override 33 | public boolean allowSubscribe(SubscribeEventArgs args) { 34 | logger.debug("ExampleSubscribeEventListener.allowSubscribe() called [{}]", args.log()); 35 | return true; 36 | } 37 | } -------------------------------------------------------------------------------- /plugin-example/src/main/java/net/anyflow/lannister/pluginexample/ExampleUnsubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.pluginexample; 18 | 19 | import net.anyflow.lannister.plugin.Plugin; 20 | import net.anyflow.lannister.plugin.UnsubscribeEventArgs; 21 | import net.anyflow.lannister.plugin.UnsubscribeEventListener; 22 | 23 | public class ExampleUnsubscribeEventListener implements UnsubscribeEventListener { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 25 | .getLogger(ExampleUnsubscribeEventListener.class); 26 | 27 | @Override 28 | public Plugin clone() { 29 | return this; 30 | } 31 | 32 | @Override 33 | public void unsubscribed(UnsubscribeEventArgs args) { 34 | logger.debug("ExampleUnsubscribeEventListener.unsubscribed() called [{}]", args.log()); 35 | } 36 | } -------------------------------------------------------------------------------- /plugin-example/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lannister 4 | 5 | 6 | org.apache.maven.skins 7 | maven-fluido-skin 8 | 1.5 9 | 10 | 11 | 12 | true 13 | true 14 | 15 | anyflow/lannister 16 | right 17 | darkblue 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /server/src/main/assembly/dep.xml: -------------------------------------------------------------------------------- 1 | 4 | bin 5 | 6 | zip 7 | tar.gz 8 | tar.bz2 9 | 10 | false 11 | 12 | 13 | target 14 | 0744 15 | ./ 16 | 17 | bin/* 18 | 19 | 20 | 21 | target 22 | 0644 23 | ./ 24 | 25 | README.md 26 | LICENSE 27 | conf/* 28 | lib/* 29 | webapp/* 30 | plugin/* 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /server/src/main/filters/default.properties: -------------------------------------------------------------------------------- 1 | log.level=DEBUG 2 | log.path=./../logs 3 | 4 | clustering.mode=hazelcast 5 | 6 | hazelcast.port=5701 7 | hazelcast.port-count=100 8 | 9 | hazelcast.multicast.enabled=true 10 | hazelcast.multicast-group=224.2.2.3 11 | hazelcast.multicast-port=54327 12 | 13 | hazelcast.tcp-ip.enabled=false 14 | hazelcast.member1=127.0.0.1 15 | hazelcast.member2=127.0.0.1 16 | 17 | project.build.startOption= 18 | -------------------------------------------------------------------------------- /server/src/main/filters/docker.properties: -------------------------------------------------------------------------------- 1 | log.level=INFO 2 | log.path=./../logs 3 | 4 | clustering.mode=hazelcast 5 | 6 | hazelcast.port=5701 7 | hazelcast.port-count=1 8 | 9 | hazelcast.multicast.enabled=false 10 | hazelcast.multicast-group=224.2.2.3 11 | hazelcast.multicast-port=54327 12 | 13 | hazelcast.tcp-ip.enabled=true 14 | hazelcast.member1=172.20.0.2 15 | hazelcast.member2=172.20.0.3 16 | 17 | project.build.startOption= -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/AbnormalDisconnectEventArgs.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister; 2 | 3 | import net.anyflow.lannister.plugin.DisconnectEventArgs; 4 | 5 | public class AbnormalDisconnectEventArgs implements DisconnectEventArgs { 6 | @Override 7 | public String clientId() { 8 | return null; 9 | } 10 | 11 | @Override 12 | public Boolean cleanSession() { 13 | return null; 14 | } 15 | 16 | @Override 17 | public Boolean byDisconnectMessage() { 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/Literals.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister; 18 | 19 | public class Literals { 20 | 21 | public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"; 22 | public static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8"; 23 | 24 | public static final String APPLICATION_JSON = "application/json"; 25 | public static final String APPLICATION_XML = "application/xml"; 26 | 27 | public static final String DATE_DEFAULT_FORMAT = "yy.MM.dd HH:mm:ss.SSS z"; 28 | public static final String DATE_TIME_FORMAT = "HH:mm:ss.SSS"; 29 | public static final String DATE_DEFAULT_TIMEZONE = "Asia/Seoul"; 30 | 31 | public static final String NETTY_EPOLL = "epoll"; 32 | public static final String NETTY_NIO = "NIO"; 33 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/NettyUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister; 18 | 19 | import io.netty.buffer.ByteBuf; 20 | 21 | public class NettyUtil { 22 | public static byte[] copy(ByteBuf buffer) { 23 | byte[] bytes = new byte[buffer.readableBytes()]; 24 | 25 | int readerIndex = buffer.readerIndex(); 26 | buffer.getBytes(readerIndex, bytes); 27 | 28 | return bytes; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/client/MessageReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.client; 18 | 19 | import net.anyflow.lannister.plugin.IMessage; 20 | 21 | public interface MessageReceiver { 22 | void messageReceived(IMessage message); 23 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/client/MqttPacketReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.client; 18 | 19 | import io.netty.channel.ChannelHandlerContext; 20 | import io.netty.channel.SimpleChannelInboundHandler; 21 | import io.netty.handler.codec.mqtt.MqttMessage; 22 | import io.netty.handler.codec.mqtt.MqttMessageIdVariableHeader; 23 | import io.netty.handler.codec.mqtt.MqttPublishMessage; 24 | import io.netty.handler.codec.mqtt.MqttQoS; 25 | import net.anyflow.lannister.message.Message; 26 | import net.anyflow.lannister.packetreceiver.MqttMessageFactory; 27 | 28 | public class MqttPacketReceiver extends SimpleChannelInboundHandler { 29 | @SuppressWarnings("unused") 30 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MqttPacketReceiver.class); 31 | 32 | private final MqttClient client; 33 | private final MessageReceiver receiver; 34 | private final SharedObject sharedObject; 35 | 36 | protected MqttPacketReceiver(MqttClient client, MessageReceiver receiver, SharedObject sharedObject) { 37 | this.client = client; 38 | this.receiver = receiver; 39 | this.sharedObject = sharedObject; 40 | } 41 | 42 | @Override 43 | protected void channelRead0(ChannelHandlerContext ctx, MqttMessage msg) throws Exception { 44 | switch (msg.fixedHeader().messageType()) { 45 | case PUBLISH: 46 | if (receiver != null) { 47 | receiver.messageReceived(Message.newMessage(client.clientId(), (MqttPublishMessage) msg)); 48 | } 49 | 50 | int messageId = ((MqttPublishMessage) msg).variableHeader().messageId(); 51 | if (((MqttPublishMessage) msg).fixedHeader().qosLevel() == MqttQoS.AT_LEAST_ONCE) { 52 | client.send(MqttMessageFactory.puback(messageId)); 53 | } 54 | else if (((MqttPublishMessage) msg).fixedHeader().qosLevel() == MqttQoS.EXACTLY_ONCE) { 55 | client.send(MqttMessageFactory.pubrec(messageId)); 56 | } 57 | break; 58 | 59 | case CONNACK: 60 | sharedObject.receivedMessage(msg); 61 | 62 | synchronized (sharedObject.locker()) { 63 | sharedObject.locker().notify(); 64 | } 65 | break; 66 | 67 | case PUBREC: 68 | client.send(MqttMessageFactory.pubrel(((MqttMessageIdVariableHeader) msg.variableHeader()).messageId())); 69 | break; 70 | 71 | case SUBACK: 72 | case PUBACK: 73 | case PUBCOMP: 74 | default: 75 | break; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/client/SharedObject.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.client; 2 | 3 | import io.netty.handler.codec.mqtt.MqttMessage; 4 | 5 | public class SharedObject { 6 | private MqttMessage receivedMessage; 7 | private Object locker; 8 | 9 | public SharedObject() { 10 | receivedMessage = null; 11 | locker = new Object(); 12 | } 13 | 14 | public Object locker() { 15 | return locker; 16 | } 17 | 18 | public MqttMessage receivedMessage() { 19 | return receivedMessage; 20 | } 21 | 22 | public void receivedMessage(MqttMessage receivedMessage) { 23 | this.receivedMessage = receivedMessage; 24 | } 25 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/ClusterDataDisposer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.concurrent.locks.Lock; 19 | 20 | import com.hazelcast.core.ILock; 21 | 22 | import net.anyflow.lannister.Settings; 23 | 24 | public class ClusterDataDisposer { 25 | public static final ClusterDataDisposer INSTANCE = new ClusterDataDisposer(); 26 | 27 | private ClusterDataDisposer() { 28 | } 29 | 30 | public void disposeLock(Lock lock) { 31 | switch (Settings.INSTANCE.clusteringMode()) { 32 | case HAZELCAST: 33 | ((ILock) lock).destroy(); 34 | break; 35 | 36 | case IGNITE: 37 | break; 38 | 39 | case SINGLE: 40 | break; 41 | 42 | default: 43 | break; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/HazelcastMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.Set; 19 | 20 | public class HazelcastMap implements Map { 21 | 22 | private com.hazelcast.core.IMap engine; 23 | 24 | public HazelcastMap(String name) { 25 | engine = Hazelcast.INSTANCE.getMap(name); 26 | } 27 | 28 | @Override 29 | public void put(K key, V value) { 30 | engine.set(key, value); 31 | } 32 | 33 | @Override 34 | public V get(K key) { 35 | return engine.get(key); 36 | } 37 | 38 | @Override 39 | public V remove(K key) { 40 | return engine.remove(key); 41 | } 42 | 43 | @Override 44 | public int size() { 45 | return engine.size(); 46 | } 47 | 48 | @Override 49 | public void dispose() { 50 | engine.destroy(); 51 | } 52 | 53 | @Override 54 | public boolean containsKey(K key) { 55 | return engine.containsKey(key); 56 | } 57 | 58 | @Override 59 | public Set keySet() { 60 | return engine.keySet(); 61 | } 62 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/HazelcastSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.stream.Stream; 19 | 20 | import com.hazelcast.core.ISet; 21 | 22 | public class HazelcastSet implements Set { 23 | private final ISet engine; 24 | 25 | protected HazelcastSet(String name) { 26 | engine = Hazelcast.INSTANCE.getSet(name); 27 | } 28 | 29 | @Override 30 | public Stream stream() { 31 | return engine.stream(); 32 | } 33 | 34 | @Override 35 | public boolean remove(V value) { 36 | return engine.remove(value); 37 | } 38 | 39 | @Override 40 | public boolean add(V value) { 41 | return engine.add(value); 42 | } 43 | 44 | @Override 45 | public void dispose() { 46 | engine.destroy(); 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/HazelcastSetValueMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.HashMap; 19 | 20 | import com.google.common.collect.Maps; 21 | import com.hazelcast.core.IdGenerator; 22 | 23 | public class HazelcastSetValueMap implements Map> { 24 | private static final IdGenerator ID_GENERATOR = Hazelcast.INSTANCE.getIdGenerator("HazelcastSetValueMap"); 25 | 26 | private final com.hazelcast.core.IMap engine; 27 | private final HashMap> values; 28 | private final String valueKeyPrefix; 29 | 30 | public HazelcastSetValueMap(String name) { 31 | engine = Hazelcast.INSTANCE.getMap(name); 32 | values = Maps.newHashMap(); 33 | valueKeyPrefix = Long.toString(ID_GENERATOR.newId()); 34 | } 35 | 36 | @Override 37 | public void put(K key, Set value) { 38 | String valueKey = valueKey(key); 39 | 40 | Set prev = values.put(valueKey, value); 41 | if (prev != null) { 42 | prev.dispose(); 43 | } 44 | 45 | engine.set(key, valueKey); 46 | } 47 | 48 | private String valueKey(K key) { 49 | return valueKeyPrefix + "_" + key.toString(); 50 | } 51 | 52 | @Override 53 | public Set get(K key) { 54 | return values.get(engine.get(key)); 55 | } 56 | 57 | @Override 58 | public Set remove(K key) { 59 | String valueKey = engine.remove(key); 60 | if (valueKey == null) { return null; } 61 | 62 | return values.remove(valueKey); 63 | } 64 | 65 | @Override 66 | public int size() { 67 | return engine.size(); 68 | } 69 | 70 | @Override 71 | public void dispose() { 72 | engine.destroy(); 73 | } 74 | 75 | @Override 76 | public boolean containsKey(K key) { 77 | return engine.containsKey(key); 78 | } 79 | 80 | @Override 81 | public java.util.Set keySet() { 82 | return engine.keySet(); 83 | } 84 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/Ignite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import org.apache.ignite.IgniteCache; 19 | import org.apache.ignite.Ignition; 20 | 21 | public class Ignite { 22 | @SuppressWarnings("unused") 23 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Hazelcast.class); 24 | 25 | @SuppressWarnings("unused") 26 | private static final String CONFIG_NAME = "lannister.ignite.xml"; 27 | 28 | public static final Ignite INSTANCE = new Ignite(); 29 | 30 | private org.apache.ignite.Ignite substance; 31 | 32 | private Ignite() { 33 | substance = Ignition.start(); 34 | } 35 | 36 | public IgniteCache getCache(String name) { 37 | return substance.getOrCreateCache(name); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/IgniteMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.Set; 19 | import java.util.stream.Collectors; 20 | 21 | import javax.cache.Cache; 22 | 23 | import org.apache.ignite.IgniteCache; 24 | import org.apache.ignite.cache.query.ScanQuery; 25 | 26 | public class IgniteMap implements Map { 27 | 28 | private IgniteCache engine; 29 | 30 | public IgniteMap(String name) { 31 | engine = Ignite.INSTANCE.getCache(name); 32 | } 33 | 34 | @Override 35 | public void put(K key, V value) { 36 | engine.put(key, value); 37 | } 38 | 39 | @Override 40 | public V get(K key) { 41 | return engine.get(key); 42 | } 43 | 44 | @Override 45 | public V remove(K key) { 46 | return engine.getAndRemove(key); 47 | } 48 | 49 | @Override 50 | public Set keySet() { 51 | return engine.query(new ScanQuery()).getAll().stream().map(Cache.Entry::getKey) 52 | .collect(Collectors.toSet()); 53 | } 54 | 55 | @Override 56 | public int size() { 57 | return engine.size(); 58 | } 59 | 60 | @Override 61 | public void dispose() { 62 | engine.destroy(); 63 | } 64 | 65 | @Override 66 | public boolean containsKey(K key) { 67 | return engine.containsKey(key); 68 | } 69 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/Map.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.Set; 19 | 20 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 21 | 22 | import net.anyflow.lannister.serialization.MapSerializer; 23 | 24 | @JsonSerialize(using = MapSerializer.class) 25 | public interface Map { 26 | void put(K key, V value); 27 | 28 | V get(K key); 29 | 30 | V remove(K key); 31 | 32 | Set keySet(); 33 | 34 | void dispose(); 35 | 36 | int size(); 37 | 38 | boolean containsKey(K key); 39 | } 40 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/Mode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | public enum Mode { 19 | HAZELCAST("hazelcast"), 20 | IGNITE("ignite"), 21 | SINGLE("single"); 22 | 23 | private String value; 24 | 25 | private Mode(String value) { 26 | this.value = value; 27 | } 28 | 29 | public String value() { 30 | return value; 31 | } 32 | 33 | public static Mode from(String value) { 34 | for (Mode item : values()) { 35 | if (item.value().equals(value)) { return item; } 36 | } 37 | 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/NativeMap.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.cluster; 2 | 3 | import java.util.Set; 4 | 5 | import com.google.common.collect.Maps; 6 | 7 | /* 8 | * Copyright 2016 The Lannister Project 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | public class NativeMap implements Map { 23 | 24 | private java.util.Map engine; 25 | 26 | public NativeMap(String name) { 27 | engine = Maps.newConcurrentMap(); 28 | } 29 | 30 | @Override 31 | public void put(K key, V value) { 32 | engine.put(key, value); 33 | } 34 | 35 | @Override 36 | public V get(K key) { 37 | return engine.get(key); 38 | } 39 | 40 | @Override 41 | public V remove(K key) { 42 | return engine.remove(key); 43 | } 44 | 45 | @Override 46 | public Set keySet() { 47 | return engine.keySet(); 48 | } 49 | 50 | @Override 51 | public int size() { 52 | return engine.size(); 53 | } 54 | 55 | @Override 56 | public void dispose() { 57 | // DO NOTHING 58 | } 59 | 60 | @Override 61 | public boolean containsKey(K key) { 62 | return engine.containsKey(key); 63 | } 64 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/NativeSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.stream.Stream; 19 | 20 | import com.google.common.collect.Sets; 21 | 22 | public class NativeSet implements Set { 23 | private final java.util.Set engine; 24 | 25 | protected NativeSet() { 26 | engine = Sets.newHashSet(); 27 | } 28 | 29 | @Override 30 | public Stream stream() { 31 | return engine.stream(); 32 | } 33 | 34 | @Override 35 | public boolean remove(V value) { 36 | return engine.remove(value); 37 | } 38 | 39 | @Override 40 | public boolean add(V value) { 41 | return engine.add(value); 42 | } 43 | 44 | @Override 45 | public void dispose() { 46 | // DO NOTHING 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/NativeSetValueMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import com.google.common.collect.Maps; 19 | 20 | public class NativeSetValueMap implements Map> { 21 | 22 | private final java.util.Map> engine; 23 | 24 | public NativeSetValueMap(String name) { 25 | engine = Maps.newHashMap(); 26 | } 27 | 28 | @Override 29 | public void put(K key, Set value) { 30 | Set prev = engine.put(key, value); 31 | if (prev != null) { 32 | prev.dispose(); 33 | } 34 | } 35 | 36 | @Override 37 | public Set get(K key) { 38 | return engine.get(key); 39 | } 40 | 41 | @Override 42 | public Set remove(K key) { 43 | return engine.remove(key); 44 | } 45 | 46 | @Override 47 | public int size() { 48 | return engine.size(); 49 | } 50 | 51 | @Override 52 | public void dispose() { 53 | // DO NOTHING 54 | } 55 | 56 | @Override 57 | public boolean containsKey(K key) { 58 | return engine.containsKey(key); 59 | } 60 | 61 | @Override 62 | public java.util.Set keySet() { 63 | return engine.keySet(); 64 | } 65 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/SerializableIntegerSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.io.IOException; 19 | import java.util.HashSet; 20 | 21 | import com.google.common.collect.Lists; 22 | import com.hazelcast.nio.ObjectDataInput; 23 | import com.hazelcast.nio.ObjectDataOutput; 24 | import com.hazelcast.nio.serialization.IdentifiedDataSerializable; 25 | 26 | import net.anyflow.lannister.serialization.SerializableFactory; 27 | 28 | public class SerializableIntegerSet extends HashSet implements IdentifiedDataSerializable { 29 | private static final long serialVersionUID = -2853172691112908250L; 30 | public static final int ID = 10; 31 | 32 | public SerializableIntegerSet() { 33 | } 34 | 35 | public SerializableIntegerSet(Integer... items) { 36 | this(); 37 | 38 | this.addAll(Lists.newArrayList(items)); 39 | } 40 | 41 | @Override 42 | public int getFactoryId() { 43 | return SerializableFactory.ID; 44 | } 45 | 46 | @Override 47 | public int getId() { 48 | return ID; 49 | } 50 | 51 | @Override 52 | public void writeData(ObjectDataOutput out) throws IOException { 53 | out.writeInt(size()); 54 | 55 | for (Integer item : this) { 56 | out.writeInt(item); 57 | } 58 | } 59 | 60 | @Override 61 | public void readData(ObjectDataInput in) throws IOException { 62 | int size = in.readInt(); 63 | 64 | for (int i = 0; i < size; ++i) { 65 | this.add(in.readInt()); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/SerializableStringSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.io.IOException; 19 | import java.util.HashSet; 20 | 21 | import com.google.common.collect.Lists; 22 | import com.hazelcast.nio.ObjectDataInput; 23 | import com.hazelcast.nio.ObjectDataOutput; 24 | import com.hazelcast.nio.serialization.IdentifiedDataSerializable; 25 | 26 | import net.anyflow.lannister.serialization.SerializableFactory; 27 | 28 | public class SerializableStringSet extends HashSet implements IdentifiedDataSerializable { 29 | private static final long serialVersionUID = 8628682087610501290L; 30 | public static final int ID = 9; 31 | 32 | public SerializableStringSet() { 33 | } 34 | 35 | public SerializableStringSet(String... items) { 36 | this(); 37 | 38 | this.addAll(Lists.newArrayList(items)); 39 | } 40 | 41 | @Override 42 | public int getFactoryId() { 43 | return SerializableFactory.ID; 44 | } 45 | 46 | @Override 47 | public int getId() { 48 | return ID; 49 | } 50 | 51 | @Override 52 | public void writeData(ObjectDataOutput out) throws IOException { 53 | out.writeInt(size()); 54 | 55 | for (String item : this) { 56 | out.writeUTF(item); 57 | } 58 | } 59 | 60 | @Override 61 | public void readData(ObjectDataInput in) throws IOException { 62 | int size = in.readInt(); 63 | 64 | for (int i = 0; i < size; ++i) { 65 | this.add(in.readUTF()); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/Set.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.stream.Stream; 19 | 20 | public interface Set { 21 | Stream stream(); 22 | 23 | boolean remove(V value); 24 | 25 | boolean add(V value); 26 | 27 | void dispose(); 28 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/SingleIdGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import com.hazelcast.core.IdGenerator; 19 | 20 | public class SingleIdGenerator implements IdGenerator { 21 | 22 | private final String name; 23 | private long id; 24 | 25 | public SingleIdGenerator(String name) { 26 | this.name = name; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | @Override 35 | public void destroy() { 36 | // DO NOTHING 37 | } 38 | 39 | @Override 40 | public boolean init(long id) { 41 | if (id < 0) { return false; } 42 | 43 | this.id = id; 44 | return true; 45 | } 46 | 47 | @Override 48 | public long newId() { 49 | return ++id; 50 | } 51 | 52 | @Override 53 | public String getPartitionKey() { 54 | throw new Error("The method should not be called"); 55 | } 56 | 57 | @Override 58 | public String getServiceName() { 59 | throw new Error("The method should not be called"); 60 | } 61 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/cluster/SingleTopic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.cluster; 17 | 18 | import java.util.Date; 19 | import java.util.Map; 20 | import java.util.UUID; 21 | 22 | import com.google.common.collect.Maps; 23 | import com.hazelcast.core.ITopic; 24 | import com.hazelcast.core.Message; 25 | import com.hazelcast.core.MessageListener; 26 | import com.hazelcast.monitor.LocalTopicStats; 27 | 28 | import io.netty.util.concurrent.GlobalEventExecutor; 29 | 30 | public class SingleTopic implements ITopic { 31 | 32 | private final String name; 33 | private final Map> messageListeners; 34 | 35 | public SingleTopic(String name) { 36 | this.name = name; 37 | this.messageListeners = Maps.newConcurrentMap(); 38 | } 39 | 40 | @Override 41 | public void destroy() { 42 | // DO NOTHING 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | @Override 51 | public void publish(E message) { 52 | final Date now = new Date(); 53 | 54 | GlobalEventExecutor.INSTANCE.execute(() -> { 55 | Message msg = new Message(name, message, now.getTime(), null); 56 | messageListeners.values().forEach(c -> c.onMessage(msg)); 57 | }); 58 | } 59 | 60 | @Override 61 | public String addMessageListener(MessageListener listener) { 62 | UUID ret = UUID.randomUUID(); 63 | 64 | messageListeners.put(ret.toString(), listener); 65 | 66 | return ret.toString(); 67 | } 68 | 69 | @Override 70 | public boolean removeMessageListener(String registrationId) { 71 | return messageListeners.remove(registrationId) != null; 72 | } 73 | 74 | @Override 75 | public String getPartitionKey() { 76 | throw new Error("The method should not be called"); 77 | } 78 | 79 | @Override 80 | public String getServiceName() { 81 | throw new Error("The method should not be called"); 82 | } 83 | 84 | @Override 85 | public LocalTopicStats getLocalTopicStats() { 86 | throw new Error("The method should not be called"); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/HtmlGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.UnsupportedEncodingException; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.w3c.tidy.Tidy; 28 | 29 | import io.netty.handler.codec.http.HttpResponseStatus; 30 | 31 | public class HtmlGenerator { 32 | 33 | private static final Logger logger = LoggerFactory.getLogger(HtmlGenerator.class); 34 | 35 | private static String html_error; 36 | 37 | static { 38 | html_error = tidy(Thread.currentThread().getContextClassLoader().getResourceAsStream("html/error.htm")); 39 | } 40 | 41 | public static String generate(Map values, String htmlPath) throws IOException { 42 | return replace(values, tidy(Thread.currentThread().getContextClassLoader().getResourceAsStream(htmlPath))); 43 | } 44 | 45 | private static String replace(Map values, String htmlTemplate) { 46 | String openMarker = "${"; 47 | String closeMarker = "}"; 48 | 49 | String ret = htmlTemplate; 50 | 51 | for (Map.Entry item : values.entrySet()) { 52 | ret = ret.replace(openMarker + item.getKey() + closeMarker, item.getValue()); 53 | } 54 | 55 | return ret; 56 | } 57 | 58 | public static String error(String message, HttpResponseStatus status) { 59 | HashMap values = new HashMap(); 60 | 61 | values.put("ERROR_CODE", status.toString()); 62 | values.put("message", message); 63 | 64 | return replace(values, html_error); 65 | } 66 | 67 | private static String tidy(InputStream is) { 68 | Tidy tidy = new Tidy(); 69 | 70 | tidy.setQuiet(true); 71 | tidy.setDocType("loose"); 72 | tidy.setTidyMark(false); 73 | tidy.setOutputEncoding("UTF8"); 74 | 75 | java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); 76 | tidy.parse(is, out); 77 | 78 | try { 79 | return out.toString("UTF-8"); 80 | } 81 | catch (UnsupportedEncodingException e) { 82 | 83 | logger.error(e.getMessage(), e); 84 | return null; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/HttpClientHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import io.netty.channel.ChannelHandlerContext; 23 | import io.netty.channel.SimpleChannelInboundHandler; 24 | import io.netty.handler.codec.http.FullHttpResponse; 25 | 26 | public class HttpClientHandler extends SimpleChannelInboundHandler { 27 | 28 | private static final Logger logger = LoggerFactory.getLogger(HttpClientHandler.class); 29 | 30 | private final MessageReceiver receiver; 31 | private final HttpRequest request; 32 | private HttpResponse response; 33 | 34 | public HttpClientHandler(MessageReceiver receiver, HttpRequest request) { 35 | this.receiver = receiver; 36 | this.request = request; 37 | } 38 | 39 | public HttpResponse httpResponse() { 40 | return response; 41 | } 42 | 43 | @Override 44 | protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception { 45 | if (!ctx.channel().isActive()) { return; } 46 | 47 | response = HttpResponse.createFrom(msg, ctx.channel()); 48 | 49 | if (logger.isDebugEnabled()) { 50 | logger.debug(response.toString()); 51 | } 52 | 53 | if (receiver != null) { 54 | receiver.messageReceived(request, response); 55 | } 56 | 57 | ctx.channel().close(); 58 | } 59 | 60 | @Override 61 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 62 | logger.error(cause.getMessage(), cause); 63 | ctx.channel().close(); 64 | } 65 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/HttpConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | public class HttpConstants { 20 | 21 | public static final String MESSAGE_404_NOT_FOUND = "404 NOT FOUND"; 22 | public static final String FAILED_TO_FIND_REQUEST_HANDLER = "Failed to find the request handler."; 23 | 24 | public static final class HeaderValues { 25 | public static final String APPLICATION_JSON = "application/json"; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/IHttpClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | import io.netty.channel.ChannelOption; 20 | 21 | public interface IHttpClient { 22 | HttpRequest httpRequest(); 23 | 24 | HttpResponse get(); 25 | 26 | HttpResponse get(MessageReceiver receiver); 27 | 28 | HttpResponse post(); 29 | 30 | HttpResponse post(MessageReceiver receiver); 31 | 32 | HttpResponse put(); 33 | 34 | HttpResponse put(MessageReceiver receiver); 35 | 36 | HttpResponse delete(); 37 | 38 | HttpResponse delete(MessageReceiver receiver); 39 | 40 | IHttpClient setOption(ChannelOption option, T value); 41 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/MessageReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | public interface MessageReceiver { 20 | void messageReceived(HttpRequest request, HttpResponse response); 21 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/WebServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import io.netty.bootstrap.ServerBootstrap; 23 | import io.netty.channel.EventLoopGroup; 24 | import io.netty.channel.ServerChannel; 25 | import io.netty.channel.epoll.EpollServerSocketChannel; 26 | import io.netty.channel.socket.nio.NioServerSocketChannel; 27 | import net.anyflow.lannister.Literals; 28 | import net.anyflow.lannister.Settings; 29 | 30 | public class WebServer { 31 | private static final Logger logger = LoggerFactory.getLogger(WebServer.class); 32 | 33 | private final EventLoopGroup bossGroup; 34 | private final EventLoopGroup workerGroup; 35 | 36 | public WebServer(EventLoopGroup bossGroup, EventLoopGroup workerGroup) { 37 | this.bossGroup = bossGroup; 38 | this.workerGroup = workerGroup; 39 | } 40 | 41 | public EventLoopGroup bossGroup() { 42 | return bossGroup; 43 | } 44 | 45 | public EventLoopGroup workerGroup() { 46 | return workerGroup; 47 | } 48 | 49 | public void start(String requestHandlerPakcageRoot) throws Exception { 50 | start(requestHandlerPakcageRoot, null); 51 | } 52 | 53 | public void start(String requestHandlerPakcageRoot, 54 | final Class websocketFrameHandlerClass) throws Exception { 55 | HttpRequestHandler.setRequestHandlerPakcageRoot(requestHandlerPakcageRoot); 56 | 57 | Class serverChannelClass; 58 | 59 | if (Literals.NETTY_EPOLL.equals(Settings.INSTANCE.nettyTransportMode())) { 60 | serverChannelClass = EpollServerSocketChannel.class; 61 | } 62 | else { 63 | serverChannelClass = NioServerSocketChannel.class; 64 | } 65 | 66 | if (Settings.INSTANCE.httpPort() != null) { 67 | ServerBootstrap bootstrap = new ServerBootstrap(); 68 | 69 | bootstrap.group(bossGroup, workerGroup).channel(serverChannelClass) 70 | .childHandler(new WebServerChannelInitializer(false, websocketFrameHandlerClass)); 71 | 72 | bootstrap.bind(Settings.INSTANCE.httpPort()).sync(); 73 | } 74 | 75 | if (Settings.INSTANCE.httpsPort() != null) { 76 | ServerBootstrap bootstrap = new ServerBootstrap(); 77 | 78 | bootstrap.group(bossGroup, workerGroup).channel(serverChannelClass) 79 | .childHandler(new WebServerChannelInitializer(true, websocketFrameHandlerClass)); 80 | 81 | bootstrap.bind(Settings.INSTANCE.httpsPort()).sync(); 82 | } 83 | 84 | logger.info("Lannister HTTP server started [http.port={}, https.port={}]", Settings.INSTANCE.httpPort(), 85 | Settings.INSTANCE.httpsPort()); 86 | } 87 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/http/WebsocketFrameHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.http; 18 | 19 | import java.util.List; 20 | 21 | import io.netty.channel.ChannelHandlerContext; 22 | import io.netty.handler.codec.MessageToMessageDecoder; 23 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 24 | 25 | public abstract class WebsocketFrameHandler extends MessageToMessageDecoder { 26 | public static final List DEFAULT_SUBPROTOCOLS = null; 27 | public static final boolean ALLOW_EXTENSIONS = false; 28 | public static final int MAX_FRAME_SIZE = 65536; 29 | 30 | public abstract String subprotocols(); 31 | 32 | public abstract String websocketPath(); 33 | 34 | public abstract boolean allowExtensions(); 35 | 36 | public abstract int maxFrameSize(); 37 | 38 | public abstract void websocketFrameReceived(ChannelHandlerContext ctx, WebSocketFrame wsframe); 39 | 40 | @Override 41 | protected void decode(ChannelHandlerContext ctx, WebSocketFrame msg, List out) throws Exception { 42 | websocketFrameReceived(ctx, msg); 43 | } 44 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/Index.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler; 18 | 19 | import net.anyflow.lannister.http.HttpRequestHandler; 20 | 21 | @HttpRequestHandler.Handles(paths = { "/", "/index", }, httpMethods = { "GET" }, webResourcePath = "index.html") 22 | public class Index extends HttpRequestHandler { 23 | @SuppressWarnings("unused") 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Index.class); 25 | 26 | @Override 27 | public String service() { 28 | return null; 29 | } 30 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/admin/Index.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.admin; 18 | 19 | import net.anyflow.lannister.http.HttpRequestHandler; 20 | 21 | @HttpRequestHandler.Handles(paths = { "/admin", "/admin/index", "/admin/dashboard", "/admin/messages", "/admin/clients", 22 | "/admin/broker", "/admin/credential", "/admin/websocket_tester", 23 | "/admin/about" }, httpMethods = { "GET" }, webResourcePath = "admin/index.html") 24 | public class Index extends HttpRequestHandler { 25 | @SuppressWarnings("unused") 26 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Index.class); 27 | 28 | @Override 29 | public String service() { 30 | return null; 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/Clients.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import com.hazelcast.core.IdGenerator; 20 | 21 | import net.anyflow.lannister.cluster.ClusterDataFactory; 22 | import net.anyflow.lannister.http.HttpRequestHandler; 23 | import net.anyflow.lannister.session.Session; 24 | 25 | @HttpRequestHandler.Handles(paths = { "api/clients" }, httpMethods = { "POST" }) 26 | public class Clients extends HttpRequestHandler { 27 | @SuppressWarnings("unused") 28 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Clients.class); 29 | 30 | @Override 31 | public String service() { 32 | IdGenerator idgen = ClusterDataFactory.INSTANCE.createIdGenerator("CLIENT_ID_GENERATOR"); 33 | 34 | String clientId = null; 35 | while (clientId == null) { 36 | clientId = String.format("laniClientId%011d", idgen.newId()); 37 | 38 | if (Session.NEXUS.get(clientId) != null) { 39 | clientId = null; 40 | } 41 | } 42 | 43 | return String.format("{\"id\":\"%s\"}", clientId); 44 | } 45 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/InboundMessageStatuses.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.message.InboundMessageStatus; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/inboundMessageStatuses" }, httpMethods = { "GET" }) 30 | public class InboundMessageStatuses extends HttpRequestHandler { 31 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(InboundMessageStatuses.class); 32 | 33 | @Override 34 | public String service() { 35 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 36 | 37 | switch (filter) { 38 | case "": 39 | case "all": 40 | return all(); 41 | 42 | default: 43 | return null; 44 | } 45 | } 46 | 47 | private String all() { 48 | try { 49 | return new ObjectMapper().writeValueAsString(InboundMessageStatus.NEXUS.keySet().stream() 50 | .map(key -> InboundMessageStatus.NEXUS.get(key)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/MessageReferenceCounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import com.fasterxml.jackson.core.JsonProcessingException; 20 | import com.fasterxml.jackson.databind.ObjectMapper; 21 | import com.google.common.base.Strings; 22 | 23 | import io.netty.handler.codec.http.HttpResponseStatus; 24 | import net.anyflow.lannister.http.HttpRequestHandler; 25 | 26 | @HttpRequestHandler.Handles(paths = { "api/messageReferenceCounts" }, httpMethods = { "GET" }) 27 | public class MessageReferenceCounts extends HttpRequestHandler { 28 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MessageReferenceCounts.class); 29 | 30 | @Override 31 | public String service() { 32 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 33 | 34 | switch (filter) { 35 | case "": 36 | case "all": 37 | return all(); 38 | 39 | default: 40 | return null; 41 | } 42 | } 43 | 44 | private String all() { 45 | try { 46 | return new ObjectMapper() 47 | .writeValueAsString(net.anyflow.lannister.message.MessageReferenceCounts.INSTANCE.data()); 48 | } 49 | catch (JsonProcessingException e) { 50 | logger.error(e.getMessage(), e); 51 | 52 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 53 | return null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/Messages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.message.Message; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/messages" }, httpMethods = { "GET" }) 30 | public class Messages extends HttpRequestHandler { 31 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Messages.class); 32 | 33 | @Override 34 | public String service() { 35 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 36 | 37 | switch (filter) { 38 | case "": 39 | case "all": 40 | return all(); 41 | 42 | default: 43 | return null; 44 | } 45 | } 46 | 47 | private String all() { 48 | try { 49 | return new ObjectMapper().writeValueAsString( 50 | Message.NEXUS.keySet().stream().map(key -> Message.NEXUS.get(key)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/OutboundMessageStatuses.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.message.OutboundMessageStatus; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/outboundMessageStatuses" }, httpMethods = { "GET" }) 30 | public class OutboundMessageStatuses extends HttpRequestHandler { 31 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(OutboundMessageStatuses.class); 32 | 33 | @Override 34 | public String service() { 35 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 36 | 37 | switch (filter) { 38 | case "": 39 | case "all": 40 | return all(); 41 | 42 | default: 43 | return null; 44 | } 45 | } 46 | 47 | private String all() { 48 | try { 49 | return new ObjectMapper().writeValueAsString(OutboundMessageStatus.NEXUS.keySet().stream() 50 | .map(key -> OutboundMessageStatus.NEXUS.get(key)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/Sessions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.session.Session; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/sessions" }, httpMethods = { "GET" }) 30 | public class Sessions extends HttpRequestHandler { 31 | 32 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Sessions.class); 33 | 34 | private String liveString() { 35 | try { 36 | return new ObjectMapper().writeValueAsString(Session.NEXUS.keySet().stream() 37 | .map(c -> Session.NEXUS.get(c)).filter(s -> s.isConnected(false)).collect(Collectors.toList())); 38 | } 39 | catch (JsonProcessingException e) { 40 | logger.error(e.getMessage(), e); 41 | 42 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 43 | return null; 44 | } 45 | } 46 | 47 | private String allString() { 48 | try { 49 | return new ObjectMapper().writeValueAsString( 50 | Session.NEXUS.keySet().stream().map(c -> Session.NEXUS.get(c)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | 60 | @Override 61 | public String service() { 62 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 63 | 64 | switch (filter) { 65 | case "": 66 | case "live": 67 | return liveString(); 68 | 69 | case "all": 70 | return allString(); 71 | 72 | default: 73 | return null; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/Statistics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import com.fasterxml.jackson.core.JsonProcessingException; 20 | import com.fasterxml.jackson.databind.ObjectMapper; 21 | import com.fasterxml.jackson.databind.SerializationFeature; 22 | 23 | import io.netty.handler.codec.http.HttpResponseStatus; 24 | import net.anyflow.lannister.http.HttpRequestHandler; 25 | 26 | @HttpRequestHandler.Handles(paths = { "api/statistics" }, httpMethods = { "GET" }) 27 | public class Statistics extends HttpRequestHandler { 28 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Statistics.class); 29 | 30 | @Override 31 | public String service() { 32 | 33 | try { 34 | return new ObjectMapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) 35 | .writeValueAsString(net.anyflow.lannister.Statistics.INSTANCE.data()); 36 | } 37 | catch (JsonProcessingException e) { 38 | logger.error(e.getMessage(), e); 39 | 40 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 41 | return null; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/TopicSubscribers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.topic.TopicSubscriber; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/topicSubscribers" }, httpMethods = { "GET" }) 30 | public class TopicSubscribers extends HttpRequestHandler { 31 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscribers.class); 32 | 33 | @Override 34 | public String service() { 35 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 36 | 37 | switch (filter) { 38 | case "": 39 | case "all": 40 | return all(); 41 | 42 | default: 43 | return null; 44 | } 45 | } 46 | 47 | private String all() { 48 | try { 49 | return new ObjectMapper().writeValueAsString(TopicSubscriber.NEXUS.keySet().stream() 50 | .map(key -> TopicSubscriber.NEXUS.get(key)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/TopicSubscriptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.topic.TopicSubscription; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/topicSubscriptions" }, httpMethods = { "GET" }) 30 | public class TopicSubscriptions extends HttpRequestHandler { 31 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscriptions.class); 32 | 33 | @Override 34 | public String service() { 35 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 36 | 37 | switch (filter) { 38 | case "": 39 | case "all": 40 | return all(); 41 | 42 | default: 43 | return null; 44 | } 45 | } 46 | 47 | private String all() { 48 | try { 49 | return new ObjectMapper().writeValueAsString(TopicSubscription.NEXUS.keySet().stream() 50 | .map(key -> TopicSubscription.NEXUS.get(key)).collect(Collectors.toList())); 51 | } 52 | catch (JsonProcessingException e) { 53 | logger.error(e.getMessage(), e); 54 | 55 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/httphandler/api/Topics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import java.util.stream.Collectors; 20 | 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.google.common.base.Strings; 24 | 25 | import io.netty.handler.codec.http.HttpResponseStatus; 26 | import net.anyflow.lannister.http.HttpRequestHandler; 27 | import net.anyflow.lannister.topic.Topic; 28 | 29 | @HttpRequestHandler.Handles(paths = { "api/topics" }, httpMethods = { "GET" }) 30 | public class Topics extends HttpRequestHandler { 31 | 32 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Topics.class); 33 | 34 | @Override 35 | public String service() { 36 | String filter = Strings.nullToEmpty(httpRequest().parameter("filter")); 37 | 38 | switch (filter) { 39 | case "": 40 | case "all": 41 | return all(); 42 | case "nosys": 43 | return nosys(); 44 | 45 | default: 46 | return null; 47 | } 48 | } 49 | 50 | private String all() { 51 | try { 52 | return new ObjectMapper().writeValueAsString( 53 | Topic.NEXUS.keySet().stream().map(key -> Topic.NEXUS.get(key)).collect(Collectors.toList())); 54 | } 55 | catch (JsonProcessingException e) { 56 | logger.error(e.getMessage(), e); 57 | 58 | this.httpResponse().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); 59 | return null; 60 | } 61 | } 62 | 63 | private String nosys() { 64 | try { 65 | return new ObjectMapper() 66 | .writeValueAsString(Topic.NEXUS.keySet().stream().filter(topicName -> !topicName.startsWith("$SYS")) 67 | .map(key -> Topic.NEXUS.get(key)).collect(Collectors.toList())); 68 | } 69 | catch (JsonProcessingException e) { 70 | logger.error(e.getMessage(), e); 71 | return null; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/message/ConnectOptions.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.message; 2 | 3 | import io.netty.handler.codec.mqtt.MqttVersion; 4 | 5 | public class ConnectOptions { 6 | private MqttVersion version; 7 | private String clientId; 8 | private String userName; 9 | private String password; 10 | private boolean cleanSession; 11 | private Message will; 12 | private int keepAliveTimeSeconds; 13 | 14 | public ConnectOptions() { 15 | this.version = MqttVersion.MQTT_3_1_1; 16 | this.clientId = null; 17 | this.cleanSession = true; 18 | this.will = null; 19 | this.userName = null; 20 | this.password = null; 21 | this.keepAliveTimeSeconds = 120; 22 | } 23 | 24 | public ConnectOptions(MqttVersion version, String clientId, boolean cleanSession, Message will, String userName, 25 | String password, int keepAliveTimeSeconds) { 26 | this.version = version; 27 | this.clientId = clientId; 28 | this.cleanSession = cleanSession; 29 | this.will = will; 30 | this.userName = userName; 31 | this.password = password; 32 | this.keepAliveTimeSeconds = keepAliveTimeSeconds; 33 | } 34 | 35 | public MqttVersion version() { 36 | return version; 37 | } 38 | 39 | public void version(MqttVersion version) { 40 | this.version = version; 41 | } 42 | 43 | public String clientId() { 44 | return clientId; 45 | } 46 | 47 | public void clientId(String clientId) { 48 | this.clientId = clientId; 49 | } 50 | 51 | public String userName() { 52 | return userName; 53 | } 54 | 55 | public void userName(String userName) { 56 | this.userName = userName; 57 | } 58 | 59 | public String password() { 60 | return password; 61 | } 62 | 63 | public void password(String password) { 64 | this.password = password; 65 | } 66 | 67 | public boolean cleanSession() { 68 | return cleanSession; 69 | } 70 | 71 | public void cleanSession(boolean cleanSession) { 72 | this.cleanSession = cleanSession; 73 | } 74 | 75 | public Message will() { 76 | return will; 77 | } 78 | 79 | public void will(Message will) { 80 | this.will = will; 81 | } 82 | 83 | public int keepAliveTimeSeconds() { 84 | return keepAliveTimeSeconds; 85 | } 86 | 87 | public void keepAliveTimeSeconds(int keepAliveTimeSeconds) { 88 | this.keepAliveTimeSeconds = keepAliveTimeSeconds; 89 | } 90 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/message/InboundMessageStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.message; 18 | 19 | import java.io.IOException; 20 | import java.util.Date; 21 | 22 | import com.fasterxml.jackson.annotation.JsonIgnore; 23 | import com.fasterxml.jackson.annotation.JsonProperty; 24 | import com.hazelcast.nio.ObjectDataInput; 25 | import com.hazelcast.nio.ObjectDataOutput; 26 | 27 | import net.anyflow.lannister.serialization.SerializableFactory; 28 | 29 | public class InboundMessageStatus extends MessageStatus { 30 | public static final InboundMessageStatuses NEXUS = new InboundMessageStatuses(); 31 | public static final int ID = 2; 32 | 33 | @JsonProperty 34 | private Status status; 35 | 36 | public InboundMessageStatus() { // just for Serialization 37 | } 38 | 39 | public InboundMessageStatus(String messageKey, String clientId, int messageId, String topicName, Status status) { 40 | super(messageKey, clientId, messageId, topicName); 41 | 42 | this.status = status; 43 | } 44 | 45 | @Override 46 | public String key() { 47 | return InboundMessageStatuses.key(messageId(), clientId()); 48 | } 49 | 50 | public Status status() { 51 | return status; 52 | } 53 | 54 | public void status(Status status) { 55 | this.status = status; 56 | super.updateTime = new Date(); 57 | } 58 | 59 | @JsonIgnore 60 | @Override 61 | public int getFactoryId() { 62 | return SerializableFactory.ID; 63 | } 64 | 65 | @JsonIgnore 66 | @Override 67 | public int getId() { 68 | return ID; 69 | } 70 | 71 | @Override 72 | public void writeData(ObjectDataOutput out) throws IOException { 73 | super.writeData(out); 74 | 75 | out.writeByte(status != null ? status.value() : Byte.MIN_VALUE); 76 | } 77 | 78 | @Override 79 | public void readData(ObjectDataInput in) throws IOException { 80 | super.readData(in); 81 | 82 | byte rawByte = in.readByte(); 83 | status = rawByte != Byte.MIN_VALUE ? Status.valueOf(rawByte) : null; 84 | } 85 | 86 | public enum Status { 87 | RECEIVED((byte) 0), 88 | PUBRECED((byte) 1); 89 | 90 | private byte value; 91 | 92 | private Status(byte value) { 93 | this.value = value; 94 | } 95 | 96 | public byte value() { 97 | return value; 98 | } 99 | 100 | public static Status valueOf(byte value) { 101 | for (Status q : values()) { 102 | if (q.value == value) { return q; } 103 | } 104 | throw new IllegalArgumentException("Invalid ReceiverTargetStatus: " + value); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/message/MessageReferenceCounts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.message; 17 | 18 | import com.google.common.collect.Maps; 19 | 20 | import net.anyflow.lannister.cluster.ClusterDataFactory; 21 | import net.anyflow.lannister.cluster.Map; 22 | 23 | public class MessageReferenceCounts { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MessageReferenceCounts.class); 25 | 26 | public static final MessageReferenceCounts INSTANCE = new MessageReferenceCounts(); 27 | 28 | private final Map data; // key : message.key() 29 | 30 | private MessageReferenceCounts() { 31 | this.data = ClusterDataFactory.INSTANCE.createMap("MessagesReferenceCounts_data"); 32 | } 33 | 34 | public java.util.Map data() { 35 | java.util.Map ret = Maps.newHashMap(); 36 | data.keySet().stream().forEach(k -> ret.put(k, data.get(k))); 37 | 38 | return ret; 39 | } 40 | 41 | public void retain(String messageKey) { 42 | Integer count = data.get(messageKey); 43 | if (count == null) { 44 | count = 0; 45 | } 46 | 47 | data.put(messageKey, ++count); 48 | logger.debug("RETAINed message reference [count={}, messageKey={}]", count, messageKey); 49 | } 50 | 51 | public void release(String messageKey) { 52 | Integer count = data.get(messageKey); 53 | if (count == null) { return; } 54 | 55 | if (count <= 0) { 56 | logger.error("Invalid Message reference Found![key={}, count={}]", messageKey, count); 57 | return; 58 | } 59 | else if (count == 1) { 60 | data.remove(messageKey); 61 | logger.debug("REMOVEed Message reference [key={}]", messageKey); 62 | 63 | Message.NEXUS.remove(messageKey); 64 | } 65 | else { 66 | data.put(messageKey, --count); 67 | logger.debug("RELEASEed Message reference [key={}, count={}]", messageKey, count); 68 | } 69 | } 70 | 71 | public int size() { 72 | return data.size(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/message/Messages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package net.anyflow.lannister.message; 17 | 18 | import java.util.Set; 19 | 20 | import com.google.common.collect.Sets; 21 | 22 | import net.anyflow.lannister.cluster.ClusterDataFactory; 23 | import net.anyflow.lannister.cluster.Map; 24 | import net.anyflow.lannister.message.InboundMessageStatus.Status; 25 | 26 | public class Messages { 27 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Messages.class); 28 | 29 | private final Map data; 30 | 31 | protected Messages() { 32 | data = ClusterDataFactory.INSTANCE.createMap("Messages_data"); 33 | } 34 | 35 | public static String key(String publisherId, Integer messageId) { 36 | return publisherId + "_" + Integer.toString(messageId); 37 | } 38 | 39 | public int size() { 40 | return data.size(); 41 | } 42 | 43 | public void dispose() { 44 | data.dispose(); 45 | } 46 | 47 | public Message remove(String key) { 48 | Message ret = data.remove(key); 49 | if (ret == null) { return null; } 50 | 51 | if (logger.isDebugEnabled()) { 52 | logger.debug("REMOVEed Message [messageId={}, publisherId={}, topicName=]", ret.id(), ret.publisherId(), 53 | ret.topicName()); 54 | logger.debug("Messages size={}", data.size()); 55 | } 56 | 57 | return ret; 58 | } 59 | 60 | public Set keySet() { 61 | return Sets.newHashSet(data.keySet()); 62 | } 63 | 64 | public Message get(String key) { 65 | return data.get(key); 66 | } 67 | 68 | public void put(String key, Message message) { 69 | data.put(key, message); 70 | 71 | InboundMessageStatus.NEXUS.put(new InboundMessageStatus(message.key(), message.publisherId(), message.id(), 72 | message.topicName(), Status.RECEIVED)); 73 | 74 | if (logger.isDebugEnabled()) { 75 | logger.debug("ADDed Message [messageId={}, publisherId={}, topicName=]", message.id(), 76 | message.publisherId(), message.topicName()); 77 | logger.debug("Messages size={}", data.size()); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/packetreceiver/DisconnectReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.packetreceiver; 18 | 19 | import io.netty.channel.ChannelHandler.Sharable; 20 | import io.netty.channel.ChannelHandlerContext; 21 | import net.anyflow.lannister.session.Session; 22 | 23 | @Sharable 24 | public class DisconnectReceiver { 25 | @SuppressWarnings("unused") 26 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DisconnectReceiver.class); 27 | public static final DisconnectReceiver INSTANCE = new DisconnectReceiver(); 28 | 29 | public static final DisconnectReceiver SHARED = new DisconnectReceiver(); 30 | 31 | private DisconnectReceiver() { 32 | } 33 | 34 | protected void handle(ChannelHandlerContext ctx, Session session) { 35 | session.will(null); // [MQTT-3.1.2-8],[MQTT-3.1.2-10] 36 | session.dispose(false); // [MQTT-3.14.4-1],[MQTT-3.14.4-2],[MQTT-3.14.4-3] 37 | } 38 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/packetreceiver/PingReqReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.packetreceiver; 18 | 19 | import io.netty.channel.ChannelHandlerContext; 20 | import net.anyflow.lannister.session.Session; 21 | 22 | public class PingReqReceiver { 23 | @SuppressWarnings("unused") 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(PingReqReceiver.class); 25 | 26 | public static final PingReqReceiver SHARED = new PingReqReceiver(); 27 | 28 | private PingReqReceiver() { 29 | } 30 | 31 | protected void handle(ChannelHandlerContext ctx, Session session) { 32 | session.send(MqttMessageFactory.pingresp(), null); // [MQTT-3.12.4-1] 33 | } 34 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/packetreceiver/PubCompReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.packetreceiver; 18 | 19 | import io.netty.channel.ChannelHandlerContext; 20 | import net.anyflow.lannister.message.OutboundMessageStatus; 21 | import net.anyflow.lannister.session.Session; 22 | 23 | public class PubCompReceiver { 24 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(PubCompReceiver.class); 25 | 26 | public static final PubCompReceiver SHARED = new PubCompReceiver(); 27 | 28 | private PubCompReceiver() { 29 | } 30 | 31 | protected void handle(ChannelHandlerContext ctx, Session session, int messageId) { 32 | OutboundMessageStatus status = OutboundMessageStatus.NEXUS.removeByKey(messageId, session.clientId()); 33 | if (status == null) { 34 | logger.error("PUBCOMP target does not exist [clientId={}, messageId={}]", session.clientId(), messageId); 35 | session.dispose(true); // [MQTT-3.3.5-2] 36 | return; 37 | } 38 | 39 | logger.debug("Outbound message status REMOVED [clientId={}, messageId={}]", session.clientId(), messageId); 40 | } 41 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/packetreceiver/PubRecReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.packetreceiver; 18 | 19 | import io.netty.channel.ChannelHandlerContext; 20 | import net.anyflow.lannister.message.OutboundMessageStatus; 21 | import net.anyflow.lannister.plugin.DeliveredEventArgs; 22 | import net.anyflow.lannister.plugin.DeliveredEventListener; 23 | import net.anyflow.lannister.plugin.Plugins; 24 | import net.anyflow.lannister.session.Session; 25 | 26 | public class PubRecReceiver { 27 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(PubRecReceiver.class); 28 | 29 | public static final PubRecReceiver SHARED = new PubRecReceiver(); 30 | 31 | private PubRecReceiver() { 32 | } 33 | 34 | protected void handle(ChannelHandlerContext ctx, Session session, int messageId) { 35 | OutboundMessageStatus status = OutboundMessageStatus.NEXUS.getBy(messageId, session.clientId()); 36 | if (status == null || status.status() == OutboundMessageStatus.Status.TO_PUBLISH) { 37 | logger.error("PUBREC target does not exist or Invalid status [clientId={}, messageId={}]", 38 | session.clientId(), messageId); 39 | session.dispose(true); // [MQTT-3.3.5-2] 40 | return; 41 | } 42 | 43 | if (status.status() == OutboundMessageStatus.Status.PUBLISHED) { 44 | ctx.channel().eventLoop().execute(() -> { 45 | Plugins.INSTANCE.get(DeliveredEventListener.class).delivered(new DeliveredEventArgs() { 46 | @Override 47 | public String clientId() { 48 | return session.clientId(); 49 | } 50 | 51 | @Override 52 | public int messageId() { 53 | return messageId; 54 | } 55 | }); 56 | }); 57 | } 58 | 59 | OutboundMessageStatus.NEXUS.update(messageId, session.clientId(), OutboundMessageStatus.Status.PUBRECED); 60 | 61 | session.send(MqttMessageFactory.pubrel(messageId), null); 62 | } 63 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/packetreceiver/PubRelReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.packetreceiver; 18 | 19 | import io.netty.channel.ChannelHandlerContext; 20 | import io.netty.handler.codec.mqtt.MqttMessage; 21 | import net.anyflow.lannister.message.InboundMessageStatus; 22 | import net.anyflow.lannister.session.Session; 23 | import net.anyflow.lannister.topic.Topic; 24 | import net.anyflow.lannister.topic.Topics.ClientType; 25 | 26 | public class PubRelReceiver { 27 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(PubRelReceiver.class); 28 | 29 | public static final PubRelReceiver SHARED = new PubRelReceiver(); 30 | 31 | private PubRelReceiver() { 32 | } 33 | 34 | protected void handle(ChannelHandlerContext ctx, Session session, int messageId) { 35 | 36 | // TODO what if the PUBREL is resented one? 37 | 38 | Topic topic = Topic.NEXUS.get(session.clientId(), messageId, ClientType.PUBLISHER); 39 | if (topic == null) { 40 | logger.error("PUBREL target does not exist [clientId={}, messageId={}]", session.clientId(), messageId); 41 | session.dispose(true); // [MQTT-3.3.5-2] 42 | return; 43 | } 44 | 45 | MqttMessage toSend = MqttMessageFactory.pubcomp(messageId); 46 | final String log = toSend.toString(); 47 | 48 | session.send(toSend, f -> { 49 | if (!f.isSuccess()) { 50 | logger.error("packet outgoing failed [{}] {}", log, f.cause()); 51 | return; 52 | } 53 | 54 | InboundMessageStatus.NEXUS.removeByKey(messageId, session.clientId()); 55 | logger.debug("Inbound message status REMOVED [clientId={}, messageId={}]", session.clientId(), messageId); 56 | }); 57 | } 58 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultAuthenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultAuthenticator implements Authenticator { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DefaultAuthenticator.class); 21 | 22 | @Override 23 | public Plugin clone() { 24 | return new DefaultAuthenticator(); 25 | } 26 | 27 | @Override 28 | public boolean isValid(String clientId) { 29 | if (logger.isDebugEnabled()) { 30 | logger.debug("DefaultAuthenticator.isValid() called [clientId={}]", clientId); 31 | } 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean isValid(String clientId, String userName, String password) { 38 | if (logger.isDebugEnabled()) { 39 | logger.debug("DefaultAuthenticator.isValid() called [clientId={}, userName={}, password={}]", clientId, 40 | userName, password); 41 | } 42 | return true; 43 | } 44 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultAuthorizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultAuthorizer implements Authorizer { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DefaultAuthorizer.class); 21 | 22 | @Override 23 | public Plugin clone() { 24 | return new DefaultAuthorizer(); 25 | } 26 | 27 | @Override 28 | public boolean isAuthorized(String clientId, String userName) { 29 | logger.debug("DefaultAuthorizer.isAuthorized() called [clientId={}, userName={}]", clientId, userName); 30 | return true; 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultConnectEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultConnectEventListener implements ConnectEventListener { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DefaultConnectEventListener.class); 21 | 22 | @Override 23 | public Plugin clone() { 24 | return this; 25 | } 26 | 27 | @Override 28 | public void connectHandled(ConnectEventArgs args) { 29 | logger.debug("DefaultConnectEventListener.connectHandled() called [{}]", args.log()); 30 | } 31 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultDeliveredEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultDeliveredEventListener implements DeliveredEventListener { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 21 | .getLogger(DefaultDeliveredEventListener.class); 22 | 23 | @Override 24 | public Plugin clone() { 25 | return this; 26 | } 27 | 28 | @Override 29 | public void delivered(DeliveredEventArgs args) { 30 | logger.debug("DefaultDeliveredEventListener.delivered() called [{}]", args.log()); 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultDisconnectEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultDisconnectEventListener implements DisconnectEventListener { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 21 | .getLogger(DefaultDisconnectEventListener.class); 22 | 23 | @Override 24 | public Plugin clone() { 25 | return this; 26 | } 27 | 28 | @Override 29 | public void disconnected(DisconnectEventArgs args) { 30 | logger.debug("DefaultDisconnectEventListener.disconnected() called [{}]", args.log()); 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultPublishEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultPublishEventListener implements PublishEventListener { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DefaultPublishEventListener.class); 21 | 22 | @Override 23 | public Plugin clone() { 24 | return this; 25 | } 26 | 27 | @Override 28 | public boolean allowPublish(PublishEventArgs args) { 29 | logger.debug("DefaultPublishEventListener.allowPublish() called [{}]", args.log()); 30 | return true; 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultServiceChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultServiceChecker implements ServiceChecker { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DefaultServiceChecker.class); 21 | 22 | @Override 23 | public Plugin clone() { 24 | return new DefaultServiceChecker(); 25 | } 26 | 27 | @Override 28 | public boolean isServiceAvailable() { 29 | logger.debug("DefaultServiceChecker.isServiceAvailable() called"); 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultSubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultSubscribeEventListener implements SubscribeEventListener { 20 | @SuppressWarnings("unused") 21 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 22 | .getLogger(DefaultSubscribeEventListener.class); 23 | 24 | public static final DefaultSubscribeEventListener SHARED = new DefaultSubscribeEventListener(); 25 | 26 | @Override 27 | public Plugin clone() { 28 | return this; 29 | } 30 | 31 | @Override 32 | public boolean allowSubscribe(SubscribeEventArgs args) { 33 | return args.cleanSession() 34 | || args.topicSubscriptions().stream().filter(ts -> ts.topicFilter().startsWith("$SYS")).count() <= 0; 35 | } 36 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/plugin/DefaultUnsubscribeEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.plugin; 18 | 19 | public class DefaultUnsubscribeEventListener implements UnsubscribeEventListener { 20 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory 21 | .getLogger(DefaultUnsubscribeEventListener.class); 22 | 23 | @Override 24 | public Plugin clone() { 25 | return this; 26 | } 27 | 28 | @Override 29 | public void unsubscribed(UnsubscribeEventArgs args) { 30 | logger.debug("DefaultUnsubscribeEventListener.unsubscribed() called [{}]", args.log()); 31 | } 32 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/ChannelIdSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import java.io.IOException; 20 | 21 | import com.fasterxml.jackson.core.JsonGenerator; 22 | import com.fasterxml.jackson.core.JsonProcessingException; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | 25 | import io.netty.channel.ChannelId; 26 | 27 | public final class ChannelIdSerializer extends com.fasterxml.jackson.databind.JsonSerializer { 28 | 29 | @Override 30 | public void serialize(ChannelId value, JsonGenerator generator, SerializerProvider provider) 31 | throws IOException, JsonProcessingException { 32 | 33 | generator.writeString(value.toString()); 34 | } 35 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/HazelcastSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Luca Burgazzoli 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import java.util.function.Supplier; 20 | 21 | import com.hazelcast.nio.serialization.Serializer; 22 | 23 | public class HazelcastSerializer implements Serializer, Supplier { 24 | protected final Class type; 25 | protected final int typeId; 26 | protected final ThreadLocal threadLocal; 27 | 28 | protected HazelcastSerializer(final Class type, int typeId) { 29 | this(type, typeId, null); 30 | } 31 | 32 | protected HazelcastSerializer(final Class type, int typeId, Supplier supplier) { 33 | this.type = type; 34 | this.typeId = typeId; 35 | this.threadLocal = supplier != null ? ThreadLocal.withInitial(supplier) : null; 36 | } 37 | 38 | @Override 39 | public int getTypeId() { 40 | return typeId; 41 | } 42 | 43 | @Override 44 | public void destroy() { 45 | // Did nothing in original Source(escape from code inspection error) 46 | } 47 | 48 | public Class getType() { 49 | return this.type; 50 | } 51 | 52 | @Override 53 | public S get() { 54 | return threadLocal.get(); 55 | } 56 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/JsonSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Luca Burgazzoli 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import java.io.IOException; 20 | 21 | import com.fasterxml.jackson.core.JsonFactory; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.fasterxml.jackson.dataformat.smile.SmileFactory; 24 | import com.hazelcast.nio.ObjectDataInput; 25 | import com.hazelcast.nio.ObjectDataOutput; 26 | import com.hazelcast.nio.serialization.Serializer; 27 | import com.hazelcast.nio.serialization.StreamSerializer; 28 | 29 | public final class JsonSerializer extends HazelcastSerializer implements StreamSerializer { 30 | public static final int TYPEID_JSON_PLAIN = 100; 31 | public static final int TYPEID_JSON_BINARY = 101; 32 | 33 | private JsonSerializer(Class type, int typeId) { 34 | this(type, typeId, null); 35 | } 36 | 37 | private JsonSerializer(Class type, int typeId, final JsonFactory factory) { 38 | super(type, typeId, () -> new ObjectMapper(factory)); 39 | } 40 | 41 | @Override 42 | public void write(ObjectDataOutput out, T object) throws IOException { 43 | out.writeByteArray(get().writeValueAsBytes(object)); 44 | } 45 | 46 | @Override 47 | public T read(ObjectDataInput in) throws IOException { 48 | return get().readValue(in.readByteArray(), getType()); 49 | } 50 | 51 | public static Serializer makeBinary(final Class type) { 52 | return new JsonSerializer<>(type, TYPEID_JSON_BINARY, new SmileFactory()); 53 | } 54 | 55 | public static Serializer makePlain(final Class type) { 56 | return new JsonSerializer<>(type, TYPEID_JSON_PLAIN); 57 | } 58 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/MapSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import java.io.IOException; 20 | import java.util.stream.Collectors; 21 | 22 | import com.fasterxml.jackson.core.JsonGenerator; 23 | import com.fasterxml.jackson.core.JsonProcessingException; 24 | import com.fasterxml.jackson.databind.SerializerProvider; 25 | 26 | import net.anyflow.lannister.cluster.Map; 27 | 28 | public final class MapSerializer extends com.fasterxml.jackson.databind.JsonSerializer> { 29 | @Override 30 | public void serialize(Map value, JsonGenerator gen, SerializerProvider serializers) 31 | throws IOException, JsonProcessingException { 32 | gen.writeObject(value.keySet().stream().map(key -> value.get(key)).collect(Collectors.toList())); 33 | } 34 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/SerializableFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import com.hazelcast.nio.serialization.DataSerializableFactory; 20 | import com.hazelcast.nio.serialization.IdentifiedDataSerializable; 21 | 22 | import net.anyflow.lannister.cluster.SerializableIntegerSet; 23 | import net.anyflow.lannister.cluster.SerializableStringSet; 24 | import net.anyflow.lannister.message.InboundMessageStatus; 25 | import net.anyflow.lannister.message.Message; 26 | import net.anyflow.lannister.message.OutboundMessageStatus; 27 | import net.anyflow.lannister.session.Session; 28 | import net.anyflow.lannister.topic.Notification; 29 | import net.anyflow.lannister.topic.Topic; 30 | import net.anyflow.lannister.topic.TopicSubscriber; 31 | import net.anyflow.lannister.topic.TopicSubscription; 32 | 33 | public class SerializableFactory implements DataSerializableFactory { 34 | public static final int ID = 1; 35 | 36 | @Override 37 | public IdentifiedDataSerializable create(int classId) { 38 | switch (classId) { 39 | case Message.ID: 40 | return new Message(); 41 | 42 | case InboundMessageStatus.ID: 43 | return new InboundMessageStatus(); 44 | 45 | case OutboundMessageStatus.ID: 46 | return new OutboundMessageStatus(); 47 | 48 | case Session.ID: 49 | return new Session(); 50 | 51 | case Notification.ID: 52 | return new Notification(); 53 | 54 | case Topic.ID: 55 | return new Topic(); 56 | 57 | case TopicSubscriber.ID: 58 | return new TopicSubscriber(); 59 | 60 | case TopicSubscription.ID: 61 | return new TopicSubscription(); 62 | 63 | case SerializableStringSet.ID: 64 | return new SerializableStringSet(); 65 | 66 | case SerializableIntegerSet.ID: 67 | return new SerializableIntegerSet(); 68 | 69 | default: 70 | throw new Error("Invalid class ID of Hazelcast Serialization [ID=" + classId + "]"); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/serialization/SysValueSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.serialization; 18 | 19 | import java.io.IOException; 20 | 21 | import com.fasterxml.jackson.core.JsonGenerator; 22 | import com.fasterxml.jackson.core.JsonProcessingException; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | 25 | import net.anyflow.lannister.Statistics.SysValue; 26 | 27 | public final class SysValueSerializer extends com.fasterxml.jackson.databind.JsonSerializer { 28 | @Override 29 | public void serialize(SysValue value, JsonGenerator generator, SerializerProvider provider) 30 | throws IOException, JsonProcessingException { 31 | 32 | generator.writeString(value.value()); 33 | } 34 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/server/ByteCounterCodec.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.server; 2 | 3 | import java.util.List; 4 | 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageCodec; 8 | import net.anyflow.lannister.Statistics; 9 | import net.anyflow.lannister.Statistics.Criterion; 10 | 11 | public class ByteCounterCodec extends MessageToMessageCodec { 12 | @SuppressWarnings("unused") 13 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ByteCounterCodec.class); 14 | 15 | @Override 16 | protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { 17 | Statistics.INSTANCE.add(Criterion.BYTE_SENT, msg.retain().readableBytes()); 18 | Statistics.INSTANCE.add(Criterion.MESSAGES_SENT, 1); 19 | 20 | out.add(msg); 21 | } 22 | 23 | @Override 24 | protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { 25 | Statistics.INSTANCE.add(Criterion.BYTE_RECEIVED, msg.retain().readableBytes()); 26 | Statistics.INSTANCE.add(Criterion.MESSAGES_RECEIVED, 1); 27 | 28 | out.add(msg); 29 | } 30 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/server/MqttWebSocketCodec.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.server; 2 | 3 | import java.util.List; 4 | 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageCodec; 8 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 9 | 10 | public class MqttWebSocketCodec extends MessageToMessageCodec { 11 | @Override 12 | protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception { 13 | out.add(new BinaryWebSocketFrame(msg.retain())); 14 | } 15 | 16 | @Override 17 | protected void decode(ChannelHandlerContext ctx, BinaryWebSocketFrame msg, List out) throws Exception { 18 | out.add(msg.retain().content()); 19 | } 20 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/topic/Notification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.topic; 18 | 19 | import java.io.IOException; 20 | 21 | import com.fasterxml.jackson.annotation.JsonIgnore; 22 | import com.hazelcast.nio.ObjectDataInput; 23 | import com.hazelcast.nio.ObjectDataOutput; 24 | 25 | import net.anyflow.lannister.message.Message; 26 | import net.anyflow.lannister.serialization.SerializableFactory; 27 | 28 | public class Notification implements com.hazelcast.nio.serialization.IdentifiedDataSerializable { 29 | public final static int ID = 5; 30 | 31 | private String clientId; 32 | private Topic topic; 33 | private Message message; 34 | 35 | public Notification() { // just for Serialization 36 | } 37 | 38 | protected Notification(String clientId, Topic topic, Message message) { 39 | this.clientId = clientId; 40 | this.topic = topic; 41 | this.message = message; 42 | } 43 | 44 | public String clientId() { 45 | return clientId; 46 | } 47 | 48 | public Topic topic() { 49 | return topic; 50 | } 51 | 52 | public Message message() { 53 | return message; 54 | } 55 | 56 | @JsonIgnore 57 | @Override 58 | public int getFactoryId() { 59 | return SerializableFactory.ID; 60 | } 61 | 62 | @Override 63 | public int getId() { 64 | return ID; 65 | } 66 | 67 | @Override 68 | public void writeData(ObjectDataOutput out) throws IOException { 69 | out.writeUTF(clientId); 70 | out.writeBoolean(topic != null); 71 | if (topic != null) { 72 | topic.writeData(out); 73 | } 74 | out.writeBoolean(message != null); 75 | if (message != null) { 76 | message.writeData(out); 77 | } 78 | } 79 | 80 | @Override 81 | public void readData(ObjectDataInput in) throws IOException { 82 | clientId = in.readUTF(); 83 | if (in.readBoolean()) { 84 | Topic temp = new Topic(); 85 | temp.readData(in); 86 | 87 | topic = temp; 88 | } 89 | if (in.readBoolean()) { 90 | Message temp = new Message(); 91 | temp.readData(in); 92 | 93 | message = temp; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /server/src/main/java/net/anyflow/lannister/topic/TopicSubscriber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.topic; 18 | 19 | import java.io.IOException; 20 | 21 | import com.fasterxml.jackson.annotation.JsonIgnore; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import com.hazelcast.nio.ObjectDataInput; 24 | import com.hazelcast.nio.ObjectDataOutput; 25 | 26 | import net.anyflow.lannister.serialization.SerializableFactory; 27 | 28 | public class TopicSubscriber implements com.hazelcast.nio.serialization.IdentifiedDataSerializable { 29 | public static final TopicSubscribers NEXUS = new TopicSubscribers(); 30 | public static final int ID = 7; 31 | @JsonProperty 32 | private String clientId; 33 | @JsonProperty 34 | private String topicName; 35 | 36 | public TopicSubscriber() { // just for Serialization 37 | } 38 | 39 | public TopicSubscriber(String clientId, String topicName) { 40 | this.clientId = clientId; 41 | this.topicName = topicName; 42 | } 43 | 44 | public String key() { 45 | return TopicSubscribers.key(topicName, clientId); 46 | } 47 | 48 | public String clientId() { 49 | return clientId; 50 | } 51 | 52 | public String topicName() { 53 | return topicName; 54 | } 55 | 56 | @JsonIgnore 57 | @Override 58 | public int getFactoryId() { 59 | return SerializableFactory.ID; 60 | } 61 | 62 | @JsonIgnore 63 | @Override 64 | public int getId() { 65 | return ID; 66 | } 67 | 68 | @Override 69 | public void writeData(ObjectDataOutput out) throws IOException { 70 | out.writeUTF(topicName); 71 | out.writeUTF(clientId); 72 | } 73 | 74 | @Override 75 | public void readData(ObjectDataInput in) throws IOException { 76 | topicName = in.readUTF(); 77 | clientId = in.readUTF(); 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return new StringBuilder().append("clientId=").append(clientId).append(", topicName=").append(topicName) 83 | .toString(); 84 | } 85 | } -------------------------------------------------------------------------------- /server/src/main/resources/lannister.cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 20 | 21 | LANNISTER 22 | LANNISTER_HAZELCAST_GROUP_PASSWORD 23 | 24 | 25 | 26 | slf4j 27 | false 28 | 15 29 | true 30 | 5000 31 | 30000 32 | 15 33 | 34 | 35 | 36 | ${hazelcast.port} 37 | 38 | 39 | ${hazelcast.multicast-group} 40 | ${hazelcast.multicast-port} 41 | 42 | 43 | ${hazelcast.member1} 44 | ${hazelcast.member2} 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /server/src/main/resources/lannister.log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /server/src/main/resources/lannister.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 The Lannister Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | netty.logger=false 18 | netty.nativeTransportMode=true 19 | 20 | netty.bossThreadCount=2 21 | netty.workerThreadCount=0 22 | 23 | #X.509 certificate chain file in PEM format 24 | lannister.ssl.certChainFilePath=self 25 | #X.509 private key file in PEM format 26 | lannister.ssl.privateKeyFilePath=self 27 | 28 | #single, hazelcast, ignite 29 | clustering.mode=${clustering.mode} 30 | 31 | ##################################### lannister mqttserver 32 | 33 | #If empty, the channel will not be established. 34 | mqttserver.tcp.port=1883 35 | #If empty, the channel will not be established. 36 | mqttserver.tcp.ssl.port=8883 37 | #If empty, the channel will not be established. 38 | mqttserver.websocket.port=9001 39 | #If empty, the channel will not be established. 40 | mqttserver.websocket.ssl.port=9002 41 | 42 | mqttserver.websocket.path=/mqtt 43 | 44 | mqttserver.sessionExpirationHandlerExecutionIntervalSeconds=5 45 | 46 | mqttserver.responseTimeoutSeconds=5 47 | 48 | #default value is 8092 49 | mqttserver.maxBytesInMessage= 50 | 51 | mqttserver.acceptEmptyClientId=true 52 | 53 | mqttserver.sys.intervalSeconds=2 54 | 55 | #topic filters cannot be subscribed(comma seperation) 56 | mqttserver.subscribe.banned_topicfilters=nosubscribe,filters_cannot_be_subscribed/# 57 | 58 | 59 | ###################################### lannister.mqttclient 60 | mqttclient.responseTimeoutSeconds=15 61 | 62 | 63 | ##################################### lannister webserver 64 | 65 | #If empty, the channel will not be established. 66 | webserver.http.port=8090 67 | #If empty, the channel will not be established. 68 | webserver.https.port=8493 69 | 70 | webserver.contextRoot=/ 71 | webserver.allowCrossDomain=true 72 | webserver.MIME={"html":"text/html","htm":"text/html","css":"text/css","js":"text/javascript","gif":"image/gif","png":"image/png","jpg":"image/jpg","bmp":"bmp/image/bmp","ttf":"application/x-font-ttf","eot":"application/vnd.ms-fontobject","woff":"application/font-woff","woff2":"application/font-woff2","svg":"image/svg+xml"} 73 | webserver.webResourcePhysicalRootPath=${project.basedir}/src/main/webapp 74 | 75 | webserver.logging.writelogOfNettyLogger=false 76 | webserver.logging.writeHttpRequest=true 77 | webserver.logging.writeHttpResponse=true 78 | webserver.logging.httpResponseContentSize=-1 79 | webserver.logging.logWebResourceHttpResponseContent=false 80 | -------------------------------------------------------------------------------- /server/src/main/resources/shutdown.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 The Lannister Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | #!/bin/sh 18 | 19 | echo "Lannister shutdown started" 20 | 21 | cd "$(dirname "$0")" 22 | 23 | echo 'current directory :' 24 | pwd 25 | 26 | LOG_FILE="${log.path}/output.log" 27 | TAIL_PID=0 28 | if [ -f "$LOG_FILE" ]; 29 | then 30 | tail -f -n0 $LOG_FILE & 31 | TAIL_PID=$! 32 | fi 33 | 34 | processor=${project.build.finalName} 35 | 36 | for i in {0..5} 37 | do 38 | PID=`ps -ef | grep $processor | grep -v grep | awk '{print $2}'` 39 | echo 'PID='$PID 40 | 41 | if [ ${#PID} -gt 0 ]; then 42 | if [ $i -gt 5 ]; then 43 | kill -9 $PID 44 | echo $processor " killing..." 45 | else 46 | kill -15 $PID 47 | echo $processor " shutdowning..." 48 | fi 49 | sleep 5 50 | else 51 | break 52 | fi 53 | done 54 | 55 | if [ $TAIL_PID -gt 0 ]; then 56 | kill -9 $TAIL_PID 57 | fi 58 | 59 | echo "Lannister shutdown completed" 60 | -------------------------------------------------------------------------------- /server/src/main/resources/startup.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 The Lannister Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | #!/bin/sh 18 | 19 | echo 'Boostrapping Lannister started' 20 | 21 | cd "$(dirname "$0")" 22 | 23 | echo 'current directory :' 24 | pwd 25 | 26 | echo 'Prepare log directory & file...' 27 | LOG_DIRECTORY="${log.path}" 28 | if [ -d "$LOG_DIRECTORY" ]; 29 | then 30 | echo $LOG_DIRECTORY' found' 31 | else 32 | mkdir $LOG_DIRECTORY 33 | echo $LOG_DIRECTORY' created' 34 | fi 35 | 36 | LOG_FILE=$LOG_DIRECTORY"/output.log" 37 | if [ -f "$LOG_FILE" ]; 38 | then 39 | echo $LOG_FILE' found' 40 | else 41 | touch $LOG_FILE 42 | echo $LOG_FILE' created' 43 | fi 44 | 45 | tail -f -n0 $LOG_FILE & 46 | TAIL_PID=$! 47 | 48 | echo 'Execute Lannister execution file...' 49 | EXECUTE_FILE='./../lib/${project.build.finalName}.jar' 50 | 51 | nohup java -Dname=${project.build.finalName} ${project.build.startOption} -jar $EXECUTE_FILE >/dev/null 2>&1 & 52 | 53 | sleep 10 54 | 55 | echo "Bootstrapping finished." 56 | 57 | kill -9 $TAIL_PID 58 | 59 | exit 0 60 | -------------------------------------------------------------------------------- /server/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Lannister admin index 10 | 11 | 12 | 13 | Welcome to Lannister(under construction)! 14 | 15 | 16 | -------------------------------------------------------------------------------- /server/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lannister 4 | 5 | 6 | org.apache.maven.skins 7 | maven-fluido-skin 8 | 1.5 9 | 10 | 11 | 12 | true 13 | true 14 | 15 | anyflow/lannister 16 | right 17 | darkblue 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/NettyUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister; 18 | 19 | import org.hamcrest.Matchers; 20 | import org.junit.Assert; 21 | import org.junit.BeforeClass; 22 | import org.junit.Test; 23 | 24 | import io.netty.buffer.ByteBuf; 25 | import io.netty.buffer.Unpooled; 26 | import io.netty.util.CharsetUtil; 27 | 28 | public class NettyUtilTest { 29 | 30 | @BeforeClass 31 | public static void setUpBeforeClass() throws Exception { 32 | Application.configureLog4j(); 33 | } 34 | 35 | @Test 36 | public void testCopy() throws Exception { 37 | String original = "TestString"; 38 | 39 | ByteBuf nettyBuf = Unpooled.copiedBuffer(original, CharsetUtil.UTF_8); 40 | 41 | byte[] byteArray = NettyUtil.copy(nettyBuf); 42 | 43 | String copied = new String(byteArray); 44 | 45 | Assert.assertThat(original, Matchers.equalTo(copied)); 46 | } 47 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/TestSuite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister; 18 | 19 | import org.junit.AfterClass; 20 | import org.junit.BeforeClass; 21 | import org.junit.runner.RunWith; 22 | import org.junit.runners.Suite; 23 | import org.junit.runners.Suite.SuiteClasses; 24 | 25 | import net.anyflow.lannister.httphandler.IndexTest; 26 | import net.anyflow.lannister.httphandler.api.ClientsTest; 27 | import net.anyflow.lannister.httphandler.api.SessionsTest; 28 | import net.anyflow.lannister.httphandler.api.TopicsTest; 29 | import net.anyflow.lannister.packetreceiver.ConnectReceiverTest; 30 | import net.anyflow.lannister.server.MqttServerTest; 31 | import net.anyflow.lannister.server.SessionExpiratorTest; 32 | import net.anyflow.lannister.session.SessionTest; 33 | import net.anyflow.lannister.session.WillTest; 34 | import net.anyflow.lannister.topic.TopicMatcherTest; 35 | import net.anyflow.lannister.topic.TopicTest; 36 | 37 | @RunWith(Suite.class) 38 | @SuiteClasses({ NettyUtilTest.class, IndexTest.class, SessionsTest.class, ConnectReceiverTest.class, 39 | TopicMatcherTest.class, TopicsTest.class, MqttServerTest.class, TopicTest.class, SessionTest.class, 40 | ClientsTest.class, WillTest.class, SessionExpiratorTest.class }) 41 | public class TestSuite { 42 | 43 | private static boolean SETUP_CALLED = false; 44 | 45 | @BeforeClass 46 | public static void setUp() { 47 | if (SETUP_CALLED) { return; } 48 | 49 | Application.main(null); 50 | SETUP_CALLED = true; 51 | } 52 | 53 | @AfterClass 54 | public static void tearDown() { 55 | Application.INSTANCE.shutdown(); 56 | } 57 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/TestUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister; 18 | 19 | import io.netty.channel.ChannelId; 20 | import net.anyflow.lannister.cluster.ClusterDataFactory; 21 | 22 | public class TestUtil { 23 | 24 | private static int clientIdNo = 0; 25 | 26 | public static String newClientId() { 27 | String clientIdPrefix = "testClientId"; 28 | 29 | synchronized (clientIdPrefix) { 30 | return clientIdPrefix + Integer.toString(clientIdNo++); 31 | } 32 | } 33 | 34 | static public ChannelId newChannelId(String clientId, boolean newChannelId) { 35 | return new ChannelId() { 36 | private static final long serialVersionUID = 3931333967922160660L; 37 | 38 | Long idPostfix = ClusterDataFactory.INSTANCE.createIdGenerator("unittest_embeddedchannel").newId(); 39 | 40 | @Override 41 | public int compareTo(ChannelId o) { 42 | return this.asLongText().equals(o.asLongText()) ? 0 : 1; 43 | } 44 | 45 | @Override 46 | public String asShortText() { 47 | return asLongText(); 48 | } 49 | 50 | @Override 51 | public String asLongText() { 52 | if (newChannelId) { 53 | return clientId + idPostfix.toString(); 54 | } 55 | else { 56 | return clientId; 57 | } 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | if (newChannelId) { 63 | return (clientId + idPostfix.toString()).hashCode(); 64 | } 65 | else { 66 | return clientId.hashCode(); 67 | } 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return asLongText(); 73 | } 74 | }; 75 | } 76 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/httphandler/IndexTest.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.httphandler; 2 | 3 | import org.junit.Assert; 4 | import org.junit.BeforeClass; 5 | import org.junit.Test; 6 | 7 | import io.netty.handler.codec.http.HttpResponseStatus; 8 | import io.netty.util.CharsetUtil; 9 | import net.anyflow.lannister.Settings; 10 | import net.anyflow.lannister.TestSuite; 11 | import net.anyflow.lannister.http.HttpClient; 12 | import net.anyflow.lannister.http.HttpResponse; 13 | 14 | public class IndexTest { 15 | 16 | @BeforeClass 17 | public static void setUpBeforeClass() throws Exception { 18 | TestSuite.setUp(); 19 | } 20 | 21 | @Test 22 | public void testService() throws Exception { 23 | HttpClient client = new HttpClient("http://localhost:" + Settings.INSTANCE.httpPort() + "/index"); 24 | HttpResponse res = client.get(); 25 | 26 | Assert.assertEquals(HttpResponseStatus.OK, res.status()); 27 | Assert.assertTrue(res.content().toString(CharsetUtil.UTF_8).length() > 0); 28 | } 29 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/httphandler/api/ClientsTest.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.httphandler.api; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import com.google.common.base.Strings; 7 | import com.jayway.jsonpath.JsonPath; 8 | 9 | import io.netty.handler.codec.http.HttpResponseStatus; 10 | import io.netty.util.CharsetUtil; 11 | import net.anyflow.lannister.http.HttpClient; 12 | import net.anyflow.lannister.http.HttpResponse; 13 | 14 | public class ClientsTest { 15 | @Test 16 | public void testClients() throws Exception { 17 | HttpClient client = new HttpClient("http://localhost:8090/api/clients"); 18 | HttpResponse res = client.post(); 19 | 20 | Assert.assertEquals(HttpResponseStatus.OK, res.status()); 21 | Assert.assertFalse(Strings.isNullOrEmpty(JsonPath.read(res.content().toString(CharsetUtil.UTF_8), "$.id"))); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/httphandler/api/TopicsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.httphandler.api; 18 | 19 | import org.junit.Assert; 20 | import org.junit.BeforeClass; 21 | import org.junit.Test; 22 | 23 | import io.netty.handler.codec.http.HttpResponseStatus; 24 | import io.netty.util.CharsetUtil; 25 | import net.anyflow.lannister.TestSuite; 26 | import net.anyflow.lannister.http.HttpClient; 27 | import net.anyflow.lannister.http.HttpResponse; 28 | 29 | public class TopicsTest { 30 | 31 | @BeforeClass 32 | public static void setUpBeforeClass() throws Exception { 33 | TestSuite.setUp(); 34 | } 35 | 36 | @Test 37 | public void testAll() throws Exception { 38 | HttpClient client = new HttpClient("http://localhost:8090/api/topics?filter=all"); 39 | HttpResponse res = client.get(); 40 | 41 | Assert.assertEquals(HttpResponseStatus.OK, res.status()); 42 | Assert.assertTrue(res.content().toString(CharsetUtil.UTF_8).startsWith("[")); 43 | Assert.assertTrue(res.content().toString(CharsetUtil.UTF_8).endsWith("]")); 44 | } 45 | 46 | @Test 47 | public void testNosys() throws Exception { 48 | HttpClient client = new HttpClient("http://localhost:8090/api/topics?filter=nosys"); 49 | HttpResponse res = client.get(); 50 | 51 | Assert.assertEquals(HttpResponseStatus.OK, res.status()); 52 | Assert.assertTrue(res.content().toString(CharsetUtil.UTF_8).startsWith("[")); 53 | Assert.assertTrue(res.content().toString(CharsetUtil.UTF_8).endsWith("]")); 54 | } 55 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/server/MqttServerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.server; 18 | 19 | import org.junit.Assert; 20 | import org.junit.BeforeClass; 21 | import org.junit.Test; 22 | 23 | import io.netty.handler.codec.mqtt.MqttConnectReturnCode; 24 | import net.anyflow.lannister.Settings; 25 | import net.anyflow.lannister.TestSuite; 26 | import net.anyflow.lannister.TestUtil; 27 | import net.anyflow.lannister.client.MqttClient; 28 | import net.anyflow.lannister.message.ConnectOptions; 29 | 30 | public class MqttServerTest { 31 | @SuppressWarnings("unused") 32 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MqttServerTest.class); 33 | 34 | @BeforeClass 35 | public static void setUpBeforeClass() throws Exception { 36 | TestSuite.setUp(); 37 | } 38 | 39 | @Test 40 | public void testConnectDisconnect() throws Exception { 41 | ConnectOptions options = new ConnectOptions(); 42 | options.clientId(TestUtil.newClientId()); 43 | 44 | MqttClient client = new MqttClient("mqtt://localhost:" + Settings.INSTANCE.mqttPort()); 45 | MqttConnectReturnCode ret = client.connectOptions(options).connect(); 46 | 47 | Assert.assertEquals(MqttConnectReturnCode.CONNECTION_ACCEPTED, ret); 48 | 49 | Assert.assertTrue(client.isConnected()); 50 | 51 | client.disconnect(true); 52 | 53 | Assert.assertFalse(client.isConnected()); 54 | } 55 | 56 | @Test 57 | public void testSslConnectDisconnect() throws Exception { 58 | ConnectOptions options = new ConnectOptions(); 59 | options.clientId(TestUtil.newClientId()); 60 | 61 | MqttClient client = new MqttClient("mqtts://localhost:" + Settings.INSTANCE.mqttsPort(), true); 62 | MqttConnectReturnCode ret = client.connectOptions(options).connect(); 63 | 64 | Assert.assertEquals(MqttConnectReturnCode.CONNECTION_ACCEPTED, ret); 65 | 66 | Assert.assertTrue(client.isConnected()); 67 | 68 | client.disconnect(true); 69 | 70 | Assert.assertFalse(client.isConnected()); 71 | } 72 | } -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/server/SessionExpiratorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Lannister Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.anyflow.lannister.server; 18 | 19 | import java.util.Date; 20 | 21 | import org.junit.Assert; 22 | import org.junit.BeforeClass; 23 | import org.junit.Test; 24 | 25 | import io.netty.handler.codec.mqtt.MqttConnectReturnCode; 26 | import net.anyflow.lannister.Settings; 27 | import net.anyflow.lannister.TestSuite; 28 | import net.anyflow.lannister.TestUtil; 29 | import net.anyflow.lannister.client.MqttClient; 30 | import net.anyflow.lannister.message.ConnectOptions; 31 | import net.anyflow.lannister.session.Session; 32 | 33 | public class SessionExpiratorTest { 34 | @BeforeClass 35 | public static void setUpBeforeClass() throws Exception { 36 | TestSuite.setUp(); 37 | } 38 | 39 | @Test 40 | public void testHandlerAdded() throws Exception { 41 | String clientId = TestUtil.newClientId(); 42 | ConnectOptions options = new ConnectOptions(); 43 | options.clientId(clientId); 44 | 45 | MqttClient client = new MqttClient("mqtt://localhost:" + Settings.INSTANCE.mqttPort()); 46 | MqttConnectReturnCode ret = client.connectOptions(options).connect(); 47 | 48 | Assert.assertTrue(ret == MqttConnectReturnCode.CONNECTION_ACCEPTED); 49 | 50 | Session session = Session.NEXUS.get(clientId); 51 | 52 | Assert.assertNotNull(session); 53 | 54 | session.setLastIncomingTime(new Date(1L)); 55 | 56 | Assert.assertTrue(session.isExpired()); 57 | 58 | int expireTimeout = Settings.INSTANCE.getInt("mqttserver.sessionExpirationHandlerExecutionIntervalSeconds", 1); 59 | 60 | Thread.sleep((expireTimeout + 2) * 1000); 61 | 62 | Assert.assertNull(Session.NEXUS.get(clientId)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/session/SessionTest.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.session; 2 | 3 | import org.junit.Assert; 4 | import org.junit.BeforeClass; 5 | import org.junit.Test; 6 | 7 | import io.netty.handler.codec.mqtt.MqttQoS; 8 | import net.anyflow.lannister.TestSuite; 9 | import net.anyflow.lannister.topic.TopicSubscription; 10 | 11 | public class SessionTest { 12 | 13 | @BeforeClass 14 | public static void setUpBeforeClass() throws Exception { 15 | TestSuite.setUp(); 16 | } 17 | 18 | @Test 19 | public void testMatches() throws Exception { 20 | String testTopic = "testTopic/test"; 21 | Session session = new Session("1", "1", 1, 50, true, null); 22 | 23 | TopicSubscription ts0 = new TopicSubscription(session.clientId(), "testTopic/#", MqttQoS.AT_MOST_ONCE); 24 | TopicSubscription ts1 = new TopicSubscription(session.clientId(), "testTopic/+", MqttQoS.AT_LEAST_ONCE); 25 | TopicSubscription ts2 = new TopicSubscription(session.clientId(), testTopic, MqttQoS.EXACTLY_ONCE); 26 | 27 | TopicSubscription.NEXUS.put(ts0); 28 | TopicSubscription.NEXUS.put(ts1); 29 | TopicSubscription.NEXUS.put(ts2); 30 | 31 | Assert.assertEquals(3, TopicSubscription.NEXUS.topicFiltersOf(session.clientId()).size()); 32 | 33 | TopicSubscription target = session.matches(testTopic); 34 | 35 | Assert.assertTrue(target.topicFilter().equals(testTopic)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /server/src/test/java/net/anyflow/lannister/topic/TopicTest.java: -------------------------------------------------------------------------------- 1 | package net.anyflow.lannister.topic; 2 | 3 | import org.junit.Assert; 4 | import org.junit.BeforeClass; 5 | import org.junit.Test; 6 | 7 | import io.netty.handler.codec.mqtt.MqttQoS; 8 | import io.netty.handler.codec.mqtt.MqttTopicSubscription; 9 | import io.netty.util.CharsetUtil; 10 | import net.anyflow.lannister.Settings; 11 | import net.anyflow.lannister.TestSuite; 12 | import net.anyflow.lannister.TestUtil; 13 | import net.anyflow.lannister.client.MqttClient; 14 | import net.anyflow.lannister.message.ConnectOptions; 15 | import net.anyflow.lannister.message.Message; 16 | import net.anyflow.lannister.message.Messages; 17 | import net.anyflow.lannister.message.OutboundMessageStatus; 18 | import net.anyflow.lannister.server.MqttServerTest; 19 | import net.anyflow.lannister.session.Session; 20 | 21 | public class TopicTest { 22 | @SuppressWarnings("unused") 23 | private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MqttServerTest.class); 24 | 25 | @BeforeClass 26 | public static void setUpBeforeClass() throws Exception { 27 | TestSuite.setUp(); 28 | } 29 | 30 | @Test 31 | public void persistMessagesForDisconnectedPersistantSession() throws Exception { 32 | String clientId = TestUtil.newClientId(); 33 | 34 | ConnectOptions options = new ConnectOptions(); 35 | options.clientId(clientId); 36 | options.cleanSession(false); 37 | 38 | String topicName = "testTopic"; 39 | String message = "test message"; 40 | 41 | MqttClient client = new MqttClient("mqtt://localhost:" + Settings.INSTANCE.mqttPort()); 42 | client.connectOptions(options).connect(); 43 | 44 | client.subscribe(new MqttTopicSubscription(topicName, MqttQoS.EXACTLY_ONCE)); 45 | client.disconnect(true); 46 | 47 | Thread.sleep(100); 48 | 49 | Assert.assertNotNull(Session.NEXUS.get(clientId)); 50 | 51 | String publisherId = TestUtil.newClientId(); 52 | 53 | MqttClient publisher = new MqttClient("mqtt://localhost:" + Settings.INSTANCE.mqttPort()); 54 | 55 | ConnectOptions pubOptions = new ConnectOptions(); 56 | pubOptions.clientId(publisherId); 57 | pubOptions.cleanSession(true); 58 | 59 | int messageId = 1; 60 | publisher.connectOptions(pubOptions).connect(); 61 | publisher.publish(new Message(messageId, topicName, publisherId, message.getBytes(CharsetUtil.UTF_8), 62 | MqttQoS.EXACTLY_ONCE, false)); 63 | 64 | Thread.sleep(100); 65 | 66 | publisher.disconnect(true); 67 | 68 | Thread.sleep(1000); 69 | 70 | Assert.assertNull(Session.NEXUS.get(publisherId)); 71 | 72 | Topic topic = Topic.NEXUS.get(topicName); 73 | Assert.assertNotNull(topic); 74 | 75 | OutboundMessageStatus status = OutboundMessageStatus.NEXUS.getBy(messageId, clientId); 76 | 77 | Assert.assertNotNull(status); 78 | Assert.assertTrue(Messages.key(publisherId, messageId).equals(status.messageKey())); 79 | } 80 | } -------------------------------------------------------------------------------- /server/src/test/resources/lannister.cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 20 | 21 | LANNISTER 22 | LANNISTER_HAZELCAST_GROUP_PASSWORD 23 | 24 | 25 | 26 | slf4j 27 | false 28 | 15 29 | true 30 | 5000 31 | 30000 32 | 15 33 | 34 | 35 | 36 | ${hazelcast.port} 37 | 38 | 39 | ${hazelcast.multicast-group} 40 | ${hazelcast.multicast-port} 41 | 42 | 43 | ${hazelcast.member1} 44 | ${hazelcast.member2} 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /server/src/test/resources/lannister.log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /server/src/test/resources/lannister.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 The Lannister Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | netty.logger=false 18 | netty.nativeTransportMode=true 19 | 20 | netty.bossThreadCount=0 21 | netty.workerThreadCount=0 22 | 23 | #X.509 certificate chain file in PEM format 24 | lannister.ssl.certChainFilePath=self 25 | #X.509 private key file in PEM format 26 | lannister.ssl.privateKeyFilePath=self 27 | 28 | #single, hazelcast, ignite 29 | clustering.mode=single 30 | 31 | ##################################### lannister mqttserver 32 | 33 | #If empty, the channel will not be established. 34 | mqttserver.tcp.port=1883 35 | #If empty, the channel will not be established. 36 | mqttserver.tcp.ssl.port=8883 37 | #If empty, the channel will not be established. 38 | mqttserver.websocket.port=9001 39 | #If empty, the channel will not be established. 40 | mqttserver.websocket.ssl.port=9002 41 | 42 | mqttserver.websocket.path=/mqtt 43 | 44 | mqttserver.sessionExpirationHandlerExecutionIntervalSeconds=5 45 | 46 | mqttserver.responseTimeoutSeconds=5 47 | 48 | #default value is 8092 49 | mqttserver.maxBytesInMessage= 50 | 51 | mqttserver.acceptEmptyClientId=true 52 | 53 | mqttserver.sys.intervalSeconds=2 54 | 55 | #topic filters cannot be subscribed(comma seperation) 56 | mqttserver.subscribe.banned_topicfilters=nosubscribe,filters_cannot_be_subscribed/# 57 | 58 | 59 | ###################################### lannister.mqttclient 60 | mqttclient.responseTimeoutSeconds=15 61 | 62 | 63 | ##################################### lannister webserver 64 | 65 | #If empty, the channel will not be established. 66 | webserver.http.port=8090 67 | #If empty, the channel will not be established. 68 | webserver.https.port=8493 69 | 70 | webserver.contextRoot=/ 71 | webserver.allowCrossDomain=true 72 | webserver.MIME={"html":"text/html","htm":"text/html","css":"text/css","js":"text/javascript","gif":"image/gif","png":"image/png","jpg":"image/jpg","bmp":"bmp/image/bmp"} 73 | webserver.webResourcePhysicalRootPath=${project.basedir}/src/main/webapp 74 | 75 | webserver.logging.writelogOfNettyLogger=false 76 | webserver.logging.writeHttpRequest=true 77 | webserver.logging.writeHttpResponse=true 78 | webserver.logging.httpResponseContentSize=-1 79 | webserver.logging.logWebResourceHttpResponseContent=false -------------------------------------------------------------------------------- /src/site/markdown/clustering.md: -------------------------------------------------------------------------------- 1 | ## `[DRAFT]` Clustering 2 | 3 | Lannister's clustering features heavily rely on Hazelcast and follows its guidance strictly, hence the documentation focused on general clustering characteristics of Lannister and configuration used. For detailed information and fine tuning, refer [Hazelcast Reference Manual](http://docs.hazelcast.org/docs/3.7/manual/html-single/index.html). 4 | 5 | ### Characteristics 6 | * **Distribution Transparency** : Clustered data are fully accessible on any node in the same cluster without knowing cluster information include location. 7 | * **High Availability** : Backups are distributed on every update of Topic / Session / Message / Message Status data in a cluster. 8 | * **Data Partitioning** : Clustered data is stored in Distributed Cache, thus it minimize redundancy overhead and makes scaling out easy(compared to data replication manner). 9 | * **Single process(JVM) per node** : Logics and (clustered) data in a Lannister node are co-located in a single process(JVM), which removes additional dependency and configuration(Hazelcast Embedded Mode). 10 | * **Dynamic Joining** : Lannister nodes can be joined/unjoined dynamically, which makes scaling elastic. It also supports auto-scaling of AWS explicitly. 11 | 12 | ![characteristics diagram](images/clustering_architecture.svg) 13 | 14 | The diagram depicts characteristics described in the above section. 3 Lannister nodes works in a cluster and a MQTT client access one of the nodes. The client accesses all data in the cluster but it doesn't care where the data is in thanks to logical view. Behind the scene, the node access data to local or remote master and update backup at each access. 15 | 16 | Every nodes works in its own single process(JVM) and has no dependency on other process. 17 | 18 | (Dynamic Joining is omitted in the diagram). 19 | 20 | ### Configuration 21 | ``` 22 | 23 | LANNISTER 24 | LANNISTER_HAZELCAST_GROUP_PASSWORD 25 | 26 | 27 | 28 | slf4j 29 | false 30 | 15 31 | true 32 | 5000 33 | 30000 34 | 15 35 | 36 | 37 | 38 | ${hazelcast.port} 39 | 40 | 41 | ${hazelcast.multicast-group} 42 | ${hazelcast.multicast-port} 43 | 44 | 45 | ${hazelcast.member1} 46 | ${hazelcast.member2} 47 | 48 | 49 | 50 | ``` 51 | For more information, refer [Understanding Configuration](http://docs.hazelcast.org/docs/3.7/manual/html-single/index.html#understanding-configuration) 52 | -------------------------------------------------------------------------------- /src/site/markdown/configuration.md: -------------------------------------------------------------------------------- 1 | 16 | ## `[DRAFT]` Configuration 17 | ### SSL settings 18 | ### WebSocket settings 19 | -------------------------------------------------------------------------------- /src/site/markdown/gettingStarted.md: -------------------------------------------------------------------------------- 1 | 16 | ## Getting Started 17 | 18 | Before getting into Lannister installation, check the follows are installed in your machine. 19 | 20 | * Java 8 or later 21 | * Maven 3 (case for starting from source) 22 | 23 | ### Starting from package 24 | 1. Go to https://goo.gl/GJ1piF 25 | 2. Download a compressed file preferred (`zip` / `tar.gz` / `tar.bz2`) 26 | 3. Unpack downloaded file and move into the directory 27 | 4. Execute `./bin/startup.sh` 28 | 5. For shutdown, execute `./bin/shutdown.sh` 29 | 30 | ### Starting from source 31 | 32 | ``` 33 | # Download lannister source 34 | git clone https://github.com/anyflow/lannister.git 35 | 36 | # Change directory to lannister 37 | cd lannister 38 | 39 | # Build(The command builds all sub-projects(interface, server, plugin-example simultaneously) 40 | mvn install 41 | 42 | # Run lannister server 43 | mvn exec:java -pl server 44 | ``` 45 | -------------------------------------------------------------------------------- /src/site/markdown/plugin.md: -------------------------------------------------------------------------------- 1 | 16 | ## `[DRAFT]` Plug-In 17 | -------------------------------------------------------------------------------- /src/site/markdown/restapis.md: -------------------------------------------------------------------------------- 1 | 16 | ## `[DRAFT]` Lannister REST APIs 17 | -------------------------------------------------------------------------------- /src/site/markdown/structure.md: -------------------------------------------------------------------------------- 1 | 16 | ## `[DRAFT]` Package/Project structure 17 | 18 | Lannister package and project structure are described. 19 | 20 | ### Package structure 21 | ``` 22 | root # package root 23 | |-- bin # startup / shutdown script files 24 | |-- config # main / clustering / logging configuration files 25 | |-- lib # lannister and its dependency jar files 26 | |-- plugin # plugin-example and 3rd party plugin files 27 | |-- webapp # lannister admin web resource files 28 | |-- logs # runtime log files 29 | 30 | ``` 31 | 32 | ### Project structure 33 | Lannister has 3 sub-projects - `interface`, `server`, `plugin-example`. 34 | 35 | * [`interface`](./lannister-interface/index.html) : Source codes common to `server` and `plugin-example` 36 | * [`server`](./lannister-server/index.html) : Lannister server source codes 37 | * [`plugin-example`](./lannister-plugin-example/index.html) : Lannister plugin example source codes 38 | 39 | Lannister follows Maven standard directory layout. The diagram below shows main directories of the project. For more information about it refer [Introduction to the Standard Directory Layout](https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html). 40 | 41 | ``` 42 | root # project root 43 | |-- src 44 | | |-- site # root project documentation & config/resource files 45 | |-- target 46 | |-- interface # interface project root 47 | | |-- src 48 | | | |-- main # interface project source code & config/resource files 49 | | |-- target 50 | |-- server # server project root 51 | | |-- src 52 | | | |-- main # interface project source code & config/resource files 53 | | |-- target # 54 | 55 | ``` 56 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | Lannister 20 | 21 | 22 | org.apache.maven.skins 23 | maven-fluido-skin 24 | 1.5 25 | 26 | 27 | 28 | true 29 | true 30 | 31 | anyflow/lannister 32 | right 33 | darkblue 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | --------------------------------------------------------------------------------