├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── config ├── acl │ └── basic_policy.csv ├── config.yaml └── monitor │ └── prometheus │ ├── smqtt-application-1638608184756.json │ ├── smqtt-jvm-1638607233202.json │ └── smqtt-netty-1638607270130.json ├── icon ├── admin.png ├── application.png ├── component.png ├── icon.jpg ├── jvm.png ├── logo.png └── netty.png ├── pom.xml ├── smqtt-bootstrap ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── github │ │ │ └── quickmsg │ │ │ ├── AbstractStarter.java │ │ │ ├── docker │ │ │ └── DockerStarter.java │ │ │ ├── exception │ │ │ └── NotSupportConfigException.java │ │ │ └── jar │ │ │ └── JarStarter.java │ └── resources │ │ ├── banner.txt │ │ └── test.yaml │ └── test │ └── java │ ├── ClusterNode1.java │ ├── ClusterNode2.java │ ├── ClusterNode3.java │ └── topic │ └── TopicTest.java ├── smqtt-common ├── pom.xml ├── pom.xml.versionsBackup └── src │ └── main │ └── java │ └── io │ └── github │ └── quickmsg │ └── common │ ├── Receiver.java │ ├── StartUp.java │ ├── acl │ ├── AclAction.java │ ├── AclManager.java │ ├── AclPolicy.java │ ├── AclType.java │ ├── filter │ │ └── AclFunction.java │ └── model │ │ └── PolicyModel.java │ ├── annotation │ ├── AllowCors.java │ ├── Header.java │ ├── Headers.java │ ├── Intercept.java │ └── Router.java │ ├── auth │ ├── AuthBean.java │ └── AuthManager.java │ ├── bootstrap │ └── BootstrapKey.java │ ├── channel │ ├── ChannelRegistry.java │ ├── MockMqttChannel.java │ ├── MqttChannel.java │ └── traffic │ │ └── TrafficHandlerLoader.java │ ├── cluster │ ├── ClusterHandler.java │ ├── ClusterNode.java │ └── ClusterRegistry.java │ ├── config │ ├── AbstractConfiguration.java │ ├── AclConfig.java │ ├── AuthConfig.java │ ├── BootstrapConfig.java │ ├── ConfigCheck.java │ ├── Configuration.java │ ├── ConnectModel.java │ └── SslContext.java │ ├── context │ ├── ContextHolder.java │ └── ReceiveContext.java │ ├── enums │ ├── ChannelStatus.java │ ├── ClusterStatus.java │ ├── Event.java │ ├── HttpType.java │ └── RuleType.java │ ├── environment │ └── EnvContext.java │ ├── http │ └── HttpActor.java │ ├── interceptor │ ├── Interceptor.java │ ├── InterceptorHandler.java │ ├── Invocation.java │ └── MessageProxy.java │ ├── message │ ├── CloseMqttMessage.java │ ├── ClusterMessage.java │ ├── EventRegistry.java │ ├── HeapMqttMessage.java │ ├── HttpPublishMessage.java │ ├── JsonMap.java │ ├── MessageRegistry.java │ ├── MqttMessageBuilder.java │ ├── RetainMessage.java │ ├── SessionMessage.java │ ├── SmqttMessage.java │ ├── SubscribeChannelContext.java │ └── system │ │ └── ChannelStatusMessage.java │ ├── metric │ ├── AbstractMetricRegistry.java │ ├── CounterType.java │ ├── EventCounter.java │ ├── MeterType.java │ ├── MetricBean.java │ ├── MetricConstant.java │ ├── MetricCounter.java │ ├── MetricFactory.java │ ├── MetricManager.java │ ├── MetricManagerHolder.java │ ├── MetricRegistry.java │ ├── TotalCounter.java │ ├── WholeCounter.java │ ├── WindowCounter.java │ └── local │ │ ├── EmptyMetricCounter.java │ │ ├── LocalMetricBean.java │ │ └── LocalMetricManager.java │ ├── protocol │ ├── Protocol.java │ └── ProtocolAdaptor.java │ ├── retry │ ├── AbsAck.java │ ├── Ack.java │ ├── AckManager.java │ ├── RetryAck.java │ └── TimeAckManager.java │ ├── rule │ ├── DslExecutor.java │ ├── RuleChainDefinition.java │ ├── RuleDefinition.java │ └── source │ │ ├── Source.java │ │ ├── SourceBean.java │ │ └── SourceDefinition.java │ ├── scheduler │ └── SchedulerFactory.java │ ├── spi │ ├── AppServiceLoader.java │ ├── CacheLoader.java │ ├── DynamicLoader.java │ └── Spi.java │ ├── topic │ ├── SubscribeTopic.java │ └── TopicRegistry.java │ ├── transport │ ├── Transport.java │ ├── TransportFactory.java │ └── package-info.java │ └── utils │ ├── BannerUtils.java │ ├── ClassPathLoader.java │ ├── CsvReader.java │ ├── FileExtension.java │ ├── FormatUtils.java │ ├── IPUtils.java │ ├── JacksonUtil.java │ ├── LoggerLevel.java │ ├── MessageUtils.java │ ├── PropertiesLoader.java │ └── TopicRegexUtils.java ├── smqtt-core ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── github │ │ └── quickmsg │ │ └── core │ │ ├── Bootstrap.java │ │ ├── DefaultTransport.java │ │ ├── acl │ │ └── JCasBinAclManager.java │ │ ├── auth │ │ ├── AuthManagerFactory.java │ │ ├── FileAuthManager.java │ │ ├── FixedAuthManager.java │ │ ├── HttpAuthManager.java │ │ ├── NoneAuthManager.java │ │ └── SqlAuthManager.java │ │ ├── cluster │ │ ├── ClusterReceiver.java │ │ └── InJvmClusterRegistry.java │ │ ├── http │ │ ├── AbstractHttpActor.java │ │ ├── HttpConfiguration.java │ │ ├── HttpReceiver.java │ │ ├── HttpRouterAcceptor.java │ │ ├── HttpTransport.java │ │ ├── HttpTransportFactory.java │ │ ├── acl │ │ │ ├── AclAddPolicyActor.java │ │ │ ├── AclDeletePolicyActor.java │ │ │ └── AclQueryPolicyActor.java │ │ ├── actors │ │ │ ├── AllowCorsHttpActor.java │ │ │ ├── CloseConnectionActor.java │ │ │ ├── ClusterActor.java │ │ │ ├── ConnectionActor.java │ │ │ ├── CounterHttpActor.java │ │ │ ├── CpuHttpActor.java │ │ │ ├── EventHttpActor.java │ │ │ ├── IsClusterActor.java │ │ │ ├── JvmHttpActor.java │ │ │ ├── PrometheusActor.java │ │ │ ├── PublishActor.java │ │ │ ├── SubscribeActor.java │ │ │ ├── resource │ │ │ │ ├── FaviconResourceActor.java │ │ │ │ ├── IndexResourceActor.java │ │ │ │ ├── LoginResourceActor.java │ │ │ │ └── StaticResourceActor.java │ │ │ ├── rule │ │ │ │ ├── RuleAddActor.java │ │ │ │ ├── RuleDeleteActor.java │ │ │ │ ├── RuleQueryActor.java │ │ │ │ ├── RuleTypeActor.java │ │ │ │ └── RuleUpdateActor.java │ │ │ └── source │ │ │ │ ├── SourceAddActor.java │ │ │ │ ├── SourceDeleteActor.java │ │ │ │ ├── SourceQueryActor.java │ │ │ │ ├── SourceTypeActor.java │ │ │ │ └── SourceUpdateActor.java │ │ └── model │ │ │ ├── LoginDo.java │ │ │ ├── LoginVm.java │ │ │ └── Msg.java │ │ ├── mqtt │ │ ├── AbstractReceiveContext.java │ │ ├── MqttConfiguration.java │ │ ├── MqttReceiveContext.java │ │ ├── MqttReceiver.java │ │ ├── MqttTransportFactory.java │ │ └── traffic │ │ │ ├── CacheTrafficHandlerLoader.java │ │ │ └── LazyTrafficHandlerLoader.java │ │ ├── protocol │ │ ├── CommonProtocol.java │ │ ├── ConnectAckProtocol.java │ │ ├── ConnectProtocol.java │ │ ├── PublishAckProtocol.java │ │ ├── PublishProtocol.java │ │ ├── SubscribeAckProtocol.java │ │ ├── SubscribeProtocol.java │ │ ├── UnSubscribeAckProtocol.java │ │ └── UnSubscribeProtocol.java │ │ ├── spi │ │ ├── DefaultChannelRegistry.java │ │ ├── DefaultMessageRegistry.java │ │ ├── DefaultProtocolAdaptor.java │ │ └── DefaultTopicRegistry.java │ │ ├── ssl │ │ └── AbstractSslHandler.java │ │ ├── topic │ │ ├── FixedTopicFilter.java │ │ ├── TopicFilter.java │ │ ├── TreeNode.java │ │ ├── TreeTopicFilter.java │ │ └── WildCarTopic.java │ │ └── websocket │ │ ├── ByteBufToWebSocketFrameEncoder.java │ │ ├── WebSocketFrameToByteBufDecoder.java │ │ ├── WebSocketMqttReceiver.java │ │ └── WebSocketMqttTransportFactory.java │ └── resources │ ├── META-INF │ └── services │ │ ├── io.github.quickmsg.common.http.HttpActor │ │ └── io.github.quickmsg.common.protocol.Protocol │ └── logback.xml ├── smqtt-metric ├── pom.xml ├── smqtt-metric-influxdb │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── metric │ │ ├── InfluxDbMetricBean.java │ │ ├── InfluxDbMetricFactory.java │ │ ├── InfluxDbMetricManager.java │ │ └── InfluxDbMetricRegistry.java └── smqtt-metric-prometheus │ ├── pom.xml │ └── src │ └── main │ └── java │ └── io │ └── github │ └── quickmsg │ └── metric │ ├── PrometheusMetricBean.java │ ├── PrometheusMetricFactory.java │ ├── PrometheusMetricManager.java │ └── PrometheusMetricRegistry.java ├── smqtt-persistent ├── pom.xml ├── smqtt-persistent-db │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── io │ │ │ └── github │ │ │ └── quickmsg │ │ │ └── persistent │ │ │ ├── DbConnectionHolder.java │ │ │ ├── config │ │ │ ├── ConnectionProvider.java │ │ │ └── HikariCPConnectionProvider.java │ │ │ ├── registry │ │ │ └── DbMessageRegistry.java │ │ │ └── tables │ │ │ ├── DefaultCatalog.java │ │ │ ├── Indexes.java │ │ │ ├── Keys.java │ │ │ ├── Smqtt.java │ │ │ ├── Tables.java │ │ │ └── tables │ │ │ ├── Databasechangelog.java │ │ │ ├── Databasechangeloglock.java │ │ │ ├── SmqttRetain.java │ │ │ ├── SmqttSession.java │ │ │ └── records │ │ │ ├── DatabasechangelogRecord.java │ │ │ ├── DatabasechangeloglockRecord.java │ │ │ ├── SmqttRetainRecord.java │ │ │ └── SmqttSessionRecord.java │ │ └── resources │ │ ├── META-INF │ │ └── services │ │ │ └── io.github.quickmsg.common.message.MessageRegistry │ │ └── liquibase │ │ └── smqtt_db.xml └── smqtt-persistent-redis │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── io │ │ └── github │ │ └── quickmsg │ │ └── persistent │ │ ├── factory │ │ └── ClientFactory.java │ │ ├── message │ │ ├── RetainMessageEntity.java │ │ └── SessionMessageEntity.java │ │ ├── registry │ │ └── RedisMessageRegistry.java │ │ └── strategy │ │ ├── ClientStrategy.java │ │ ├── ClusterClientStrategy.java │ │ ├── SentinelClientStrategy.java │ │ └── SingleClientStrategy.java │ └── resources │ └── META-INF │ └── services │ └── io.github.quickmsg.common.message.MessageRegistry ├── smqtt-registry ├── pom.xml └── smqtt-registry-scube │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── io │ │ └── github │ │ └── quickmsg │ │ └── registry │ │ ├── DefaultObjectMapper.java │ │ ├── JacksonMessageCodec.java │ │ └── ScubeClusterRegistry.java │ └── resources │ ├── META-INF │ └── services │ │ ├── io.github.quickmsg.common.cluster.ClusterRegistry │ │ └── io.scalecube.cluster.transport.api.MessageCodec │ └── log4j.xml ├── smqtt-rule ├── pom.xml ├── smqtt-rule-dsl │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── dsl │ │ ├── RuleDsl.java │ │ ├── RuleDslExecutor.java │ │ └── RuleDslParser.java ├── smqtt-rule-engine │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── io │ │ │ └── github │ │ │ └── quickmsg │ │ │ └── rule │ │ │ ├── RuleChain.java │ │ │ ├── RuleExecute.java │ │ │ ├── RuleNode.java │ │ │ ├── node │ │ │ ├── DatabaseRuleNode.java │ │ │ ├── EmptyNode.java │ │ │ ├── LoggerRuleNode.java │ │ │ ├── PredicateRuleNode.java │ │ │ ├── TopicRuleNode.java │ │ │ └── TransmitRuleNode.java │ │ │ └── source │ │ │ ├── SourceFactory.java │ │ │ ├── SourceLoader.java │ │ │ └── SourceManager.java │ │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.github.quickmsg.common.rule.source.SourceBean └── smqtt-rule-source │ ├── pom.xml │ ├── smqtt-rule-source-db │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── source │ │ └── db │ │ ├── DbSourceBean.java │ │ └── config │ │ ├── ConnectionProvider.java │ │ └── HikariCPConnectionProvider.java │ ├── smqtt-rule-source-http │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── http │ │ ├── HttpParam.java │ │ └── HttpSourceBean.java │ ├── smqtt-rule-source-kafka │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── source │ │ └── mqtt │ │ └── KafkaSourceBean.java │ ├── smqtt-rule-source-mqtt │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── source │ │ └── mqtt │ │ └── MqttSourceBean.java │ ├── smqtt-rule-source-rabbitmq │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── github │ │ └── quickmsg │ │ └── source │ │ └── rabbitmq │ │ └── RabbitmqSourceBean.java │ └── smqtt-rule-source-rocketmq │ ├── pom.xml │ └── src │ └── main │ └── java │ └── io │ └── github │ └── quickmsg │ └── source │ └── rocketmq │ └── RocketmqSourceBean.java ├── smqtt-spring-boot-starter ├── pom.xml └── src │ └── main │ └── java │ └── io │ └── github │ └── quickmsg │ └── starter │ ├── AutoMqttConfiguration.java │ ├── EnableMqttServer.java │ └── SpringBootstrapConfig.java └── smqtt-ui ├── .env ├── .env.development ├── .gitignore ├── README.md ├── babel.config.js ├── mvn ├── package.json ├── pom.xml ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ └── img │ │ ├── cluster.png │ │ ├── cpu.png │ │ ├── csys.png │ │ ├── idle.png │ │ ├── iowait.png │ │ ├── jvm.png │ │ ├── logo.png │ │ ├── path.png │ │ ├── starttime.png │ │ ├── threadcount.png │ │ ├── user.png │ │ └── version.png ├── bootstrap.js ├── components │ ├── cache │ │ └── AKeepAlive.js │ ├── checkbox │ │ ├── ColorCheckbox.vue │ │ ├── ImgCheckbox.vue │ │ └── index.js │ ├── exception │ │ ├── ExceptionPage.vue │ │ └── typeConfig.js │ ├── menu │ │ ├── Contextmenu.vue │ │ ├── SideMenu.vue │ │ ├── index.less │ │ └── menu.js │ ├── page │ │ └── header │ │ │ ├── PageHeader.vue │ │ │ └── index.less │ ├── setting │ │ ├── Setting.vue │ │ ├── SettingItem.vue │ │ └── i18n.js │ ├── table │ │ ├── StandardTable.vue │ │ ├── advance │ │ │ ├── ActionColumns.vue │ │ │ ├── ActionSize.vue │ │ │ ├── AdvanceTable.vue │ │ │ ├── SearchArea.vue │ │ │ └── index.js │ │ └── api │ │ │ └── ApiTable.vue │ ├── tool │ │ └── Drawer.vue │ └── transition │ │ └── PageToggleTransition.vue ├── config │ ├── config.js │ ├── default │ │ ├── admin.config.js │ │ ├── animate.config.js │ │ ├── antd.config.js │ │ ├── index.js │ │ └── setting.config.js │ ├── index.js │ └── replacer │ │ ├── index.js │ │ └── resolve.config.js ├── layouts │ ├── AdminLayout.vue │ ├── BlankView.vue │ ├── CommonLayout.vue │ ├── PageLayout.vue │ ├── PageView.vue │ ├── footer │ │ └── PageFooter.vue │ ├── header │ │ ├── AdminHeader.vue │ │ ├── HeaderAvatar.vue │ │ ├── HeaderNotice.vue │ │ ├── HeaderSearch.vue │ │ └── index.less │ └── tabs │ │ ├── TabsHead.vue │ │ ├── TabsView.vue │ │ ├── i18n.js │ │ └── index.js ├── main.js ├── mock │ ├── common │ │ ├── activityData.js │ │ ├── index.js │ │ └── tableData.js │ ├── extend │ │ └── index.js │ ├── index.js │ └── user │ │ └── current.js ├── pages │ ├── components │ │ ├── Palette.vue │ │ ├── TaskCard.vue │ │ └── table │ │ │ ├── Api.vue │ │ │ ├── Table.vue │ │ │ └── index.js │ ├── dashboard │ │ ├── acl │ │ │ ├── Acl.vue │ │ │ └── index.js │ │ ├── clusters │ │ │ ├── Clusters.vue │ │ │ └── index.js │ │ ├── connections │ │ │ ├── Connections.vue │ │ │ └── index.js │ │ ├── console │ │ │ ├── Console.vue │ │ │ └── index.js │ │ ├── publish │ │ │ ├── Publish.vue │ │ │ └── index.js │ │ └── subscribes │ │ │ ├── Subscribes.vue │ │ │ └── index.js │ ├── exception │ │ ├── 403.vue │ │ ├── 404.vue │ │ └── 500.vue │ ├── login │ │ ├── Login.vue │ │ └── index.js │ └── rule │ │ ├── RuleEditor.vue │ │ ├── flow-data.js │ │ └── index.js ├── plugins │ ├── authority-plugin.js │ ├── i18n-extend.js │ ├── index.js │ └── tabs-page-plugin.js ├── router │ ├── async │ │ ├── config.async.js │ │ └── router.map.js │ ├── config.js │ ├── guards.js │ ├── i18n.js │ └── index.js ├── services │ ├── api.js │ ├── index.js │ ├── smqtt.js │ └── user.js ├── store │ ├── index.js │ └── modules │ │ ├── account.js │ │ ├── index.js │ │ └── setting.js ├── theme │ ├── antd │ │ ├── ant-menu.less │ │ ├── ant-message.less │ │ ├── ant-table.less │ │ ├── ant-time-picker.less │ │ └── index.less │ ├── default │ │ ├── color.less │ │ ├── index.less │ │ ├── nprogress.less │ │ └── style.less │ ├── index.less │ └── theme.less └── utils │ ├── Objects.js │ ├── authority-utils.js │ ├── axios-interceptors.js │ ├── colors.js │ ├── formatter.js │ ├── i18n.js │ ├── request.js │ ├── routerUtil.js │ ├── theme-color-replacer-extend.js │ ├── themeUtil.js │ └── util.js ├── vue.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | *.iml 4 | ./.idea/** 5 | /.idea/ 6 | target/ 7 | *.versionsBackup 8 | 9 | # Log file 10 | *.log 11 | 12 | # BlueJ files 13 | *.ctxt 14 | 15 | # Mobile Tools for Java (J2ME) 16 | .mtj.tmp/ 17 | 18 | # Package Files # 19 | *.jar 20 | *.war 21 | *.nar 22 | *.ear 23 | *.zip 24 | *.tar.gz 25 | *.rar 26 | 27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 28 | hs_err_pid* 29 | /ignite/ 30 | ./ignite/** 31 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /config/acl/basic_policy.csv: -------------------------------------------------------------------------------- 1 | p, client01, topicA, PUBLISH,allow 2 | p, client02, topicB, PUBLISH,deny 3 | p, ip{192.168.0.172/24}, topicB, PUBLISH,deny 4 | p, all, topicB, SUBSCRIBE,allow 5 | -------------------------------------------------------------------------------- /icon/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/admin.png -------------------------------------------------------------------------------- /icon/application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/application.png -------------------------------------------------------------------------------- /icon/component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/component.png -------------------------------------------------------------------------------- /icon/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/icon.jpg -------------------------------------------------------------------------------- /icon/jvm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/jvm.png -------------------------------------------------------------------------------- /icon/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/logo.png -------------------------------------------------------------------------------- /icon/netty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/icon/netty.png -------------------------------------------------------------------------------- /smqtt-bootstrap/src/main/java/io/github/quickmsg/docker/DockerStarter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.docker; 2 | 3 | import io.github.quickmsg.AbstractStarter; 4 | import io.github.quickmsg.common.utils.FileExtension; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | @Slf4j 13 | public class DockerStarter extends AbstractStarter { 14 | 15 | private final static String CONFIG_DIR_PATH = "/config"; 16 | 17 | public static void main(String[] args) { 18 | log.info("DockerStarter start args {}", String.join(",", args)); 19 | start(findConfigByPath()); 20 | } 21 | 22 | private static String findConfigByPath() { 23 | File configFile = new File(CONFIG_DIR_PATH); 24 | File[] files = configFile.listFiles(); 25 | if (files != null) { 26 | for (File file : files) { 27 | if (file.isDirectory()) { 28 | continue; 29 | } 30 | String filename = file.getName(); 31 | if (filename.endsWith(FileExtension.PROPERTIES_SYMBOL) 32 | || filename.endsWith(FileExtension.YAML_SYMBOL_1) 33 | || filename.endsWith(FileExtension.YAML_SYMBOL_2)) { 34 | return file.getAbsolutePath(); 35 | } 36 | } 37 | } 38 | 39 | return null; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /smqtt-bootstrap/src/main/java/io/github/quickmsg/exception/NotSupportConfigException.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.exception; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public class NotSupportConfigException extends RuntimeException { 7 | 8 | public NotSupportConfigException() { 9 | super("请使用properties/yaml配置文件"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /smqtt-bootstrap/src/main/java/io/github/quickmsg/jar/JarStarter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.jar; 2 | 3 | import io.github.quickmsg.AbstractStarter; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Slf4j 12 | public class JarStarter extends AbstractStarter { 13 | 14 | public static void main(String[] args) throws IOException { 15 | log.info("JarStarter start args {}", String.join(",", args)); 16 | if (args.length > 0) { 17 | start(args[0]); 18 | } else { 19 | start(null); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-bootstrap/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | _____ __ __ ____ _______ _______ 3 | / ____| \/ |/ __ \__ __|__ __| 4 | | (___ | \ / | | | | | | | | 5 | \___ \| |\/| | | | | | | | | 6 | ____) | | | | |__| | | | | | 7 | |_____/|_| |_|\___\_\ |_| |_| 8 | 9 | -------------------------------------------------------------------------------- /smqtt-bootstrap/src/main/resources/test.yaml: -------------------------------------------------------------------------------- 1 | smqtt: 2 | tcp: 3 | port: 7000 -------------------------------------------------------------------------------- /smqtt-bootstrap/src/test/java/ClusterNode2.java: -------------------------------------------------------------------------------- 1 | import ch.qos.logback.classic.Level; 2 | import io.github.quickmsg.common.config.BootstrapConfig; 3 | import io.github.quickmsg.core.Bootstrap; 4 | 5 | /** 6 | * @author luxurong 7 | * @date 2021/5/6 19:25 8 | * @description 9 | */ 10 | public class ClusterNode2 { 11 | 12 | @org.junit.Test 13 | public void startServer() throws InterruptedException { 14 | 15 | Bootstrap bootstrap = Bootstrap.builder() 16 | .rootLevel(Level.DEBUG) 17 | .tcpConfig( 18 | BootstrapConfig 19 | .TcpConfig 20 | .builder() 21 | .port(8551) 22 | .build()) 23 | .clusterConfig( 24 | BootstrapConfig. 25 | ClusterConfig 26 | .builder() 27 | .enable(true) 28 | .node("node-3") 29 | .namespace("smqtt") 30 | .port(7772) 31 | .url("127.0.0.1:7773,127.0.0.1:7771"). 32 | build()) 33 | .build() 34 | .start().block(); 35 | assert bootstrap != null; 36 | // 关闭服 37 | // bootstrap.shutdown(); 38 | Thread.sleep(1000000); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-bootstrap/src/test/java/ClusterNode3.java: -------------------------------------------------------------------------------- 1 | import ch.qos.logback.classic.Level; 2 | import io.github.quickmsg.common.config.BootstrapConfig; 3 | import io.github.quickmsg.core.Bootstrap; 4 | 5 | /** 6 | * @author luxurong 7 | * @date 2021/5/6 19:25 8 | * @description 9 | */ 10 | public class ClusterNode3 { 11 | 12 | @org.junit.Test 13 | public void startServer() throws InterruptedException { 14 | 15 | Bootstrap bootstrap = Bootstrap.builder() 16 | .rootLevel(Level.DEBUG) 17 | .tcpConfig( 18 | BootstrapConfig 19 | .TcpConfig 20 | .builder() 21 | .port(8553) 22 | .build()) 23 | .clusterConfig( 24 | BootstrapConfig. 25 | ClusterConfig 26 | .builder() 27 | .enable(true) 28 | .node("node-4") 29 | .port(7771) 30 | .namespace("smqtt") 31 | .url("127.0.0.1:7773,127.0.0.1:7772"). 32 | build()) 33 | .build() 34 | .start().block(); 35 | assert bootstrap != null; 36 | // 关闭服 37 | // bootstrap.shutdown(); 38 | Thread.sleep(1000000); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/Receiver.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common; 2 | 3 | import reactor.core.publisher.Mono; 4 | import reactor.netty.DisposableServer; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public interface Receiver { 10 | 11 | /** 12 | * 绑定接口 13 | * 14 | * @return {@link DisposableServer} 15 | */ 16 | Mono bind(); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/StartUp.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public interface StartUp { 9 | 10 | 11 | /** 12 | * 注入环境变量 13 | * 14 | * @param environmentMap 注入不同配置 15 | * @see io.github.quickmsg.common.config.BootstrapConfig 16 | */ 17 | default void startUp(Map environmentMap) { 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/acl/AclAction.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.acl; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum AclAction { 7 | 8 | /** 9 | * mqtt sub 10 | */ 11 | SUBSCRIBE, 12 | 13 | /** 14 | * mqtt pub 15 | */ 16 | PUBLISH, 17 | /** 18 | * 新增ACL配置时, 一次性添加以上三种动作 19 | */ 20 | ALL 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/acl/AclManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.acl; 2 | 3 | import io.github.quickmsg.common.acl.model.PolicyModel; 4 | import io.github.quickmsg.common.channel.MqttChannel; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface AclManager { 12 | 13 | boolean check(MqttChannel mqttChannel, String source, AclAction action); 14 | 15 | boolean add(String sub,String source,AclAction action,AclType type); 16 | 17 | 18 | boolean delete(String sub,String source,AclAction action,AclType type); 19 | 20 | List> get(PolicyModel policyModel); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/acl/AclPolicy.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.acl; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum AclPolicy { 7 | 8 | /** 9 | * no check 10 | */ 11 | NONE, 12 | /** 13 | * disk file 14 | */ 15 | FILE, 16 | 17 | /** 18 | * sql database 19 | */ 20 | JDBC 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/acl/AclType.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.acl; 2 | 3 | 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public enum AclType { 10 | 11 | ALL(""), 12 | 13 | 14 | ALLOW("allow"), 15 | 16 | DENY("deny"); 17 | 18 | @Getter 19 | private final String desc; 20 | 21 | AclType(String desc) { 22 | this.desc = desc; 23 | } 24 | 25 | public static AclType fromDesc(String desc) { 26 | for (AclType type : AclType.values()) { 27 | if (type.desc.equals(desc)) { 28 | return type; 29 | } 30 | } 31 | return null; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/acl/model/PolicyModel.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.acl.model; 2 | 3 | import io.github.quickmsg.common.acl.AclAction; 4 | import io.github.quickmsg.common.acl.AclType; 5 | import lombok.Data; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | @Data 11 | public class PolicyModel { 12 | 13 | private String subject; 14 | 15 | private String source; 16 | 17 | private AclAction action; 18 | 19 | private AclType aclType; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/annotation/AllowCors.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Target({ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | @Inherited 12 | public @interface AllowCors { 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/annotation/Header.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.annotation; 2 | 3 | import java.lang.annotation.*; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | 10 | @Target({ElementType.TYPE}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @Inherited 14 | public @interface Header { 15 | 16 | String key(); 17 | 18 | String value(); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/annotation/Headers.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | 9 | @Target({ElementType.TYPE}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | @Inherited 13 | public @interface Headers { 14 | 15 | Header[] headers(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/annotation/Intercept.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Target({ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | @Inherited 12 | public @interface Intercept { 13 | 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/annotation/Router.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.annotation; 2 | 3 | import io.github.quickmsg.common.enums.HttpType; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | @Inherited 15 | public @interface Router { 16 | 17 | String value(); 18 | 19 | boolean resource() default false; 20 | 21 | HttpType type() default HttpType.GET; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/auth/AuthBean.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.auth; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Data 9 | public class AuthBean { 10 | 11 | private String clientId; 12 | 13 | private String username; 14 | 15 | private String password; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/auth/AuthManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.auth; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public interface AuthManager { 7 | 8 | /** 9 | * 认证接口 10 | * 11 | * @param userName 用户名称 12 | * @param passwordInBytes 密钥 13 | * @param clientIdentifier 设备标志 14 | * @return 布尔 15 | */ 16 | Boolean auth(String userName, byte[] passwordInBytes, String clientIdentifier); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/channel/ChannelRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.channel; 2 | 3 | import io.github.quickmsg.common.StartUp; 4 | import io.github.quickmsg.common.spi.DynamicLoader; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface ChannelRegistry extends StartUp { 12 | 13 | 14 | ChannelRegistry INSTANCE = DynamicLoader.findFirst(ChannelRegistry.class).orElse(null); 15 | 16 | 17 | /** 18 | * 关闭通道 19 | * 20 | * @param mqttChannel {@link MqttChannel} 21 | */ 22 | void close(MqttChannel mqttChannel); 23 | 24 | /** 25 | * 注册通道 26 | * 27 | * @param clientIdentifier 客户端id 28 | * @param mqttChannel {@link MqttChannel} 29 | */ 30 | void registry(String clientIdentifier, MqttChannel mqttChannel); 31 | 32 | /** 33 | * 判读通道是否存在 34 | * 35 | * @param clientIdentifier 客户端id 36 | * @return 布尔 37 | */ 38 | boolean exists(String clientIdentifier); 39 | 40 | 41 | /** 42 | * 获取通道 43 | * 44 | * @param clientIdentifier 客户端id 45 | * @return MqttChannel 46 | */ 47 | MqttChannel get(String clientIdentifier); 48 | 49 | 50 | /** 51 | * 获取通道计数 52 | * 53 | * @return 通道数 54 | */ 55 | Integer counts(); 56 | 57 | 58 | /** 59 | * 获取说有channel信息 60 | * 61 | * @return {@link Collection} 62 | */ 63 | Collection getChannels(); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/channel/MockMqttChannel.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.channel; 2 | 3 | import io.netty.handler.codec.mqtt.MqttMessage; 4 | import reactor.core.publisher.Mono; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class MockMqttChannel extends MqttChannel { 10 | 11 | private MockMqttChannel() { 12 | 13 | } 14 | 15 | public final static MockMqttChannel DEFAULT_MOCK_CHANNEL = new MockMqttChannel(); 16 | 17 | 18 | public static MockMqttChannel wrapClientIdentifier(String clientIdentifier) { 19 | MockMqttChannel mockMqttChannel = new MockMqttChannel(); 20 | mockMqttChannel.setClientIdentifier(clientIdentifier); 21 | return mockMqttChannel; 22 | } 23 | 24 | 25 | @Override 26 | public Mono write(MqttMessage mqttMessage, boolean retry) { 27 | return Mono.empty(); 28 | } 29 | 30 | 31 | @Override 32 | public Boolean getIsMock() { 33 | return true; 34 | } 35 | 36 | 37 | @Override 38 | public String toString() { 39 | return "MockMqttChannel{" + 40 | ", clientIdentifier='" + getClientIdentifier() + '\'' + '}'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/channel/traffic/TrafficHandlerLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.channel.traffic; 2 | 3 | import io.netty.handler.traffic.AbstractTrafficShapingHandler; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public interface TrafficHandlerLoader { 9 | 10 | /** 11 | * return TrafficHandlerLoader 12 | * 13 | * @return {@link AbstractTrafficShapingHandler} 14 | */ 15 | AbstractTrafficShapingHandler get(); 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/cluster/ClusterHandler.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.cluster; 2 | 3 | import io.github.quickmsg.common.message.HeapMqttMessage; 4 | import reactor.core.publisher.Mono; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface ClusterHandler { 12 | 13 | 14 | /** 15 | * 获取集群信息 16 | * 17 | * @return {@link ClusterNode} 18 | */ 19 | List getClusterInfo(); 20 | 21 | 22 | /** 23 | * 传播集群消息 24 | * 25 | * @param heapMqttMessage 集群 26 | * @return {@link Mono} 27 | */ 28 | Mono spreadGossip(HeapMqttMessage heapMqttMessage); 29 | 30 | 31 | /** 32 | * 传播集群消息 33 | * 34 | * @param heapMqttMessage 集群 35 | * @return {@link Mono} 36 | */ 37 | Mono send(HeapMqttMessage heapMqttMessage); 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/cluster/ClusterNode.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.cluster; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | @Data 10 | @Builder 11 | public class ClusterNode { 12 | 13 | /** 14 | * 别名 15 | */ 16 | private String alias; 17 | 18 | /** 19 | * host 20 | */ 21 | private String host; 22 | 23 | 24 | /** 25 | * 端口 26 | */ 27 | private Integer port; 28 | 29 | 30 | /** 31 | * 命名空间 32 | */ 33 | private String namespace; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/AbstractConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | import io.github.quickmsg.common.rule.RuleChainDefinition; 4 | import io.github.quickmsg.common.rule.RuleDefinition; 5 | import io.github.quickmsg.common.rule.source.SourceDefinition; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public interface AbstractConfiguration extends Configuration { 14 | 15 | 16 | /** 17 | * 获取websocket端口 18 | * 19 | * @return port 20 | */ 21 | Integer getWebSocketPort(); 22 | 23 | /** 24 | * 获取规则引擎 25 | * 26 | * @return {@link RuleDefinition} 27 | */ 28 | List getRuleChainDefinitions(); 29 | 30 | 31 | /** 32 | * 获取source 33 | * 34 | * @return {@link SourceDefinition} 35 | */ 36 | List getSourceDefinitions(); 37 | 38 | /** 39 | * 获取acl配置 40 | * 41 | * @return {@link AclConfig} 42 | */ 43 | AclConfig getAclConfig(); 44 | 45 | /** 46 | * 获取环境参数 47 | * 48 | * @return {@link Map} 49 | */ 50 | Map getEnvironmentMap(); 51 | 52 | 53 | AuthConfig getAuthConfig(); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/AclConfig.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | import io.github.quickmsg.common.acl.AclPolicy; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | @Data 10 | public class AclConfig { 11 | 12 | private AclPolicy aclPolicy; 13 | 14 | private String filePath; 15 | 16 | private JdbcAclConfig jdbcAclConfig; 17 | 18 | @Data 19 | public static class JdbcAclConfig { 20 | 21 | private String driver; 22 | 23 | private String url; 24 | 25 | private String username; 26 | 27 | private String password; 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/AuthConfig.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | @Data 11 | public class AuthConfig { 12 | 13 | private SqlAuthConfig sql; 14 | 15 | private HttpAuthConfig http; 16 | 17 | private FixedAuthConfig fixed; 18 | 19 | private String file; 20 | 21 | @Data 22 | public static class FixedAuthConfig { 23 | 24 | private String username; 25 | 26 | private String password; 27 | 28 | } 29 | 30 | @Data 31 | public static class HttpAuthConfig { 32 | 33 | private String host; 34 | 35 | private int port; 36 | 37 | private String path; 38 | 39 | private String method; 40 | 41 | private Map headers; 42 | 43 | private Map params; 44 | 45 | } 46 | 47 | 48 | @Data 49 | public static class SqlAuthConfig { 50 | 51 | private String driver; 52 | 53 | private String url; 54 | 55 | private String username; 56 | 57 | private String password; 58 | 59 | private String authSql; 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/ConfigCheck.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | import io.github.quickmsg.common.metric.MeterType; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class ConfigCheck { 11 | 12 | public static void checkMeterConfig(BootstrapConfig.MeterConfig config) { 13 | if (config != null) { 14 | if (config.getMeterType() == MeterType.INFLUXDB) { 15 | if (config.getInfluxdb() != null) { 16 | Objects.requireNonNull(config.getInfluxdb().getUri()); 17 | Objects.requireNonNull(config.getInfluxdb().getDb()); 18 | } 19 | } 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/ConnectModel.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum ConnectModel { 7 | UNIQUE, 8 | KICK 9 | } 10 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/config/SslContext.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class SslContext { 16 | 17 | private String crt; 18 | 19 | private String key; 20 | 21 | private String ca; 22 | 23 | private Boolean enable; 24 | 25 | 26 | public SslContext(String crt, String key) { 27 | this.crt = crt; 28 | this.key = key; 29 | } 30 | 31 | public SslContext(String crt, String key, Boolean enable) { 32 | this.crt = crt; 33 | this.key = key; 34 | this.enable = enable; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/context/ContextHolder.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.context; 2 | 3 | import io.github.quickmsg.common.config.Configuration; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public class ContextHolder { 9 | 10 | private static ReceiveContext context ; 11 | 12 | public static void setReceiveContext(ReceiveContext context){ 13 | ContextHolder.context = context; 14 | } 15 | 16 | public static ReceiveContext getReceiveContext(){ 17 | return ContextHolder.context; 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/enums/ChannelStatus.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.enums; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum ChannelStatus { 7 | 8 | /** 9 | * 初始化 10 | */ 11 | INIT, 12 | 13 | /** 14 | * 在线 15 | */ 16 | ONLINE, 17 | 18 | /** 19 | * 离线 20 | */ 21 | OFFLINE, 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/enums/ClusterStatus.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.enums; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum ClusterStatus { 7 | 8 | /** 9 | * 添加 10 | */ 11 | ADDED, 12 | 13 | /** 14 | * 移除 15 | */ 16 | REMOVED, 17 | 18 | /** 19 | * 离开 20 | */ 21 | LEAVING, 22 | 23 | 24 | /** 25 | * 更新 26 | */ 27 | UPDATED 28 | 29 | } 30 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/enums/HttpType.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.enums; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum HttpType { 7 | 8 | /** 9 | * post请求 10 | */ 11 | POST, 12 | /** 13 | * get请求 14 | */ 15 | GET, 16 | /** 17 | * delete请求 18 | */ 19 | DELETE, 20 | /** 21 | * put请求 22 | */ 23 | PUT, 24 | 25 | /** 26 | * OPTIONS请求 27 | */ 28 | OPTIONS, 29 | 30 | /** 31 | * 文件流 32 | */ 33 | File, 34 | 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/enums/RuleType.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.enums; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum RuleType { 7 | 8 | /** 9 | * 条件过滤器 10 | */ 11 | PREDICATE, 12 | 13 | /** 14 | * topic转发器 15 | */ 16 | TOPIC, 17 | /** 18 | * log转发器 19 | */ 20 | LOG, 21 | /** 22 | * kafka转发器 23 | */ 24 | KAFKA, 25 | /** 26 | * rocketmq转发器 27 | */ 28 | ROCKET_MQ, 29 | /** 30 | * rabbitmq转发器 31 | */ 32 | RABBIT_MQ, 33 | /** 34 | * web 35 | */ 36 | HTTP, 37 | 38 | /** 39 | * 数据库 40 | */ 41 | DATA_BASE, 42 | /** 43 | * mqtt转发 44 | */ 45 | MQTT 46 | 47 | } 48 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/environment/EnvContext.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.environment; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | @Getter 13 | public class EnvContext { 14 | 15 | private final Map environments; 16 | 17 | public EnvContext() { 18 | this.environments = new HashMap<>(); 19 | } 20 | 21 | 22 | public EnvContext(Map environments) { 23 | this.environments = environments; 24 | } 25 | 26 | public Optional obtainKey(String key) { 27 | return Optional.ofNullable(environments) 28 | .map(envs -> envs.get(key)); 29 | } 30 | 31 | public String obtainKeyOrDefault(String key, String defaultValue) { 32 | return Optional.ofNullable(environments) 33 | .map(envs -> envs.get(key)).orElse(defaultValue); 34 | } 35 | 36 | public void put(String key, String defaultValue) { 37 | Optional.ofNullable(environments) 38 | .ifPresent(envs -> envs.put(key, defaultValue)); 39 | } 40 | 41 | public static EnvContext empty() { 42 | return new EnvContext(null); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/interceptor/Interceptor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.interceptor; 2 | 3 | import io.github.quickmsg.common.protocol.ProtocolAdaptor; 4 | 5 | import java.lang.reflect.Proxy; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public interface Interceptor { 11 | 12 | /** 13 | * 拦截目标参数 14 | * 15 | * @param invocation {@link Invocation} 16 | * @return Object 17 | */ 18 | Object intercept(Invocation invocation); 19 | 20 | 21 | /** 22 | * 拦截链 23 | * 24 | * @param protocolAdaptor {{@link ProtocolAdaptor} 25 | * @return 代理类 26 | */ 27 | default ProtocolAdaptor proxyProtocol(ProtocolAdaptor protocolAdaptor) { 28 | return (ProtocolAdaptor) Proxy.newProxyInstance(protocolAdaptor.getClass().getClassLoader(), new Class[]{ProtocolAdaptor.class}, new InterceptorHandler(this, protocolAdaptor)); 29 | } 30 | 31 | 32 | /** 33 | * 排序 34 | * 35 | * @return 排序 36 | */ 37 | int sort(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/interceptor/InterceptorHandler.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.interceptor; 2 | 3 | import io.github.quickmsg.common.annotation.Intercept; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.util.Optional; 10 | 11 | /** 12 | * @author luxurong 13 | */ 14 | public class InterceptorHandler implements InvocationHandler { 15 | 16 | private final Interceptor interceptor; 17 | 18 | private final Object target; 19 | 20 | public InterceptorHandler(Interceptor interceptor, Object target) { 21 | this.interceptor = interceptor; 22 | this.target = target; 23 | } 24 | 25 | 26 | @Override 27 | public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { 28 | Intercept intercept = method.getAnnotation(Intercept.class); 29 | if (intercept == null) { 30 | return method.invoke(target, args); 31 | } else { 32 | return interceptor.intercept(new Invocation(method, target, args)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/interceptor/Invocation.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.interceptor; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | @AllArgsConstructor 13 | @Getter 14 | @Slf4j 15 | public class Invocation { 16 | 17 | private Method method; 18 | 19 | private Object target; 20 | 21 | private Object[] args; 22 | 23 | public Object proceed() { 24 | try { 25 | return method.invoke(target, args); 26 | } catch (Exception e) { 27 | log.error("invocation {} proceed error", this, e); 28 | return null; 29 | } 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/CloseMqttMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Data 9 | public class CloseMqttMessage { 10 | 11 | private String clientIdentifier; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/ClusterMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Data 9 | public class ClusterMessage { 10 | 11 | public ClusterMessage(){} 12 | 13 | private ClusterEvent clusterEvent; 14 | 15 | private Object message; 16 | 17 | public static enum ClusterEvent{ 18 | 19 | PUBLISH, 20 | 21 | CLOSE 22 | 23 | } 24 | 25 | public ClusterMessage(HeapMqttMessage heapMqttMessage){ 26 | this.clusterEvent = ClusterEvent.PUBLISH; 27 | this.message= heapMqttMessage; 28 | } 29 | 30 | public ClusterMessage(CloseMqttMessage closeMqttMessage){ 31 | this.clusterEvent = ClusterEvent.CLOSE; 32 | this.message= closeMqttMessage; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/EventRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.context.ReceiveContext; 5 | import io.github.quickmsg.common.enums.Event; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | public interface EventRegistry { 13 | 14 | 15 | /** 16 | * message 17 | * 18 | * @param event {@link Event} 19 | * @param mqttChannel {@link MqttChannel} 20 | * @param body {@link Object} 21 | * @param receiveContext {@link ReceiveContext} 22 | */ 23 | void registry(Event event, MqttChannel mqttChannel, Object body, ReceiveContext receiveContext); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/HeapMqttMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.github.quickmsg.common.utils.JacksonUtil; 4 | import io.netty.handler.codec.mqtt.MqttProperties; 5 | import io.netty.util.internal.StringUtil; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author luxurong 16 | */ 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | @Data 21 | public class HeapMqttMessage { 22 | 23 | private long timestamp; 24 | 25 | private String clientIdentifier; 26 | 27 | private String topic; 28 | 29 | private int qos; 30 | 31 | private boolean retain; 32 | 33 | private Object message; 34 | 35 | private MqttProperties properties; 36 | 37 | 38 | public Map getKeyMap() { 39 | Map keys = new HashMap<>(5); 40 | keys.put("clientIdentifier", this.clientIdentifier); 41 | keys.put("topic", this.topic); 42 | keys.put("qos", this.qos); 43 | keys.put("retain", this.retain); 44 | keys.put("msg", message); 45 | return keys; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/HttpPublishMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.netty.buffer.PooledByteBufAllocator; 4 | import io.netty.handler.codec.mqtt.MqttPublishMessage; 5 | import io.netty.handler.codec.mqtt.MqttQoS; 6 | import lombok.Data; 7 | 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author luxurong 13 | */ 14 | @Data 15 | public class HttpPublishMessage { 16 | 17 | private String topic; 18 | 19 | private int qos; 20 | 21 | private boolean retain; 22 | 23 | private String message; 24 | 25 | private Map others; 26 | 27 | 28 | public MqttPublishMessage getPublishMessage() { 29 | return MqttMessageBuilder.buildPub( 30 | false, 31 | MqttQoS.valueOf(qos), 32 | retain, 33 | 1, 34 | topic, 35 | PooledByteBufAllocator.DEFAULT.buffer().writeBytes(message.getBytes(StandardCharsets.UTF_8))); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/JsonMap.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.github.quickmsg.common.utils.JacksonUtil; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class JsonMap extends HashMap { 11 | 12 | public JsonMap() { 13 | super(); 14 | } 15 | 16 | 17 | public JsonMap(int initialCapacity) { 18 | super(initialCapacity); 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return JacksonUtil.map2Json(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/MessageRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.github.quickmsg.common.StartUp; 4 | import io.github.quickmsg.common.spi.DynamicLoader; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface MessageRegistry extends StartUp { 12 | 13 | MessageRegistry INSTANCE = DynamicLoader.findFirst(MessageRegistry.class).orElse(null); 14 | 15 | 16 | /** 17 | * 获取连接下线后的session消息 18 | * 19 | * @param clientIdentifier 设备id 20 | * @return {@link SessionMessage} 21 | */ 22 | List getSessionMessage(String clientIdentifier); 23 | 24 | 25 | /** 26 | * 发送连接下线后的session消息 27 | * 28 | * @param sessionMessage {@link SessionMessage} 29 | */ 30 | void saveSessionMessage(SessionMessage sessionMessage); 31 | 32 | 33 | /** 34 | * 保留Topic保留消息 35 | * 36 | * @param retainMessage {@link RetainMessage} 37 | */ 38 | void saveRetainMessage(RetainMessage retainMessage); 39 | 40 | 41 | /** 42 | * 保留Topic保留消息 43 | * 44 | * @param topic topic 45 | * @return {@link RetainMessage} 46 | */ 47 | List getRetainMessage(String topic); 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/SmqttMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.netty.handler.codec.mqtt.MqttMessage; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | @Getter 13 | @Setter 14 | @ToString 15 | @AllArgsConstructor 16 | public class SmqttMessage { 17 | 18 | private T message; 19 | 20 | private long timestamp; 21 | 22 | private Boolean isCluster; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/SubscribeChannelContext.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.netty.handler.codec.mqtt.MqttQoS; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Data 12 | @Builder 13 | public class SubscribeChannelContext { 14 | 15 | private MqttQoS mqttQoS; 16 | 17 | private MqttChannel mqttChannel; 18 | 19 | private String topic; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/message/system/ChannelStatusMessage.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.message.system; 2 | 3 | import io.github.quickmsg.common.enums.ChannelStatus; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ChannelStatusMessage { 15 | 16 | /** 17 | * clint id 18 | */ 19 | private String clientIdentifier; 20 | 21 | /** 22 | * timestamp 23 | */ 24 | private long timestamp; 25 | 26 | /** 27 | * username 28 | */ 29 | private String username; 30 | 31 | /** 32 | * channelStatus 33 | * 34 | * @see ChannelStatus 35 | */ 36 | private ChannelStatus channelStatus; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/AbstractMetricRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public abstract class AbstractMetricRegistry implements MetricRegistry { 11 | 12 | 13 | private final Map metricCounterMap = new HashMap<>(); 14 | 15 | protected AbstractMetricRegistry(List metricCounters) { 16 | metricCounters.forEach(metricCounter -> metricCounterMap.put(metricCounter.getCounterType(), metricCounter)); 17 | } 18 | 19 | @Override 20 | public MetricCounter getMetricCounter(CounterType counterType) { 21 | return metricCounterMap.get(counterType); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/CounterType.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Getter 9 | public enum CounterType { 10 | 11 | CONNECT("smqtt.connect.count"), 12 | SUBSCRIBE("smqtt.subscribe.count"), 13 | 14 | PUBLISH_EVENT("smqtt.publish.event.count"), 15 | CONNECT_EVENT("smqtt.connect.event.count"), 16 | SUBSCRIBE_EVENT("smqtt.subscribe.event.count"), 17 | UN_SUBSCRIBE_EVENT("smqtt.unscribe.event.count"), 18 | DIS_CONNECT_EVENT("smqtt.disconnect.event.count"), 19 | CLOSE_EVENT("smqtt.close.event.count"); 20 | 21 | private final String desc; 22 | 23 | CounterType(String desc) { 24 | this.desc = desc; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/EventCounter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import io.github.quickmsg.common.metric.CounterType; 4 | import io.github.quickmsg.common.metric.MetricBean; 5 | import io.github.quickmsg.common.metric.WholeCounter; 6 | import io.micrometer.core.instrument.Counter; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class EventCounter extends WholeCounter { 12 | 13 | private CounterType counterType; 14 | 15 | private Counter counter; 16 | 17 | public EventCounter(MetricBean metricBean, CounterType counterType) { 18 | super(metricBean); 19 | this.counterType = counterType; 20 | initCount(); 21 | } 22 | 23 | @Override 24 | public void initCount() { 25 | this.counter = 26 | getMetricBean() 27 | .getMeterRegistry().counter(getCounterType().getDesc(), getMetricBean().getTags()); 28 | } 29 | 30 | @Override 31 | public void callMeter(long count) { 32 | counter.increment(); 33 | } 34 | 35 | @Override 36 | public CounterType getCounterType() { 37 | return this.counterType; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MeterType.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum MeterType { 7 | 8 | INFLUXDB, 9 | 10 | PROMETHEUS 11 | 12 | } 13 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricBean.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import io.micrometer.core.instrument.MeterRegistry; 4 | import io.micrometer.core.instrument.Tags; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public interface MetricBean { 10 | 11 | MetricBean Close(); 12 | 13 | MeterRegistry getMeterRegistry(); 14 | 15 | default Tags getTags() { 16 | return Tags.empty().and(MetricConstant.COMMON_TAG_NAME, MetricConstant.COMMON_TAG_VALUE); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricConstant.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | public interface MetricConstant { 4 | 5 | String COMMON_TAG_NAME = "application"; 6 | 7 | String COMMON_TAG_VALUE = "smqtt"; 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricCounter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public interface MetricCounter { 7 | 8 | long getCounter(); 9 | 10 | void increment(); 11 | 12 | void decrement(); 13 | 14 | void reset(); 15 | 16 | void callMeter(long counter); 17 | 18 | MetricBean getMetricBean(); 19 | 20 | CounterType getCounterType(); 21 | 22 | 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | 4 | /** 5 | * @author luxurong 6 | */ 7 | public interface MetricFactory { 8 | 9 | MetricManager getMetricManager(); 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricManagerHolder.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | @Getter 11 | public class MetricManagerHolder { 12 | 13 | public static MetricManager metricManager = null; 14 | 15 | public static MetricManager setMetricManager(MetricManager metricManager){ 16 | MetricManagerHolder.metricManager = metricManager; 17 | return metricManager; 18 | } 19 | 20 | public static Optional getMetricRegistry(){ 21 | return Optional.of(metricManager).map(MetricManager::getMetricRegistry); 22 | } 23 | 24 | public static MetricManager getMetricManager(){ 25 | return metricManager; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/MetricRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | 4 | /** 5 | * @author luxurong 6 | */ 7 | public interface MetricRegistry { 8 | 9 | MetricCounter getMetricCounter(CounterType counterType); 10 | 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/TotalCounter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public class TotalCounter extends WholeCounter { 7 | 8 | private final CounterType counterType; 9 | 10 | public TotalCounter(MetricBean metricBean, CounterType counterType) { 11 | super(metricBean); 12 | this.counterType = counterType; 13 | initCount(); 14 | } 15 | 16 | 17 | @Override 18 | public void callMeter(long counter) { 19 | getMetricBean().getMeterRegistry().gauge(getCounterType().getDesc(), counter); 20 | } 21 | 22 | @Override 23 | public CounterType getCounterType() { 24 | return this.counterType; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/WholeCounter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public abstract class WholeCounter implements MetricCounter { 9 | 10 | 11 | private final AtomicLong count = new AtomicLong(); 12 | 13 | private final MetricBean metricBean; 14 | 15 | protected WholeCounter(MetricBean metricBean) { 16 | this.metricBean = metricBean; 17 | } 18 | 19 | public void initCount() { 20 | getMetricBean().getMeterRegistry().gauge(getCounterType().getDesc(), count); 21 | } 22 | 23 | @Override 24 | public MetricBean getMetricBean() { 25 | return this.metricBean; 26 | } 27 | 28 | @Override 29 | public void increment() { 30 | callMeter(count.incrementAndGet()); 31 | } 32 | 33 | @Override 34 | public void decrement() { 35 | callMeter(count.decrementAndGet()); 36 | } 37 | 38 | @Override 39 | public void reset() { 40 | count.set(0); 41 | } 42 | 43 | 44 | @Override 45 | public long getCounter() { 46 | return count.get(); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/local/EmptyMetricCounter.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric.local; 2 | 3 | import io.github.quickmsg.common.metric.CounterType; 4 | import io.github.quickmsg.common.metric.MetricBean; 5 | import io.github.quickmsg.common.metric.WholeCounter; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class EmptyMetricCounter extends WholeCounter { 11 | 12 | private final static EmptyMetricCounter metricCounter = new EmptyMetricCounter(); 13 | 14 | private EmptyMetricCounter(){ 15 | super(null); 16 | } 17 | 18 | public static EmptyMetricCounter instance(){ 19 | return metricCounter; 20 | } 21 | 22 | protected EmptyMetricCounter(MetricBean metricBean) { 23 | super(metricBean); 24 | } 25 | 26 | @Override 27 | public void callMeter(long counter) { 28 | 29 | } 30 | 31 | @Override 32 | public CounterType getCounterType() { 33 | return null; 34 | } 35 | 36 | @Override 37 | public void increment() { 38 | 39 | } 40 | 41 | @Override 42 | public void decrement() { 43 | 44 | } 45 | 46 | @Override 47 | public void reset() { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/local/LocalMetricBean.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric.local; 2 | 3 | import io.github.quickmsg.common.metric.MetricBean; 4 | import io.micrometer.core.instrument.MeterRegistry; 5 | import io.micrometer.core.instrument.logging.LoggingMeterRegistry; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class LocalMetricBean implements MetricBean { 11 | 12 | 13 | public LocalMetricBean() { 14 | } 15 | 16 | @Override 17 | public MetricBean Close() { 18 | return this; 19 | } 20 | 21 | @Override 22 | public MeterRegistry getMeterRegistry() { 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/metric/local/LocalMetricManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.metric.local; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.metric.*; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public class LocalMetricManager implements MetricManager { 14 | 15 | public LocalMetricManager() { 16 | } 17 | 18 | 19 | @Override 20 | public MetricRegistry getMetricRegistry() { 21 | return new AbstractMetricRegistry(createMetricRegistry(getMetricBean())) { 22 | @Override 23 | public MetricCounter getMetricCounter(CounterType counterType) { 24 | return EmptyMetricCounter.instance(); 25 | } 26 | }; 27 | } 28 | 29 | 30 | @Override 31 | public MetricBean getMetricBean() { 32 | return new LocalMetricBean(); 33 | } 34 | 35 | @Override 36 | public BootstrapConfig.MeterConfig getMeterConfig() { 37 | return null; 38 | } 39 | 40 | @Override 41 | public List createMetricRegistry(MetricBean metricBean) { 42 | return Collections.emptyList(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/protocol/Protocol.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.protocol; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.message.SmqttMessage; 5 | import io.netty.handler.codec.mqtt.MqttMessage; 6 | import io.netty.handler.codec.mqtt.MqttMessageType; 7 | import reactor.core.publisher.Mono; 8 | import reactor.util.context.ContextView; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author luxurong 14 | */ 15 | public interface Protocol { 16 | 17 | 18 | /** 19 | * 解析协议添加上下文 20 | * 21 | * @param message {@link SmqttMessage} 22 | * @param mqttChannel {@link MqttChannel} 23 | * @return Mono 24 | * @see MqttMessage 25 | */ 26 | default Mono doParseProtocol(SmqttMessage message, MqttChannel mqttChannel) { 27 | return Mono.deferContextual(contextView -> this.parseProtocol(message, mqttChannel, contextView)); 28 | } 29 | 30 | 31 | /** 32 | * 处理协议 33 | * 34 | * @param message {@link SmqttMessage} 35 | * @param mqttChannel {@link MqttChannel} 36 | * @param contextView {@link ContextView} 37 | * @see MqttMessage 38 | * @return Mono 39 | */ 40 | Mono parseProtocol(SmqttMessage message, MqttChannel mqttChannel, ContextView contextView); 41 | 42 | 43 | /** 44 | * 获取此协议支持的消息类型 45 | * 46 | * @return {@link MqttMessageType} 47 | */ 48 | List getMqttMessageTypes(); 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/protocol/ProtocolAdaptor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.protocol; 2 | 3 | import io.github.quickmsg.common.annotation.Intercept; 4 | import io.github.quickmsg.common.channel.MqttChannel; 5 | import io.github.quickmsg.common.config.Configuration; 6 | import io.github.quickmsg.common.context.ReceiveContext; 7 | import io.github.quickmsg.common.interceptor.MessageProxy; 8 | import io.github.quickmsg.common.message.SmqttMessage; 9 | import io.github.quickmsg.common.spi.DynamicLoader; 10 | import io.netty.handler.codec.mqtt.MqttMessage; 11 | 12 | /** 13 | * @author luxurong 14 | */ 15 | public interface ProtocolAdaptor { 16 | 17 | ProtocolAdaptor INSTANCE = DynamicLoader.findFirst(ProtocolAdaptor.class).orElse(null); 18 | 19 | 20 | MessageProxy MESSAGE_PROXY = new MessageProxy(); 21 | 22 | 23 | /** 24 | * 分发某种协议下 消息类型 25 | * 26 | * @param mqttChannel {@link MqttChannel} 27 | * @param mqttMessage {@link SmqttMessage} 28 | * @param receiveContext {@link ReceiveContext} 29 | * @param {@link Configuration} 30 | */ 31 | @Intercept 32 | void chooseProtocol(MqttChannel mqttChannel, SmqttMessage mqttMessage, ReceiveContext receiveContext); 33 | 34 | 35 | 36 | /** 37 | * 代理类 用来注入 filter monitor 38 | * 39 | * @return {@link ProtocolAdaptor} 40 | */ 41 | default ProtocolAdaptor proxy() { 42 | return MESSAGE_PROXY.proxy(this); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/retry/Ack.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.retry; 2 | 3 | import io.netty.util.TimerTask; 4 | 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public interface Ack extends TimerTask { 11 | 12 | int getTimed(); 13 | 14 | TimeUnit getTimeUnit(); 15 | 16 | long getId(); 17 | 18 | void start(); 19 | 20 | void stop(); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/retry/AckManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.retry; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public interface AckManager { 7 | 8 | void addAck(Ack ack); 9 | 10 | Ack getAck(Long id); 11 | 12 | void deleteAck(Long id); 13 | 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/retry/RetryAck.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.retry; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | 7 | public class RetryAck extends AbsAck { 8 | 9 | private final long id; 10 | 11 | 12 | public RetryAck(long id, int maxRetrySize, int period, Runnable runnable, AckManager ackManager, Runnable consumer) { 13 | super(maxRetrySize, period, runnable, ackManager,consumer); 14 | this.id = id; 15 | } 16 | 17 | @Override 18 | public long getId() { 19 | return id; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/retry/TimeAckManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.retry; 2 | 3 | import io.netty.util.HashedWheelTimer; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | public class TimeAckManager extends HashedWheelTimer implements AckManager { 13 | 14 | private final Map ackMap = new ConcurrentHashMap<>(); 15 | 16 | public TimeAckManager(long tickDuration, TimeUnit unit, int ticksPerWheel) { 17 | super( tickDuration, unit, ticksPerWheel); 18 | } 19 | 20 | @Override 21 | public void addAck(Ack ack) { 22 | ackMap.put(ack.getId(),ack); 23 | this.newTimeout(ack,ack.getTimed(),ack.getTimeUnit()); 24 | } 25 | 26 | @Override 27 | public Ack getAck(Long id) { 28 | return ackMap.get(id); 29 | } 30 | 31 | @Override 32 | public void deleteAck(Long id) { 33 | ackMap.remove(id); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/DslExecutor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public interface DslExecutor { 7 | 8 | /** 9 | * 执行 10 | * @param object 请求参数 11 | = */ 12 | void executeRule(Object... object); 13 | 14 | 15 | /** 16 | * 执行 17 | * @return boolean 是否需要执行 18 | */ 19 | Boolean isExecute(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/RuleChainDefinition.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class RuleChainDefinition { 17 | 18 | private String ruleName; 19 | 20 | private List chain; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/RuleDefinition.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule; 2 | 3 | import io.github.quickmsg.common.enums.RuleType; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Getter 12 | @Setter 13 | @ToString 14 | public class RuleDefinition { 15 | 16 | 17 | private String ruleName; 18 | 19 | private RuleType ruleType; 20 | 21 | private String script; 22 | 23 | 24 | } -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/source/Source.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule.source; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum Source { 7 | /** 8 | * kafka 9 | */ 10 | KAFKA, 11 | /** 12 | * rocketMq 13 | */ 14 | ROCKET_MQ, 15 | /** 16 | * RABBIT_MQ 17 | */ 18 | RABBIT_MQ, 19 | /** 20 | * 数据库 21 | */ 22 | DATA_BASE, 23 | /** 24 | * hBase 25 | */ 26 | H_BASE, 27 | 28 | /** 29 | * http 30 | */ 31 | HTTP, 32 | /** 33 | * mqtt转发 34 | */ 35 | MQTT 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/source/SourceBean.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule.source; 2 | 3 | import io.github.quickmsg.common.spi.DynamicLoader; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | public interface SourceBean { 13 | 14 | 15 | List SOURCE_BEAN_LIST = DynamicLoader.findAll(SourceBean.class) 16 | .collect(Collectors.toList()); 17 | 18 | 19 | /** 20 | * 是否支持source 21 | * 22 | * @param source {@link Source} 23 | * @return Boolean 24 | */ 25 | Boolean support(Source source); 26 | 27 | 28 | /** 29 | * 启动source 30 | * 31 | * @param sourceParam 请求参数 32 | * @return Boolean 33 | */ 34 | Boolean bootstrap(Map sourceParam); 35 | 36 | 37 | /** 38 | * 转发数据 39 | * 40 | * @param object {@link Map} 41 | */ 42 | void transmit(Object object); 43 | 44 | /** 45 | * 关闭资源 46 | */ 47 | void close(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/rule/source/SourceDefinition.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.rule.source; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | @Data 11 | public class SourceDefinition { 12 | 13 | private Source source; 14 | 15 | private String sourceName; 16 | 17 | private String replace; 18 | 19 | private Map sourceAttributes; 20 | } 21 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/scheduler/SchedulerFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.scheduler; 2 | 3 | import reactor.core.scheduler.Scheduler; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface SchedulerFactory { 12 | 13 | Map topicSchedulers = new ConcurrentHashMap<>(); 14 | 15 | 16 | /** 17 | * 获取Scheduler 18 | * 19 | * @param topic 主题 20 | * @return 定时器 21 | */ 22 | Scheduler schedulerForTopic(String topic); 23 | 24 | 25 | /** 26 | * 构建Scheduler 27 | * 28 | * @param topic 主题 29 | * @param scheduler Scheduler 30 | */ 31 | void buildSchedulerForTopic(String topic, Scheduler scheduler); 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/spi/AppServiceLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.spi; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public class AppServiceLoader { 7 | } 8 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/spi/CacheLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.spi; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.ServiceLoader; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import java.util.function.Function; 10 | import java.util.stream.Collectors; 11 | import java.util.stream.StreamSupport; 12 | 13 | /** 14 | * @author luxurong 15 | */ 16 | @Slf4j 17 | public class CacheLoader { 18 | 19 | public Map, Map> cacheBean = new ConcurrentHashMap<>(); 20 | 21 | @SuppressWarnings("unchecked") 22 | public T getBeanByType(String type, Class tClass) { 23 | Map beans = cacheBean.computeIfAbsent(tClass, this::loadAll); 24 | return (T) beans.get(type); 25 | } 26 | 27 | private Map loadAll(Class aClass) { 28 | ServiceLoader load = ServiceLoader.load(aClass); 29 | return StreamSupport.stream(load.spliterator(), false) 30 | .collect(Collectors.toMap(this::getKey, Function.identity())); 31 | } 32 | 33 | private String getKey(T t) { 34 | Spi spi = t.getClass().getAnnotation(Spi.class); 35 | if (spi == null) { 36 | log.warn("class {} not contain spi annotation ", t); 37 | } 38 | return spi == null ? "default" : spi.type(); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/spi/DynamicLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.spi; 2 | 3 | import java.util.Optional; 4 | import java.util.ServiceLoader; 5 | import java.util.function.Predicate; 6 | import java.util.stream.Stream; 7 | import java.util.stream.StreamSupport; 8 | 9 | /** 10 | * @author luxurong 11 | */ 12 | public final class DynamicLoader { 13 | 14 | 15 | private DynamicLoader() { 16 | } 17 | 18 | public static Optional findFirst(Class clazz) { 19 | ServiceLoader load = ServiceLoader.load(clazz); 20 | return StreamSupport.stream(load.spliterator(), false).findFirst(); 21 | } 22 | 23 | public static Optional findFirst(Class clazz, Predicate predicate) { 24 | ServiceLoader load = ServiceLoader.load(clazz); 25 | Stream stream = StreamSupport.stream(load.spliterator(), false); 26 | return stream.filter(predicate).findFirst(); 27 | } 28 | 29 | public static Stream findAll(Class clazz) { 30 | ServiceLoader load = ServiceLoader.load(clazz); 31 | return StreamSupport.stream(load.spliterator(), false); 32 | } 33 | 34 | public static Stream findAll(Class clazz, Predicate predicate) { 35 | ServiceLoader load = ServiceLoader.load(clazz); 36 | return StreamSupport.stream(load.spliterator(), false).filter(predicate); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/spi/Spi.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.spi; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Target({ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | @Inherited 12 | public @interface Spi { 13 | 14 | String type(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/transport/Transport.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.transport; 2 | 3 | import io.github.quickmsg.common.config.Configuration; 4 | import io.github.quickmsg.common.context.ReceiveContext; 5 | import reactor.core.Disposable; 6 | import reactor.core.publisher.Mono; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public interface Transport extends Disposable { 12 | 13 | 14 | /** 15 | * 开启连接 16 | * 17 | * @return {@link Transport} 18 | */ 19 | Mono start(); 20 | 21 | 22 | /** 23 | * 构建接受处理🥱 24 | * 25 | * @param c {@link Configuration} 26 | * @return {@link ReceiveContext} 27 | */ 28 | ReceiveContext buildReceiveContext(C c); 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/transport/TransportFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.transport; 2 | 3 | import io.github.quickmsg.common.config.Configuration; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public interface TransportFactory { 9 | 10 | /** 11 | * 创建通道 12 | * 13 | * @param c {@link Configuration} 14 | * @return {@link Transport} 15 | */ 16 | Transport createTransport(C c); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/transport/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author luxurong 3 | */ 4 | package io.github.quickmsg.common.transport; 5 | 6 | 7 | /* 网络处理 */ -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/BannerUtils.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | 10 | 11 | /** 12 | * banner 13 | * 14 | * @author zhaopeng 15 | */ 16 | @Slf4j 17 | public class BannerUtils { 18 | 19 | /** 20 | * 打印banner 21 | */ 22 | public static void banner() { 23 | try (InputStream is = BannerUtils.class.getResourceAsStream("/banner.txt")) { 24 | BufferedReader br = new BufferedReader(new InputStreamReader(is)); 25 | String line = ""; 26 | while ((line = br.readLine()) != null) { 27 | System.out.println(line); 28 | } 29 | } catch (Exception e) { 30 | log.error("banner file not exists"); 31 | } 32 | } 33 | 34 | 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/ClassPathLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.PooledByteBufAllocator; 5 | import lombok.extern.slf4j.Slf4j; 6 | import reactor.core.publisher.Mono; 7 | 8 | import java.io.*; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | @Slf4j 14 | public class ClassPathLoader { 15 | 16 | 17 | public static Mono readClassPathFile(String path) { 18 | try { 19 | InputStream inputStream = ClassPathLoader.class.getResourceAsStream(path); 20 | BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); 21 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 22 | byte[] bytes = new byte[1024]; 23 | int n ; 24 | while ((n = bufferedInputStream.read(bytes)) != -1) { 25 | out.write(bytes, 0, n); 26 | } 27 | return Mono.just(PooledByteBufAllocator.DEFAULT.buffer(out.size()).writeBytes(out.toByteArray())); 28 | } catch (IOException e) { 29 | log.error("readClassPathFile error {}",path,e); 30 | } 31 | return Mono.empty(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/FileExtension.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public class FileExtension { 7 | 8 | public static final String PROPERTIES_SYMBOL = ".properties"; 9 | 10 | public static final String YAML_SYMBOL_1 = ".yaml"; 11 | 12 | public static final String YAML_SYMBOL_2 = ".yml"; 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/IPUtils.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | import java.net.Inet4Address; 4 | import java.net.InetAddress; 5 | import java.net.NetworkInterface; 6 | import java.util.Enumeration; 7 | 8 | /** 9 | * IP帮助类 10 | * 11 | * @author zhaopeng 12 | */ 13 | public class IPUtils { 14 | 15 | /** 16 | * 获取IP地址 17 | * 18 | * @return {@link String} 19 | */ 20 | public static String getIP() { 21 | try { 22 | Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); 23 | InetAddress ip = null; 24 | while (allNetInterfaces.hasMoreElements()) { 25 | NetworkInterface netInterface = allNetInterfaces.nextElement(); 26 | Enumeration addresses = netInterface.getInetAddresses(); 27 | while (addresses.hasMoreElements()) { 28 | ip = addresses.nextElement(); 29 | if (ip != null && (ip instanceof Inet4Address)) { 30 | String retIp = ip.getHostAddress(); 31 | if (!"127.0.0.1".equals(retIp)) { 32 | return retIp; 33 | } 34 | } 35 | } 36 | } 37 | return ""; 38 | } catch (Exception e) { 39 | return ""; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/LoggerLevel.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | import ch.qos.logback.classic.LoggerContext; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class LoggerLevel { 10 | 11 | 12 | /** 13 | * 二进制日志级别 14 | */ 15 | public static void wiretap() { 16 | LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 17 | loggerContext.getLogger("reactor.netty").setLevel(ch.qos.logback.classic.Level.DEBUG); 18 | } 19 | 20 | /** 21 | * 修改root日志级别 22 | * 23 | * @param level 日志级别 24 | */ 25 | public static void root(ch.qos.logback.classic.Level level) { 26 | LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 27 | loggerContext.getLogger("root").setLevel(level); 28 | } 29 | 30 | 31 | /** 32 | * 修改logger日志级别 33 | * 34 | * @param loggerName 日志名称 35 | * @param level 日志级别 36 | */ 37 | public static void logger(String loggerName, ch.qos.logback.classic.Level level) { 38 | LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 39 | loggerContext.getLogger(loggerName).setLevel(level); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/PropertiesLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | import io.github.quickmsg.common.environment.EnvContext; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.io.*; 7 | import java.util.Enumeration; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Properties; 11 | 12 | /** 13 | * @author luxurong 14 | */ 15 | @Slf4j 16 | public class PropertiesLoader { 17 | 18 | 19 | public static EnvContext loadProperties(String filePath) { 20 | Map map = new HashMap<>(16); 21 | Properties prop = new Properties(); 22 | try { 23 | InputStream inputStream = new BufferedInputStream(new FileInputStream(new File(filePath))); 24 | prop.load(inputStream); 25 | loadMap(prop, map); 26 | } catch (IOException e) { 27 | } 28 | return new EnvContext(map); 29 | } 30 | 31 | 32 | private static void loadMap(Properties props, Map map) { 33 | @SuppressWarnings("rawtypes") 34 | Enumeration en = props.propertyNames(); 35 | while (en.hasMoreElements()) { 36 | String key = (String) en.nextElement(); 37 | String value = props.getProperty(key); 38 | map.put(key, value); 39 | } 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /smqtt-common/src/main/java/io/github/quickmsg/common/utils/TopicRegexUtils.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.common.utils; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public class TopicRegexUtils { 7 | 8 | public static final TopicRegexUtils instance = new TopicRegexUtils(); 9 | 10 | public static String regexTopic(String topic) { 11 | if (topic.startsWith("$")) { 12 | topic = "\\" + topic; 13 | } 14 | return topic 15 | .replaceAll("/", "\\\\/") 16 | .replaceAll("\\+", "[^/]+") 17 | .replaceAll("#", "(.+)") + "$"; 18 | } 19 | 20 | public boolean match(String sourcesTopic, String targetTopic) { 21 | if (sourcesTopic == null || "".equals(sourcesTopic) || targetTopic == null || "".equals(targetTopic)) { 22 | return false; 23 | } 24 | return sourcesTopic.matches(TopicRegexUtils.regexTopic(targetTopic)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /smqtt-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | smqtt-core 12 | smqtt-core 13 | 14 | 15 | io.github.quickmsg 16 | smqtt-common 17 | 1.1.7 18 | 19 | 20 | io.github.quickmsg 21 | smqtt-rule-dsl 22 | 1.1.7 23 | 24 | 25 | io.github.quickmsg 26 | smqtt-metric-influxdb 27 | 1.1.7 28 | 29 | 30 | io.github.quickmsg 31 | smqtt-metric-prometheus 32 | 1.1.7 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/auth/AuthManagerFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.auth; 2 | 3 | import io.github.quickmsg.common.auth.AuthManager; 4 | import io.github.quickmsg.common.config.AuthConfig; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class AuthManagerFactory { 10 | 11 | private final AuthConfig authConfig; 12 | 13 | public AuthManagerFactory(AuthConfig authConfig) { 14 | this.authConfig = authConfig; 15 | } 16 | 17 | public AuthManager getAuthManager() { 18 | if (authConfig == null) { 19 | return new NoneAuthManager(); 20 | } 21 | if (authConfig.getHttp() != null) { 22 | return new HttpAuthManager(authConfig); 23 | } else if (authConfig.getFile() != null) { 24 | return new FileAuthManager(authConfig); 25 | } else if (authConfig.getFixed() != null) { 26 | return new FixedAuthManager(authConfig); 27 | } else if (authConfig.getSql() != null) { 28 | return new SqlAuthManager(authConfig); 29 | } else { 30 | return new NoneAuthManager(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/auth/FileAuthManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.auth; 2 | 3 | import io.github.quickmsg.common.auth.AuthBean; 4 | import io.github.quickmsg.common.auth.AuthManager; 5 | import io.github.quickmsg.common.config.AuthConfig; 6 | import io.github.quickmsg.common.utils.CsvReader; 7 | 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Optional; 12 | 13 | /** 14 | * @author luxurong 15 | */ 16 | public class FileAuthManager implements AuthManager { 17 | 18 | private final AuthConfig authConfig; 19 | 20 | private Map authBeanMap = new HashMap<>(); 21 | 22 | public FileAuthManager(AuthConfig authConfig) { 23 | this.authConfig = authConfig; 24 | List> values = CsvReader.readCsvValues(authConfig.getFile()); 25 | for (List es : values) { 26 | AuthBean authBean = new AuthBean(); 27 | authBean.setClientId(es.get(0)); 28 | authBean.setUsername(es.get(1)); 29 | authBean.setPassword(es.get(2)); 30 | authBeanMap.put(authBean.getClientId(),authBean); 31 | } 32 | } 33 | 34 | @Override 35 | public Boolean auth(String userName, byte[] passwordInBytes, String clientIdentifier) { 36 | return Optional.ofNullable(authBeanMap.get(clientIdentifier)) 37 | .map(authBean -> authBean.getUsername().equals(userName) && authBean.getPassword().equals(new String(passwordInBytes))) 38 | .orElse(false); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/auth/FixedAuthManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.auth; 2 | 3 | import io.github.quickmsg.common.auth.AuthManager; 4 | import io.github.quickmsg.common.config.AuthConfig; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class FixedAuthManager implements AuthManager { 10 | 11 | private final AuthConfig authConfig; 12 | 13 | public FixedAuthManager(AuthConfig authConfig) { 14 | this.authConfig = authConfig; 15 | } 16 | 17 | @Override 18 | public Boolean auth(String userName, byte[] passwordInBytes, String clientIdentifier) { 19 | return authConfig.getFixed().getUsername().equals(userName) 20 | && authConfig.getFixed().getPassword().equals(new String(passwordInBytes)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/auth/NoneAuthManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.auth; 2 | 3 | import io.github.quickmsg.common.auth.AuthManager; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public class NoneAuthManager implements AuthManager { 9 | @Override 10 | public Boolean auth(String userName, byte[] passwordInBytes, String clientIdentifier) { 11 | return true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/cluster/InJvmClusterRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.cluster; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.message.ClusterMessage; 5 | import io.github.quickmsg.common.message.HeapMqttMessage; 6 | import io.github.quickmsg.common.cluster.ClusterNode; 7 | import io.github.quickmsg.common.cluster.ClusterRegistry; 8 | import io.github.quickmsg.common.enums.ClusterStatus; 9 | import reactor.core.publisher.Flux; 10 | import reactor.core.publisher.Mono; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | /** 16 | * @author luxurong 17 | */ 18 | public class InJvmClusterRegistry implements ClusterRegistry { 19 | 20 | 21 | @Override 22 | public void registry(BootstrapConfig.ClusterConfig c) { 23 | 24 | } 25 | 26 | @Override 27 | public Flux handlerClusterMessage() { 28 | return Flux.empty(); 29 | } 30 | 31 | @Override 32 | public Flux clusterEvent() { 33 | return Flux.empty(); 34 | } 35 | 36 | @Override 37 | public List getClusterNode() { 38 | return Collections.emptyList(); 39 | } 40 | 41 | @Override 42 | public Mono spreadMessage(ClusterMessage clusterMessage) { 43 | return Mono.empty(); 44 | } 45 | 46 | @Override 47 | public Mono shutdown() { 48 | return Mono.empty(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/AbstractHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http; 2 | 3 | import io.github.quickmsg.common.channel.MockMqttChannel; 4 | import io.github.quickmsg.common.context.ContextHolder; 5 | import io.github.quickmsg.common.message.SmqttMessage; 6 | import io.github.quickmsg.common.http.HttpActor; 7 | import io.github.quickmsg.core.DefaultTransport; 8 | import io.netty.handler.codec.mqtt.MqttPublishMessage; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public abstract class AbstractHttpActor implements HttpActor { 14 | 15 | /** 16 | * 发送mqtt消息 17 | * 18 | * @param mqttPublishMessage publish消息 19 | */ 20 | public void sendMqttMessage(MqttPublishMessage mqttPublishMessage) { 21 | ContextHolder 22 | .getReceiveContext() 23 | .getProtocolAdaptor() 24 | .chooseProtocol(MockMqttChannel.DEFAULT_MOCK_CHANNEL, 25 | new SmqttMessage<>(mqttPublishMessage,System.currentTimeMillis(),Boolean.FALSE), 26 | ContextHolder.getReceiveContext()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/HttpTransportFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http; 2 | 3 | import io.github.quickmsg.common.transport.Transport; 4 | import io.github.quickmsg.common.transport.TransportFactory; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class HttpTransportFactory implements TransportFactory { 10 | 11 | 12 | @Override 13 | public Transport createTransport(HttpConfiguration httpConfiguration) { 14 | return new HttpTransport(httpConfiguration, new HttpReceiver()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/AllowCorsHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Router; 5 | import io.github.quickmsg.common.config.Configuration; 6 | import io.github.quickmsg.common.enums.HttpType; 7 | import io.github.quickmsg.common.http.HttpActor; 8 | import org.reactivestreams.Publisher; 9 | import reactor.core.publisher.Mono; 10 | import reactor.netty.http.server.HttpServerRequest; 11 | import reactor.netty.http.server.HttpServerResponse; 12 | 13 | /** 14 | * @author luxurong 15 | */ 16 | 17 | @Router(value = "/**", type = HttpType.OPTIONS) 18 | @AllowCors 19 | public class AllowCorsHttpActor implements HttpActor { 20 | @Override 21 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 22 | return Mono.empty(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/ClusterActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.context.ContextHolder; 8 | import io.github.quickmsg.common.enums.HttpType; 9 | import io.github.quickmsg.common.http.HttpActor; 10 | import io.github.quickmsg.common.utils.JacksonUtil; 11 | import io.github.quickmsg.core.DefaultTransport; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.reactivestreams.Publisher; 14 | import reactor.core.publisher.Mono; 15 | import reactor.netty.http.server.HttpServerRequest; 16 | import reactor.netty.http.server.HttpServerResponse; 17 | 18 | /** 19 | * @author luxurong 20 | */ 21 | @Router(value = "/smqtt/cluster", type = HttpType.POST) 22 | @Slf4j 23 | @Header(key = "Content-Type", value = "application/json") 24 | @AllowCors 25 | public class ClusterActor implements HttpActor { 26 | 27 | 28 | @Override 29 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 30 | return request 31 | .receive() 32 | .then(response.sendString(Mono.just(JacksonUtil.bean2Json(ContextHolder.getReceiveContext().getClusterRegistry().getClusterNode()))).then()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/CounterHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.common.metric.MetricManagerHolder; 10 | import io.github.quickmsg.common.spi.DynamicLoader; 11 | import io.github.quickmsg.common.utils.JacksonUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.reactivestreams.Publisher; 14 | import reactor.core.publisher.Mono; 15 | import reactor.netty.http.server.HttpServerRequest; 16 | import reactor.netty.http.server.HttpServerResponse; 17 | 18 | /** 19 | * @author luxurong 20 | */ 21 | 22 | @Router(value = "/smqtt/monitor/counter", type = HttpType.GET) 23 | @Slf4j 24 | @Header(key = "Content-Type", value = "application/json") 25 | @AllowCors 26 | public class CounterHttpActor implements HttpActor { 27 | 28 | @Override 29 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 30 | return request 31 | .receive() 32 | .then(response 33 | .sendString(Mono.just(JacksonUtil.bean2Json(MetricManagerHolder.getMetricManager().getCounterMetric()))) 34 | .then()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/CpuHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.common.metric.MetricManagerHolder; 10 | import io.github.quickmsg.common.spi.DynamicLoader; 11 | import io.github.quickmsg.common.utils.JacksonUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.reactivestreams.Publisher; 14 | import reactor.core.publisher.Mono; 15 | import reactor.netty.http.server.HttpServerRequest; 16 | import reactor.netty.http.server.HttpServerResponse; 17 | 18 | /** 19 | * @author luxurong 20 | */ 21 | 22 | @Router(value = "/smqtt/monitor/cpu", type = HttpType.GET) 23 | @Slf4j 24 | @Header(key = "Content-Type", value = "application/json") 25 | @AllowCors 26 | public class CpuHttpActor implements HttpActor { 27 | 28 | 29 | @Override 30 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 31 | return request 32 | .receive() 33 | .then(response 34 | .sendString(Mono.just(JacksonUtil.bean2Json(MetricManagerHolder.getMetricManager().getCpuMetric()))) 35 | .then()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/EventHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.common.metric.MetricManagerHolder; 10 | import io.github.quickmsg.common.utils.JacksonUtil; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.reactivestreams.Publisher; 13 | import reactor.core.publisher.Mono; 14 | import reactor.netty.http.server.HttpServerRequest; 15 | import reactor.netty.http.server.HttpServerResponse; 16 | 17 | /** 18 | * @author luxurong 19 | */ 20 | 21 | @Router(value = "/smqtt/monitor/event", type = HttpType.GET) 22 | @Slf4j 23 | @Header(key = "Content-Type", value = "application/json") 24 | @AllowCors 25 | public class EventHttpActor implements HttpActor { 26 | 27 | 28 | @Override 29 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 30 | return request 31 | .receive() 32 | .then(response 33 | .sendString(Mono.just(JacksonUtil.bean2Json(MetricManagerHolder.getMetricManager().getEventMetric()))) 34 | .then()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/IsClusterActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Router; 5 | import io.github.quickmsg.common.config.Configuration; 6 | import io.github.quickmsg.common.context.ContextHolder; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.core.DefaultTransport; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.reactivestreams.Publisher; 12 | import reactor.core.publisher.Mono; 13 | import reactor.netty.http.server.HttpServerRequest; 14 | import reactor.netty.http.server.HttpServerResponse; 15 | 16 | /** 17 | * @author luxurong 18 | */ 19 | @Router(value = "/smqtt/is/cluster", type = HttpType.GET) 20 | @Slf4j 21 | @AllowCors 22 | public class IsClusterActor implements HttpActor { 23 | 24 | 25 | @Override 26 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 27 | return request 28 | .receive() 29 | .then(response.sendString(Mono.just(String.valueOf(ContextHolder.getReceiveContext().getConfiguration().getClusterConfig().isEnable()))).then()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/JvmHttpActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.common.metric.MetricManagerHolder; 10 | import io.github.quickmsg.common.spi.DynamicLoader; 11 | import io.github.quickmsg.common.utils.JacksonUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.reactivestreams.Publisher; 14 | import reactor.core.publisher.Mono; 15 | import reactor.netty.http.server.HttpServerRequest; 16 | import reactor.netty.http.server.HttpServerResponse; 17 | 18 | /** 19 | * @author luxurong 20 | */ 21 | 22 | @Router(value = "/smqtt/monitor/jvm", type = HttpType.GET) 23 | @Slf4j 24 | @Header(key = "Content-Type", value = "application/json") 25 | @AllowCors 26 | public class JvmHttpActor implements HttpActor { 27 | 28 | @Override 29 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 30 | return request 31 | .receive() 32 | .then(response 33 | .sendString(Mono.just(JacksonUtil.bean2Json(MetricManagerHolder.getMetricManager().getJvmMetric()))) 34 | .then()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/PrometheusActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.enums.HttpType; 8 | import io.github.quickmsg.common.http.HttpActor; 9 | import io.github.quickmsg.common.metric.MetricManagerHolder; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.reactivestreams.Publisher; 12 | import reactor.core.publisher.Mono; 13 | import reactor.netty.http.server.HttpServerRequest; 14 | import reactor.netty.http.server.HttpServerResponse; 15 | 16 | /** 17 | * 监控指标 18 | * 19 | * @author easy 20 | */ 21 | @Router(value = "/smqtt/meter", type = HttpType.GET) 22 | @Slf4j 23 | @Header(key = "Content-Type", value = "text/plain; version=0.0.4;charset=utf-8") 24 | @AllowCors 25 | public class PrometheusActor implements HttpActor { 26 | 27 | 28 | @Override 29 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration configuration) { 30 | return request 31 | .receive() 32 | .then(response 33 | .sendString(Mono.just(MetricManagerHolder.getMetricManager().scrape())) 34 | .then()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/SubscribeActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Header; 5 | import io.github.quickmsg.common.annotation.Router; 6 | import io.github.quickmsg.common.config.Configuration; 7 | import io.github.quickmsg.common.context.ContextHolder; 8 | import io.github.quickmsg.common.enums.HttpType; 9 | import io.github.quickmsg.common.http.HttpActor; 10 | import io.github.quickmsg.common.utils.JacksonUtil; 11 | import io.github.quickmsg.core.DefaultTransport; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.reactivestreams.Publisher; 14 | import reactor.core.publisher.Mono; 15 | import reactor.netty.http.server.HttpServerRequest; 16 | import reactor.netty.http.server.HttpServerResponse; 17 | 18 | /** 19 | * @author luxurong 20 | */ 21 | @Router(value = "/smqtt/subscribe", type = HttpType.POST) 22 | @Slf4j 23 | @Header(key = "Content-Type", value = "application/json") 24 | @AllowCors 25 | public class SubscribeActor implements HttpActor { 26 | 27 | @Override 28 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 29 | return request 30 | .receive() 31 | .then(response 32 | .sendString(Mono.just(JacksonUtil.bean2Json(ContextHolder.getReceiveContext().getTopicRegistry().getAllTopics()))) 33 | .then()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/resource/FaviconResourceActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors.resource; 2 | 3 | import io.github.quickmsg.common.annotation.AllowCors; 4 | import io.github.quickmsg.common.annotation.Router; 5 | import io.github.quickmsg.common.config.Configuration; 6 | import io.github.quickmsg.common.enums.HttpType; 7 | import io.github.quickmsg.common.http.HttpActor; 8 | import io.github.quickmsg.common.utils.ClassPathLoader; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.reactivestreams.Publisher; 11 | import reactor.netty.http.server.HttpServerRequest; 12 | import reactor.netty.http.server.HttpServerResponse; 13 | 14 | /** 15 | * @author luxurong 16 | */ 17 | @Router(type = HttpType.GET, value = "/favicon.ico",resource = true) 18 | @Slf4j 19 | @AllowCors 20 | public class FaviconResourceActor implements HttpActor { 21 | private final static String DEFAULT_STATIC_PATH = "/static/"; 22 | 23 | @Override 24 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 25 | String path = DEFAULT_STATIC_PATH + "favicon.ico"; 26 | return response.send(ClassPathLoader.readClassPathFile(path)).then(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/resource/IndexResourceActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors.resource; 2 | 3 | import io.github.quickmsg.common.annotation.Router; 4 | import io.github.quickmsg.common.config.Configuration; 5 | import io.github.quickmsg.common.enums.HttpType; 6 | import io.github.quickmsg.common.http.HttpActor; 7 | import io.github.quickmsg.common.utils.ClassPathLoader; 8 | import io.github.quickmsg.core.http.HttpConfiguration; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.reactivestreams.Publisher; 11 | import reactor.netty.http.server.HttpServerRequest; 12 | import reactor.netty.http.server.HttpServerResponse; 13 | 14 | /** 15 | * @author luxurong 16 | */ 17 | @Router(type = HttpType.GET, value = "/smqtt/admin",resource = true) 18 | @Slf4j 19 | public class IndexResourceActor implements HttpActor { 20 | 21 | private final static String DEFAULT_STATIC_PATH = "/static/"; 22 | 23 | @Override 24 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 25 | String path = DEFAULT_STATIC_PATH + "index.html"; 26 | return response.send(ClassPathLoader.readClassPathFile(path)).then(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/actors/resource/StaticResourceActor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.actors.resource; 2 | 3 | import io.github.quickmsg.common.annotation.Router; 4 | import io.github.quickmsg.common.config.Configuration; 5 | import io.github.quickmsg.common.enums.HttpType; 6 | import io.github.quickmsg.common.http.HttpActor; 7 | import io.github.quickmsg.common.utils.ClassPathLoader; 8 | import io.github.quickmsg.core.http.HttpConfiguration; 9 | import org.reactivestreams.Publisher; 10 | import reactor.netty.http.server.HttpServerRequest; 11 | import reactor.netty.http.server.HttpServerResponse; 12 | 13 | /** 14 | * @author luxurong 15 | */ 16 | @Router(type = HttpType.GET, value = "/static/**",resource = true) 17 | public class StaticResourceActor implements HttpActor { 18 | 19 | private final static String DEFAULT_STATIC_PATH = "/static/"; 20 | 21 | @Override 22 | public Publisher doRequest(HttpServerRequest request, HttpServerResponse response, Configuration httpConfiguration) { 23 | String path = DEFAULT_STATIC_PATH + request.path(); 24 | return response.send(ClassPathLoader.readClassPathFile(path)).then(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/model/LoginDo.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | @Data 9 | public class LoginDo { 10 | 11 | private String username; 12 | 13 | private String password; 14 | } 15 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/model/LoginVm.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | @Data 10 | public class LoginVm { 11 | 12 | @JsonProperty("access_token") 13 | private String accessToken; 14 | 15 | @JsonProperty("expires_in") 16 | private long expiresIn; 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/http/model/Msg.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.http.model; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 消息 9 | * 10 | * @author zhaopeng 11 | */ 12 | @Data 13 | @Builder 14 | @ToString 15 | public class Msg { 16 | /** 17 | * 成功 18 | */ 19 | private Boolean success; 20 | /** 21 | * 状态码 22 | */ 23 | private Integer code; 24 | /** 25 | * 消息 26 | */ 27 | private String msg; 28 | /** 29 | * 数据 30 | */ 31 | private T data; 32 | } 33 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/mqtt/MqttTransportFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.mqtt; 2 | 3 | import io.github.quickmsg.core.DefaultTransport; 4 | import io.github.quickmsg.common.transport.Transport; 5 | import io.github.quickmsg.common.transport.TransportFactory; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class MqttTransportFactory implements TransportFactory { 11 | 12 | @Override 13 | public Transport createTransport(MqttConfiguration config) { 14 | return new DefaultTransport(config ,new MqttReceiver()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/mqtt/traffic/CacheTrafficHandlerLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.mqtt.traffic; 2 | 3 | import io.github.quickmsg.common.channel.traffic.TrafficHandlerLoader; 4 | import io.netty.handler.traffic.AbstractTrafficShapingHandler; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class CacheTrafficHandlerLoader implements TrafficHandlerLoader { 10 | 11 | 12 | private final AbstractTrafficShapingHandler trafficShapingHandler; 13 | 14 | public CacheTrafficHandlerLoader(AbstractTrafficShapingHandler trafficShapingHandler) { 15 | this.trafficShapingHandler = trafficShapingHandler; 16 | } 17 | 18 | @Override 19 | public AbstractTrafficShapingHandler get() { 20 | return this.trafficShapingHandler; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/mqtt/traffic/LazyTrafficHandlerLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.mqtt.traffic; 2 | 3 | import io.github.quickmsg.common.channel.traffic.TrafficHandlerLoader; 4 | import io.netty.handler.traffic.AbstractTrafficShapingHandler; 5 | import io.netty.handler.traffic.ChannelTrafficShapingHandler; 6 | import io.netty.handler.traffic.GlobalChannelTrafficShapingHandler; 7 | 8 | import java.util.concurrent.ScheduledExecutorService; 9 | import java.util.function.Supplier; 10 | 11 | /** 12 | * @author luxurong 13 | */ 14 | public class LazyTrafficHandlerLoader implements TrafficHandlerLoader { 15 | 16 | private final Supplier shapingHandlerSupplier; 17 | 18 | public LazyTrafficHandlerLoader(Supplier shapingHandlerSupplier) { 19 | this.shapingHandlerSupplier = shapingHandlerSupplier; 20 | } 21 | 22 | @Override 23 | public AbstractTrafficShapingHandler get() { 24 | return this.shapingHandlerSupplier.get(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/protocol/ConnectAckProtocol.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.protocol; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.message.SmqttMessage; 5 | import io.github.quickmsg.common.protocol.Protocol; 6 | import io.netty.handler.codec.mqtt.MqttConnAckMessage; 7 | import io.netty.handler.codec.mqtt.MqttMessage; 8 | import io.netty.handler.codec.mqtt.MqttMessageType; 9 | import reactor.core.publisher.Mono; 10 | import reactor.util.context.ContextView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * @author luxurong 17 | */ 18 | public class ConnectAckProtocol implements Protocol { 19 | 20 | 21 | private static List MESSAGE_TYPE_LIST = new ArrayList<>(); 22 | 23 | static { 24 | MESSAGE_TYPE_LIST.add(MqttMessageType.CONNACK); 25 | } 26 | 27 | 28 | @Override 29 | public Mono parseProtocol(SmqttMessage smqttMessage, MqttChannel mqttChannel, ContextView contextView) { 30 | MqttMessage message = smqttMessage.getMessage(); 31 | return mqttChannel.cancelRetry(MqttMessageType.CONNECT,-1); 32 | } 33 | 34 | @Override 35 | public List getMqttMessageTypes() { 36 | return MESSAGE_TYPE_LIST; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/protocol/SubscribeAckProtocol.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.protocol; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.message.SmqttMessage; 5 | import io.github.quickmsg.common.protocol.Protocol; 6 | import io.netty.handler.codec.mqtt.MqttMessageType; 7 | import io.netty.handler.codec.mqtt.MqttPublishMessage; 8 | import io.netty.handler.codec.mqtt.MqttSubAckMessage; 9 | import reactor.core.publisher.Mono; 10 | import reactor.util.context.ContextView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * @author luxurong 17 | */ 18 | public class SubscribeAckProtocol implements Protocol { 19 | 20 | private static List MESSAGE_TYPE_LIST = new ArrayList<>(); 21 | 22 | 23 | static { 24 | MESSAGE_TYPE_LIST.add(MqttMessageType.SUBACK); 25 | } 26 | 27 | @Override 28 | public Mono parseProtocol(SmqttMessage smqttMessage, MqttChannel mqttChannel, ContextView contextView) { 29 | MqttSubAckMessage message = smqttMessage.getMessage(); 30 | return mqttChannel.cancelRetry(MqttMessageType.SUBSCRIBE,message.variableHeader().messageId()); 31 | } 32 | 33 | @Override 34 | public List getMqttMessageTypes() { 35 | return MESSAGE_TYPE_LIST; 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/protocol/UnSubscribeAckProtocol.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.protocol; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.message.SmqttMessage; 5 | import io.github.quickmsg.common.protocol.Protocol; 6 | import io.netty.handler.codec.mqtt.MqttMessageType; 7 | import io.netty.handler.codec.mqtt.MqttUnsubAckMessage; 8 | import reactor.core.publisher.Mono; 9 | import reactor.util.context.ContextView; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author luxurong 16 | */ 17 | public class UnSubscribeAckProtocol implements Protocol { 18 | 19 | private static List MESSAGE_TYPE_LIST = new ArrayList<>(); 20 | 21 | static { 22 | MESSAGE_TYPE_LIST.add(MqttMessageType.UNSUBACK); 23 | } 24 | 25 | @Override 26 | public Mono parseProtocol(SmqttMessage smqttMessage, MqttChannel mqttChannel, ContextView contextView) { 27 | MqttUnsubAckMessage message = smqttMessage.getMessage(); 28 | return mqttChannel.cancelRetry(MqttMessageType.UNSUBSCRIBE, message.variableHeader().messageId()); 29 | } 30 | 31 | @Override 32 | public List getMqttMessageTypes() { 33 | return MESSAGE_TYPE_LIST; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/topic/WildCarTopic.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.topic; 2 | 3 | /** 4 | * @author luxurong 5 | */ 6 | public enum WildCarTopic { 7 | 8 | /** 9 | * 单层 10 | */ 11 | ONE(), 12 | 13 | /** 14 | * 多层 15 | */ 16 | MORE() 17 | } 18 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/websocket/ByteBufToWebSocketFrameEncoder.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.websocket; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToMessageEncoder; 6 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public class ByteBufToWebSocketFrameEncoder extends MessageToMessageEncoder { 14 | 15 | 16 | @Override 17 | protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List out) throws Exception { 18 | if (byteBuf == null) { 19 | return; 20 | } 21 | BinaryWebSocketFrame result = new BinaryWebSocketFrame(); 22 | result.content().writeBytes(byteBuf); 23 | out.add(result); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/websocket/WebSocketFrameToByteBufDecoder.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.websocket; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToMessageDecoder; 6 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public class WebSocketFrameToByteBufDecoder extends MessageToMessageDecoder { 14 | 15 | @Override 16 | protected void decode(ChannelHandlerContext channelHandlerContext, BinaryWebSocketFrame wsFrame, List out) throws Exception { 17 | ByteBuf buf = wsFrame.content(); 18 | buf.retain(); 19 | out.add(buf); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smqtt-core/src/main/java/io/github/quickmsg/core/websocket/WebSocketMqttTransportFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.core.websocket; 2 | 3 | import io.github.quickmsg.common.transport.Transport; 4 | import io.github.quickmsg.common.transport.TransportFactory; 5 | import io.github.quickmsg.core.DefaultTransport; 6 | import io.github.quickmsg.core.mqtt.MqttConfiguration; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class WebSocketMqttTransportFactory implements TransportFactory { 12 | 13 | @Override 14 | public Transport createTransport(MqttConfiguration config) { 15 | return new DefaultTransport(config, new WebSocketMqttReceiver()); 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smqtt-core/src/main/resources/META-INF/services/io.github.quickmsg.common.protocol.Protocol: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.core.protocol.ConnectAckProtocol 2 | io.github.quickmsg.core.protocol.ConnectProtocol 3 | io.github.quickmsg.core.protocol.PublishAckProtocol 4 | io.github.quickmsg.core.protocol.PublishProtocol 5 | io.github.quickmsg.core.protocol.SubscribeAckProtocol 6 | io.github.quickmsg.core.protocol.SubscribeProtocol 7 | io.github.quickmsg.core.protocol.UnSubscribeAckProtocol 8 | io.github.quickmsg.core.protocol.UnSubscribeProtocol 9 | io.github.quickmsg.core.protocol.CommonProtocol -------------------------------------------------------------------------------- /smqtt-metric/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | 8 | 9 | smqtt 10 | io.github.quickmsg 11 | 1.1.7 12 | 13 | 14 | smqtt-metric 15 | 16 | pom 17 | 18 | 19 | 20 | smqtt-metric-influxdb 21 | smqtt-metric-prometheus 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-influxdb/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-metric 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | smqtt-metric-influxdb 13 | 14 | 15 | 16 | io.github.quickmsg 17 | smqtt-common 18 | 1.1.7 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-influxdb/src/main/java/io/github/quickmsg/metric/InfluxDbMetricFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.metric.MetricFactory; 5 | import io.github.quickmsg.common.metric.MetricManager; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class InfluxDbMetricFactory implements MetricFactory { 11 | 12 | private final MetricManager metricManager; 13 | 14 | public InfluxDbMetricFactory(BootstrapConfig.MeterConfig config) { 15 | this.metricManager = new InfluxDbMetricManager(config); 16 | } 17 | 18 | @Override 19 | public MetricManager getMetricManager() { 20 | return this.metricManager; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-influxdb/src/main/java/io/github/quickmsg/metric/InfluxDbMetricManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.metric.*; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class InfluxDbMetricManager implements MetricManager { 10 | 11 | private final BootstrapConfig.MeterConfig config; 12 | 13 | private final MetricBean metricBean; 14 | 15 | private final MetricRegistry metricRegistry; 16 | 17 | public InfluxDbMetricManager(BootstrapConfig.MeterConfig config) { 18 | this.config = config; 19 | this.metricBean = new InfluxDbMetricBean(this.config); 20 | this.metricRegistry = new InfluxDbMetricRegistry(createMetricRegistry(metricBean)); 21 | 22 | } 23 | 24 | 25 | 26 | @Override 27 | public MetricRegistry getMetricRegistry() { 28 | return this.metricRegistry; 29 | } 30 | 31 | @Override 32 | public MetricBean getMetricBean() { 33 | return this.metricBean; 34 | } 35 | 36 | @Override 37 | public BootstrapConfig.MeterConfig getMeterConfig() { 38 | return this.config; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-influxdb/src/main/java/io/github/quickmsg/metric/InfluxDbMetricRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.metric.AbstractMetricRegistry; 4 | import io.github.quickmsg.common.metric.MetricCounter; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class InfluxDbMetricRegistry extends AbstractMetricRegistry { 12 | 13 | 14 | public InfluxDbMetricRegistry(List counters) { 15 | super(counters); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-prometheus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-metric 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | smqtt-metric-prometheus 13 | 14 | 15 | 16 | io.micrometer 17 | micrometer-registry-prometheus 18 | 19 | 20 | io.github.quickmsg 21 | smqtt-common 22 | 1.1.7 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-prometheus/src/main/java/io/github/quickmsg/metric/PrometheusMetricFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.metric.MetricFactory; 5 | import io.github.quickmsg.common.metric.MetricManager; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class PrometheusMetricFactory implements MetricFactory { 11 | 12 | private final MetricManager metricManager; 13 | 14 | public PrometheusMetricFactory(BootstrapConfig.MeterConfig config) { 15 | this.metricManager = new PrometheusMetricManager(config); 16 | } 17 | 18 | @Override 19 | public MetricManager getMetricManager() { 20 | return this.metricManager; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-prometheus/src/main/java/io/github/quickmsg/metric/PrometheusMetricManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import io.github.quickmsg.common.metric.MetricBean; 5 | import io.github.quickmsg.common.metric.MetricManager; 6 | import io.github.quickmsg.common.metric.MetricRegistry; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class PrometheusMetricManager implements MetricManager { 12 | 13 | private final BootstrapConfig.MeterConfig config; 14 | 15 | private final MetricBean metricBean; 16 | 17 | private final MetricRegistry metricRegistry; 18 | 19 | public PrometheusMetricManager(BootstrapConfig.MeterConfig config) { 20 | this.config = config; 21 | this.metricBean = new PrometheusMetricBean(); 22 | this.metricRegistry = new PrometheusMetricRegistry(createMetricRegistry(metricBean)); 23 | } 24 | 25 | 26 | @Override 27 | public MetricRegistry getMetricRegistry() { 28 | return this.metricRegistry; 29 | } 30 | 31 | @Override 32 | public MetricBean getMetricBean() { 33 | return this.metricBean; 34 | } 35 | 36 | @Override 37 | public BootstrapConfig.MeterConfig getMeterConfig() { 38 | return this.config; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-metric/smqtt-metric-prometheus/src/main/java/io/github/quickmsg/metric/PrometheusMetricRegistry.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.metric; 2 | 3 | import io.github.quickmsg.common.metric.AbstractMetricRegistry; 4 | import io.github.quickmsg.common.metric.MetricCounter; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class PrometheusMetricRegistry extends AbstractMetricRegistry { 12 | 13 | protected PrometheusMetricRegistry(List metricCounters) { 14 | super(metricCounters); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /smqtt-persistent/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | smqtt 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | pom 12 | smqtt-persistent 13 | smqtt-persistent 14 | 15 | 16 | smqtt-persistent-db 17 | smqtt-persistent-redis 18 | 19 | 20 | 21 | 22 | 23 | org.apache.commons 24 | commons-lang3 25 | 3.12.0 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/DbConnectionHolder.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent; 2 | 3 | import io.github.quickmsg.persistent.config.HikariCPConnectionProvider; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.jooq.DSLContext; 6 | import org.jooq.impl.DSL; 7 | import reactor.core.publisher.Mono; 8 | 9 | import java.sql.Connection; 10 | import java.sql.SQLException; 11 | import java.util.Optional; 12 | 13 | /** 14 | * @author luxurong 15 | */ 16 | @Slf4j 17 | public class DbConnectionHolder { 18 | 19 | /** 20 | * 获取DSLContext 21 | * 22 | * @return {@link Mono} 23 | */ 24 | public static Mono getConnection() throws SQLException { 25 | Connection connection = HikariCPConnectionProvider.singleTon().getConnection(); 26 | return Optional.ofNullable(connection).map(Mono::just).orElse(Mono.empty()); 27 | } 28 | 29 | /** 30 | * 获取DSLContext 31 | * 32 | * @return {@link Mono} 33 | */ 34 | public static Mono getDslContext() throws SQLException { 35 | return getConnection().map(DSL::using); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/config/ConnectionProvider.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent.config; 2 | 3 | import java.sql.Connection; 4 | import java.util.Properties; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public interface ConnectionProvider { 10 | 11 | 12 | /** 13 | * 初始化 14 | * 15 | * @param properties 配置 16 | */ 17 | void init(Properties properties); 18 | 19 | /** 20 | * 获取链接 21 | * 22 | * @return {@link Connection} 23 | */ 24 | Connection getConnection(); 25 | 26 | 27 | /** 28 | * 关闭链接 29 | */ 30 | void shutdown(); 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/tables/DefaultCatalog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package io.github.quickmsg.persistent.tables; 5 | 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | import org.jooq.Schema; 11 | import org.jooq.impl.CatalogImpl; 12 | 13 | 14 | /** 15 | * This class is generated by jOOQ. 16 | */ 17 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 18 | public class DefaultCatalog extends CatalogImpl { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | 23 | public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog(); 24 | 25 | 26 | public final Smqtt SMQTT = Smqtt.SMQTT; 27 | 28 | 29 | private DefaultCatalog() { 30 | super(""); 31 | } 32 | 33 | @Override 34 | public final List getSchemas() { 35 | return Arrays.asList( 36 | Smqtt.SMQTT); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/tables/Indexes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package io.github.quickmsg.persistent.tables; 5 | 6 | 7 | import io.github.quickmsg.persistent.tables.tables.SmqttRetain; 8 | 9 | import org.jooq.Index; 10 | import org.jooq.OrderField; 11 | import org.jooq.impl.DSL; 12 | import org.jooq.impl.Internal; 13 | 14 | 15 | /** 16 | * A class modelling indexes of tables in smqtt. 17 | */ 18 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 19 | public class Indexes { 20 | 21 | // ------------------------------------------------------------------------- 22 | // INDEX definitions 23 | // ------------------------------------------------------------------------- 24 | 25 | public static final Index SMQTT_RETAIN_INDEX_TOPIC = Internal.createIndex(DSL.name("index_topic"), SmqttRetain.SMQTT_RETAIN, new OrderField[] { SmqttRetain.SMQTT_RETAIN.TOPIC }, false); 26 | } 27 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/tables/Keys.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package io.github.quickmsg.persistent.tables; 5 | 6 | 7 | import io.github.quickmsg.persistent.tables.tables.Databasechangeloglock; 8 | import io.github.quickmsg.persistent.tables.tables.records.DatabasechangeloglockRecord; 9 | 10 | import org.jooq.TableField; 11 | import org.jooq.UniqueKey; 12 | import org.jooq.impl.DSL; 13 | import org.jooq.impl.Internal; 14 | 15 | 16 | /** 17 | * A class modelling foreign key relationships and constraints of tables in 18 | * smqtt. 19 | */ 20 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 21 | public class Keys { 22 | 23 | // ------------------------------------------------------------------------- 24 | // UNIQUE and PRIMARY KEY definitions 25 | // ------------------------------------------------------------------------- 26 | 27 | public static final UniqueKey KEY_DATABASECHANGELOGLOCK_PRIMARY = Internal.createUniqueKey(Databasechangeloglock.DATABASECHANGELOGLOCK, DSL.name("KEY_databasechangeloglock_PRIMARY"), new TableField[] { Databasechangeloglock.DATABASECHANGELOGLOCK.ID }, true); 28 | } 29 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/java/io/github/quickmsg/persistent/tables/Tables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package io.github.quickmsg.persistent.tables; 5 | 6 | 7 | import io.github.quickmsg.persistent.tables.tables.Databasechangelog; 8 | import io.github.quickmsg.persistent.tables.tables.Databasechangeloglock; 9 | import io.github.quickmsg.persistent.tables.tables.SmqttRetain; 10 | import io.github.quickmsg.persistent.tables.tables.SmqttSession; 11 | 12 | 13 | /** 14 | * Convenience access to all tables in smqtt. 15 | */ 16 | @SuppressWarnings({ "all", "unchecked", "rawtypes" }) 17 | public class Tables { 18 | 19 | 20 | public static final Databasechangelog DATABASECHANGELOG = Databasechangelog.DATABASECHANGELOG; 21 | 22 | 23 | public static final Databasechangeloglock DATABASECHANGELOGLOCK = Databasechangeloglock.DATABASECHANGELOGLOCK; 24 | 25 | 26 | public static final SmqttRetain SMQTT_RETAIN = SmqttRetain.SMQTT_RETAIN; 27 | 28 | 29 | public static final SmqttSession SMQTT_SESSION = SmqttSession.SMQTT_SESSION; 30 | } 31 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-db/src/main/resources/META-INF/services/io.github.quickmsg.common.message.MessageRegistry: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.persistent.registry.DbMessageRegistry -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-persistent 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | smqtt-persistent-redis 13 | 1.1.7 14 | 15 | 16 | 3.15.6 17 | 18 | 19 | 20 | 21 | io.github.quickmsg 22 | smqtt-common 23 | 1.1.7 24 | compile 25 | 26 | 27 | 28 | org.redisson 29 | redisson 30 | ${redisson.version} 31 | 32 | 33 | 34 | org.apache.commons 35 | commons-lang3 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/src/main/java/io/github/quickmsg/persistent/factory/ClientFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent.factory; 2 | 3 | import io.github.quickmsg.persistent.strategy.ClientStrategy; 4 | import io.github.quickmsg.persistent.strategy.ClusterClientStrategy; 5 | import io.github.quickmsg.persistent.strategy.SentinelClientStrategy; 6 | import io.github.quickmsg.persistent.strategy.SingleClientStrategy; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * 客戶端公長類 13 | * 14 | * @author zhaopeng 15 | */ 16 | public class ClientFactory { 17 | 18 | public static Map strategyMap = new HashMap<>(); 19 | 20 | static { 21 | strategyMap.put("single", new SingleClientStrategy()); 22 | strategyMap.put("sentinel", new SentinelClientStrategy()); 23 | strategyMap.put("cluster", new ClusterClientStrategy()); 24 | } 25 | 26 | /** 27 | * 获取客户端策略 28 | * 29 | * @param key 30 | * @return {@link ClientStrategy} 31 | */ 32 | public static ClientStrategy getClientStrategy(String key) { 33 | return strategyMap.get(key); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/src/main/java/io/github/quickmsg/persistent/message/RetainMessageEntity.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent.message; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 保留消息实体 12 | * 13 | * @author zhaopeng 14 | */ 15 | @Data 16 | @Builder 17 | public class RetainMessageEntity implements Serializable { 18 | 19 | private static final long serialVersionUID = 1095608914696359394L; 20 | 21 | private String topic; 22 | 23 | private Integer qos; 24 | 25 | private byte[] body; 26 | 27 | private String userProperties; 28 | 29 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 30 | private Date createTime; 31 | 32 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 33 | private Date updateTime; 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/src/main/java/io/github/quickmsg/persistent/message/SessionMessageEntity.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent.message; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 会话消息实体 12 | * 13 | * @author zhaopeng 14 | */ 15 | @Data 16 | @Builder 17 | public class SessionMessageEntity implements Serializable { 18 | 19 | private static final long serialVersionUID = -2402958163229390974L; 20 | private String topic; 21 | 22 | private String clientId; 23 | 24 | private Integer qos; 25 | 26 | private Boolean retain; 27 | 28 | private String userProperties; 29 | 30 | private byte[] body; 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 32 | private Date createTime; 33 | } 34 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/src/main/java/io/github/quickmsg/persistent/strategy/ClientStrategy.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.persistent.strategy; 2 | 3 | import io.github.quickmsg.common.config.BootstrapConfig; 4 | import org.redisson.api.RedissonClient; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * redisson客户策略 10 | * 11 | * @author zhaopeng 12 | */ 13 | public interface ClientStrategy { 14 | 15 | 16 | /** 17 | * 获取redisson客户端 18 | * 19 | * @param redisConfig 20 | * @return {@link RedissonClient} 21 | */ 22 | RedissonClient getRedissonClient(BootstrapConfig.RedisConfig redisConfig); 23 | } 24 | -------------------------------------------------------------------------------- /smqtt-persistent/smqtt-persistent-redis/src/main/resources/META-INF/services/io.github.quickmsg.common.message.MessageRegistry: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.persistent.registry.RedisMessageRegistry -------------------------------------------------------------------------------- /smqtt-registry/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | smqtt 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | pom 12 | 13 | smqtt-registry-scube 14 | 15 | smqtt-registry 16 | smqtt-registry 17 | 18 | -------------------------------------------------------------------------------- /smqtt-registry/smqtt-registry-scube/src/main/java/io/github/quickmsg/registry/JacksonMessageCodec.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.registry; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import io.scalecube.cluster.transport.api.Message; 5 | import io.scalecube.cluster.transport.api.MessageCodec; 6 | 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public class JacksonMessageCodec implements MessageCodec { 14 | 15 | private final ObjectMapper delegate; 16 | 17 | public JacksonMessageCodec() { 18 | this(DefaultObjectMapper.OBJECT_MAPPER); 19 | } 20 | 21 | public JacksonMessageCodec(ObjectMapper delegate) { 22 | this.delegate = delegate; 23 | } 24 | 25 | @Override 26 | public Message deserialize(InputStream stream) throws Exception { 27 | return this.delegate.readValue(stream, Message.class); 28 | } 29 | 30 | @Override 31 | public void serialize(Message message, OutputStream stream) throws Exception { 32 | this.delegate.writeValue(stream, message); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-registry/smqtt-registry-scube/src/main/resources/META-INF/services/io.github.quickmsg.common.cluster.ClusterRegistry: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.registry.ScubeClusterRegistry -------------------------------------------------------------------------------- /smqtt-registry/smqtt-registry-scube/src/main/resources/META-INF/services/io.scalecube.cluster.transport.api.MessageCodec: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.registry.JacksonMessageCodec -------------------------------------------------------------------------------- /smqtt-registry/smqtt-registry-scube/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %level{length=1} %date{MMdd-HHmm:ss,SSS} %logger{1.} %message [%thread]%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /smqtt-rule/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | 8 | smqtt 9 | io.github.quickmsg 10 | 1.1.7 11 | 12 | smqtt-rule 13 | 14 | smqtt-rule-dsl 15 | smqtt-rule-engine 16 | smqtt-rule-source 17 | 18 | pom 19 | smqtt-rule 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-deploy-plugin 26 | 2.7 27 | 28 | true 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-dsl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-rule 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | smqtt-rule-dsl 13 | 14 | 15 | 16 | io.github.quickmsg 17 | smqtt-common 18 | 1.1.7 19 | provided 20 | 21 | 22 | smqtt-rule-engine 23 | io.github.quickmsg 24 | 1.1.7 25 | 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-deploy-plugin 32 | 2.7 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-dsl/src/main/java/io/github/quickmsg/dsl/RuleDsl.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.dsl; 2 | 3 | import io.github.quickmsg.common.enums.RuleType; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Data 12 | public class RuleDsl { 13 | 14 | private String name; 15 | 16 | private List rules; 17 | 18 | private RuleType ruleType; 19 | 20 | private String action; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-dsl/src/main/java/io/github/quickmsg/dsl/RuleDslExecutor.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.dsl; 2 | 3 | import io.github.quickmsg.common.channel.MqttChannel; 4 | import io.github.quickmsg.common.context.ReceiveContext; 5 | import io.github.quickmsg.common.message.HeapMqttMessage; 6 | import io.github.quickmsg.common.rule.DslExecutor; 7 | import io.github.quickmsg.rule.RuleChain; 8 | import reactor.core.publisher.Mono; 9 | import reactor.core.scheduler.Schedulers; 10 | 11 | /** 12 | * @author luxurong 13 | */ 14 | 15 | public class RuleDslExecutor implements DslExecutor { 16 | 17 | private final RuleChain ruleChain; 18 | 19 | public RuleDslExecutor(RuleChain ruleChain) { 20 | this.ruleChain = ruleChain; 21 | } 22 | 23 | @Override 24 | public void executeRule(Object... object) { 25 | Mono.deferContextual(ruleChain::executeRule) 26 | .contextWrite(context -> context 27 | .put(MqttChannel.class, object[0]) 28 | .put(HeapMqttMessage.class, object[1]) 29 | .put(ReceiveContext.class, object[2])) 30 | .subscribeOn(Schedulers.parallel()) 31 | .subscribe(); 32 | } 33 | 34 | 35 | @Override 36 | public Boolean isExecute() { 37 | return ruleChain.getRuleNodeList().size() > 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-dsl/src/main/java/io/github/quickmsg/dsl/RuleDslParser.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.dsl; 2 | 3 | import io.github.quickmsg.common.rule.RuleChainDefinition; 4 | import io.github.quickmsg.rule.RuleChain; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | public class RuleDslParser { 12 | 13 | private RuleChain ruleChain = RuleChain.INSTANCE; 14 | 15 | 16 | private final List ruleChainDefinitions; 17 | 18 | public RuleDslParser(List ruleChainDefinitions) { 19 | this.ruleChainDefinitions = ruleChainDefinitions; 20 | } 21 | 22 | public RuleDslExecutor parseRule() { 23 | if (ruleChainDefinitions != null && ruleChainDefinitions.size() > 0) { 24 | ruleChainDefinitions.stream().map(RuleChainDefinition::getChain).forEach(ruleChain::addRules); 25 | } 26 | return new RuleDslExecutor(ruleChain); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/RuleNode.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule; 2 | 3 | import reactor.util.context.ContextView; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public interface RuleNode extends RuleExecute { 11 | 12 | /*** 13 | * 获取下一个RuleNode 14 | * @return {@link RuleNode} 15 | */ 16 | RuleNode getNextRuleNode(); 17 | 18 | 19 | /*** 20 | * 设置下一个RuleNode 21 | * @param ruleNode {@link RuleNode} 22 | */ 23 | void setNextRuleNode(RuleNode ruleNode); 24 | 25 | 26 | /** 27 | * 执行下个Node 28 | * 29 | * @param context {@link ContextView} 30 | */ 31 | default void executeNext(ContextView context) { 32 | Optional.ofNullable(getNextRuleNode()) 33 | .ifPresent(ruleNode -> ruleNode.execute(context)); 34 | } 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/node/EmptyNode.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule.node; 2 | 3 | import io.github.quickmsg.rule.RuleNode; 4 | import reactor.util.context.ContextView; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public class EmptyNode implements RuleNode { 10 | 11 | 12 | @Override 13 | public RuleNode getNextRuleNode() { 14 | return null; 15 | } 16 | 17 | @Override 18 | public void setNextRuleNode(RuleNode ruleNode) { 19 | 20 | } 21 | 22 | @Override 23 | public void execute(ContextView contextView) { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/node/PredicateRuleNode.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule.node; 2 | 3 | import io.github.quickmsg.common.message.HeapMqttMessage; 4 | import io.github.quickmsg.rule.RuleNode; 5 | import reactor.util.context.ContextView; 6 | 7 | /** 8 | * @author luxurong 9 | */ 10 | public class PredicateRuleNode implements RuleNode { 11 | 12 | private final String script; 13 | 14 | private RuleNode ruleNode; 15 | 16 | 17 | public PredicateRuleNode(String script) { 18 | this.script = script; 19 | } 20 | 21 | @Override 22 | public RuleNode getNextRuleNode() { 23 | return this.ruleNode; 24 | } 25 | 26 | 27 | @Override 28 | public void setNextRuleNode(RuleNode ruleNode) { 29 | this.ruleNode = ruleNode; 30 | } 31 | 32 | @Override 33 | 34 | public void execute(ContextView contextView) { 35 | if ((Boolean) triggerScript(script, context -> { 36 | HeapMqttMessage mqttMessage = contextView.get(HeapMqttMessage.class); 37 | mqttMessage.getKeyMap().forEach(context::set); 38 | })) { 39 | executeNext(contextView); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/source/SourceFactory.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule.source; 2 | 3 | import io.github.quickmsg.common.rule.source.Source; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public interface SourceFactory { 9 | 10 | SourceLoader instance(Source source); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/source/SourceLoader.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule.source; 2 | 3 | import io.github.quickmsg.common.rule.source.Source; 4 | 5 | /** 6 | * @author luxurong 7 | */ 8 | public class SourceLoader { 9 | 10 | private final Source source; 11 | 12 | public SourceLoader(Source source) { 13 | this.source = source; 14 | } 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/java/io/github/quickmsg/rule/source/SourceManager.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.rule.source; 2 | 3 | import io.github.quickmsg.common.rule.source.Source; 4 | import io.github.quickmsg.common.rule.source.SourceDefinition; 5 | import io.github.quickmsg.common.rule.source.SourceBean; 6 | 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * @author luxurong 12 | */ 13 | public class SourceManager { 14 | 15 | private static final Map CACHE_BEANS = new ConcurrentHashMap<>(); 16 | 17 | 18 | public static SourceBean getSourceBean(Source source){ 19 | return CACHE_BEANS.get(source); 20 | } 21 | 22 | public static void loadSource(SourceDefinition sourceDefinition){ 23 | SourceBean.SOURCE_BEAN_LIST.forEach(sourceBean -> { 24 | if (sourceBean.support(sourceDefinition.getSource())) { 25 | if (sourceBean.bootstrap(sourceDefinition.getSourceAttributes())) { 26 | CACHE_BEANS.put(sourceDefinition.getSource(), sourceBean); 27 | } 28 | } 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-engine/src/main/resources/META-INF/services/io.github.quickmsg.common.rule.source.SourceBean: -------------------------------------------------------------------------------- 1 | io.github.quickmsg.source.mqtt.KafkaSourceBean 2 | io.github.quickmsg.source.rocketmq.RocketmqSourceBean 3 | io.github.quickmsg.source.rabbitmq.RabbitmqSourceBean 4 | io.github.quickmsg.http.HttpSourceBean 5 | io.github.quickmsg.source.db.DbSourceBean 6 | io.github.quickmsg.source.mqtt.MqttSourceBean -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | pom 7 | 8 | 9 | smqtt-rule 10 | io.github.quickmsg 11 | 1.1.7 12 | 13 | 14 | smqtt-rule-source 15 | smqtt-rule-source 16 | 17 | 18 | smqtt-rule-source-kafka 19 | smqtt-rule-source-http 20 | smqtt-rule-source-rocketmq 21 | smqtt-rule-source-rabbitmq 22 | smqtt-rule-source-db 23 | smqtt-rule-source-mqtt 24 | 25 | 26 | 27 | 28 | junit 29 | junit 30 | 4.11 31 | test 32 | 33 | 34 | io.github.quickmsg 35 | smqtt-common 36 | 1.1.7 37 | provided 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-db/src/main/java/io/github/quickmsg/source/db/config/ConnectionProvider.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.source.db.config; 2 | 3 | import java.sql.Connection; 4 | import java.util.Properties; 5 | 6 | /** 7 | * @author luxurong 8 | */ 9 | public interface ConnectionProvider { 10 | 11 | 12 | /** 13 | * 初始化 14 | * 15 | * @param properties 配置 16 | */ 17 | void init(Properties properties); 18 | 19 | /** 20 | * 获取链接 21 | * 22 | * @return {@link Connection} 23 | */ 24 | Connection getConnection(); 25 | 26 | 27 | /** 28 | * 关闭链接 29 | */ 30 | void shutdown(); 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-http/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | io.github.quickmsg 8 | smqtt-rule-source-http 9 | 1.1.7 10 | 11 | smqtt-rule-source-http 12 | 13 | https://github.com/quickmsg/smqtt 14 | 15 | 16 | smqtt-rule-source 17 | io.github.quickmsg 18 | 1.1.7 19 | 20 | 21 | 22 | 23 | io.github.quickmsg 24 | smqtt-common 25 | 1.1.7 26 | provided 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-http/src/main/java/io/github/quickmsg/http/HttpParam.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.http; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Data 12 | public class HttpParam { 13 | 14 | private String url; 15 | 16 | private Map additions; 17 | 18 | private Map headers; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-kafka/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-rule-source 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | smqtt-rule-source-kafka 13 | 1.1.7 14 | 15 | https://github.com/quickmsg/smqtt 16 | 17 | 18 | 19 | 20 | org.apache.kafka 21 | kafka-clients 22 | 2.8.0 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-rabbitmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-rule-source 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | io.github.quickmsg 13 | smqtt-rule-source-rabbitmq 14 | 1.1.7 15 | 16 | 17 | 18 | com.rabbitmq 19 | amqp-client 20 | 3.6.5 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /smqtt-rule/smqtt-rule-source/smqtt-rule-source-rocketmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | smqtt-rule-source 7 | io.github.quickmsg 8 | 1.1.7 9 | 10 | 4.0.0 11 | 12 | io.github.quickmsg 13 | smqtt-rule-source-rocketmq 14 | 1.1.7 15 | 16 | 17 | 18 | org.apache.rocketmq 19 | rocketmq-client 20 | 4.9.1 21 | 22 | 23 | netty-all 24 | io.netty 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /smqtt-spring-boot-starter/src/main/java/io/github/quickmsg/starter/EnableMqttServer.java: -------------------------------------------------------------------------------- 1 | package io.github.quickmsg.starter; 2 | 3 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 4 | import org.springframework.context.annotation.Import; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * @author luxurong 10 | */ 11 | @Target(ElementType.TYPE) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Import(AutoMqttConfiguration.class) 14 | @Documented 15 | @EnableAutoConfiguration 16 | public @interface EnableMqttServer { 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smqtt-ui/.env: -------------------------------------------------------------------------------- 1 | VUE_APP_PUBLIC_PATH=/ 2 | VUE_APP_NAME=SMQTT 3 | VUE_APP_ROUTES_KEY=admin.routes 4 | VUE_APP_PERMISSIONS_KEY=admin.permissions 5 | VUE_APP_ROLES_KEY=admin.roles 6 | VUE_APP_USER_KEY=admin.user 7 | VUE_APP_SETTING_KEY=admin.setting 8 | VUE_APP_TBAS_KEY=admin.tabs 9 | VUE_APP_TBAS_TITLES_KEY=admin.tabs.titles 10 | VUE_APP_API_BASE_URL=http://localhost:60000 11 | -------------------------------------------------------------------------------- /smqtt-ui/.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_API_BASE_URL=http://localhost:60000 2 | -------------------------------------------------------------------------------- /smqtt-ui/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | admindb/ 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | /test/unit/coverage/ 9 | /test/e2e/reports/ 10 | selenium-debug.log 11 | 12 | # Editor directories and files 13 | .idea 14 | .vscode 15 | *.suo 16 | *.ntvs* 17 | *.njsproj 18 | *.sln 19 | package-lock.json 20 | .env.production.local 21 | -------------------------------------------------------------------------------- /smqtt-ui/README.md: -------------------------------------------------------------------------------- 1 | # smqtt-ui -------------------------------------------------------------------------------- /smqtt-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) 2 | 3 | const plugins = [] 4 | if (IS_PROD) { 5 | plugins.push('transform-remove-console') 6 | } 7 | 8 | module.exports = { 9 | presets: [ 10 | '@vue/cli-plugin-babel/preset' 11 | ], 12 | plugins 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-ui/mvn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/mvn -------------------------------------------------------------------------------- /smqtt-ui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/public/favicon.ico -------------------------------------------------------------------------------- /smqtt-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= process.env.VUE_APP_NAME %> 9 | 10 | <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %> 11 | 12 | <% } %> 13 | 14 | 15 | 18 |
19 |
20 |
21 | 22 | <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %> 23 | 24 | <% } %> 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/cluster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/cluster.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/cpu.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/csys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/csys.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/idle.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/iowait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/iowait.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/jvm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/jvm.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/logo.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/path.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/starttime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/starttime.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/threadcount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/threadcount.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/user.png -------------------------------------------------------------------------------- /smqtt-ui/src/assets/img/version.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quickmsg/smqtt/90c80b0c1cbd2caffe9e6028e7683b0a20a5b850/smqtt-ui/src/assets/img/version.png -------------------------------------------------------------------------------- /smqtt-ui/src/bootstrap.js: -------------------------------------------------------------------------------- 1 | import {loadRoutes, loadGuards, setAppOptions} from '@/utils/routerUtil' 2 | import {loadInterceptors} from '@/utils/request' 3 | import guards from '@/router/guards' 4 | import interceptors from '@/utils/axios-interceptors' 5 | 6 | /** 7 | * 启动引导方法 8 | * 应用启动时需要执行的操作放在这里 9 | * @param router 应用的路由实例 10 | * @param store 应用的 vuex.store 实例 11 | * @param i18n 应用的 vue-i18n 实例 12 | * @param i18n 应用的 message 实例 13 | */ 14 | function bootstrap({router, store, i18n, message}) { 15 | // 设置应用配置 16 | setAppOptions({router, store, i18n}) 17 | // 加载 axios 拦截器 18 | loadInterceptors(interceptors, {router, store, i18n, message}) 19 | // 加载路由 20 | loadRoutes() 21 | // 加载路由守卫 22 | loadGuards(guards, {router, store, i18n, message}) 23 | } 24 | 25 | export default bootstrap 26 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import ColorCheckbox from '@/components/checkbox/ColorCheckbox' 2 | import ImgCheckbox from '@/components/checkbox/ImgCheckbox' 3 | 4 | export { 5 | ColorCheckbox, 6 | ImgCheckbox 7 | } 8 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/exception/typeConfig.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | 403: { 3 | img: 'https://gw.alipayobjects.com/zos/rmsportal/wZcnGqRDyhPOEYFcZDnb.svg', 4 | title: '403', 5 | desc: '抱歉,你无权访问该页面' 6 | }, 7 | 404: { 8 | img: 'https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg', 9 | title: '404', 10 | desc: '抱歉,你访问的页面不存在或仍在开发中' 11 | }, 12 | 500: { 13 | img: 'https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg', 14 | title: '500', 15 | desc: '抱歉,服务器出错了' 16 | } 17 | } 18 | 19 | export default config 20 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/menu/SideMenu.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 53 | 54 | 57 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/menu/index.less: -------------------------------------------------------------------------------- 1 | .shadow{ 2 | box-shadow: 2px 0 6px rgba(0, 21, 41, .35); 3 | } 4 | .side-menu{ 5 | min-height: 100vh; 6 | overflow-y: auto; 7 | z-index: 10; 8 | .logo{ 9 | height: 64px; 10 | position: relative; 11 | line-height: 64px; 12 | padding-left: 24px; 13 | -webkit-transition: all .3s; 14 | transition: all .3s; 15 | overflow: hidden; 16 | background-color: @layout-trigger-background; 17 | &.light{ 18 | background-color: #fff; 19 | h1{ 20 | color: @primary-color; 21 | } 22 | } 23 | h1{ 24 | color: @menu-dark-highlight-color; 25 | font-size: 20px; 26 | margin: 0 0 0 12px; 27 | display: inline-block; 28 | vertical-align: middle; 29 | } 30 | img{ 31 | width: 32px; 32 | vertical-align: middle; 33 | } 34 | } 35 | } 36 | .menu{ 37 | padding: 16px 0; 38 | } 39 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/page/header/index.less: -------------------------------------------------------------------------------- 1 | .page-header{ 2 | background: @base-bg-color; 3 | padding: 16px 24px; 4 | &.head.fixed{ 5 | margin: auto; 6 | max-width: 1400px; 7 | } 8 | .page-header-wide{ 9 | .breadcrumb{ 10 | margin-bottom: 20px; 11 | } 12 | .detail{ 13 | display: flex; 14 | .row { 15 | display: flex; 16 | flex-wrap: wrap; 17 | justify-content: space-between; 18 | } 19 | .avatar { 20 | margin:0 24px 0 0; 21 | } 22 | .main{ 23 | width: 100%; 24 | .title{ 25 | font-size: 20px; 26 | color: @title-color; 27 | margin-bottom: 16px; 28 | } 29 | .content{ 30 | display: flex; 31 | flex-wrap: wrap; 32 | color: @text-color-second; 33 | } 34 | .extra{ 35 | display: flex; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/setting/SettingItem.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | 15 | 26 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/table/advance/ActionSize.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 39 | 40 | -------------------------------------------------------------------------------- /smqtt-ui/src/components/table/advance/index.js: -------------------------------------------------------------------------------- 1 | import AdvanceTable from './AdvanceTable' 2 | export default AdvanceTable -------------------------------------------------------------------------------- /smqtt-ui/src/components/table/api/ApiTable.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 46 | 47 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/config.js: -------------------------------------------------------------------------------- 1 | // 自定义配置,参考 ./default/setting.config.js,需要自定义的属性在这里配置即可 2 | module.exports = { 3 | theme: { 4 | color: '#1890ff', 5 | mode: 'night', 6 | }, 7 | multiPage: true, 8 | hideSetting: true, 9 | animate: { 10 | name: 'lightSpeed', 11 | direction: 'left' 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/default/admin.config.js: -------------------------------------------------------------------------------- 1 | // admin 配置 2 | const ADMIN = { 3 | palettes: ['#f5222d', '#fa541c', '#fadb14', '#3eaf7c', '#13c2c2', '#1890ff', '#722ed1', '#eb2f96'], 4 | animates: require('./animate.config').preset, 5 | theme: { 6 | mode: { 7 | DARK: 'dark', 8 | LIGHT: 'light', 9 | NIGHT: 'night' 10 | } 11 | }, 12 | layout: { 13 | SIDE: 'side', 14 | HEAD: 'head' 15 | } 16 | } 17 | 18 | module.exports = ADMIN 19 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/default/animate.config.js: -------------------------------------------------------------------------------- 1 | const direct_s = ['left', 'right'] 2 | const direct_1 = ['left', 'right', 'down', 'up'] 3 | const direct_1_b = ['downBig', 'upBig', 'leftBig', 'rightBig'] 4 | const direct_2 = ['topLeft', 'bottomRight', 'topRight', 'bottomLeft'] 5 | const direct_3 = ['downLeft', 'upRight', 'downRight', 'upLeft'] 6 | 7 | // animate.css 配置 8 | const ANIMATE = { 9 | preset: [ //预设动画配置 10 | {name: 'back', alias: '渐近', directions: direct_1}, 11 | {name: 'bounce', alias: '弹跳', directions: direct_1.concat('default')}, 12 | {name: 'fade', alias: '淡化', directions: direct_1.concat(direct_1_b).concat(direct_2).concat('default')}, 13 | {name: 'flip', alias: '翻转', directions: ['x', 'y']}, 14 | {name: 'lightSpeed', alias: '光速', directions: direct_s}, 15 | {name: 'rotate', alias: '旋转', directions: direct_3.concat('default')}, 16 | {name: 'roll', alias: '翻滚', directions: ['default']}, 17 | {name: 'zoom', alias: '缩放', directions: direct_1.concat('default')}, 18 | {name: 'slide', alias: '滑动', directions: direct_1}, 19 | ] 20 | } 21 | module.exports = ANIMATE 22 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/default/index.js: -------------------------------------------------------------------------------- 1 | const ANTD = require('./antd.config') 2 | const ADMIN = require('./admin.config') 3 | const ANIMATE = require('./animate.config') 4 | const setting = require('./setting.config') 5 | 6 | module.exports = {ANTD, ADMIN, ANIMATE, setting} 7 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/index.js: -------------------------------------------------------------------------------- 1 | const deepMerge = require('deepmerge') 2 | const _config = require('./config') 3 | const {setting} = require('./default') 4 | const config = deepMerge(setting, _config) 5 | 6 | module.exports = config 7 | -------------------------------------------------------------------------------- /smqtt-ui/src/config/replacer/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * webpack-theme-color-replacer 配置 3 | * webpack-theme-color-replacer 是一个高效的主题色替换插件,可以实现系统运行时动态切换主题功能。 4 | * 但有些情景下,我们需要为 webpack-theme-color-replacer 配置一些规则,以达到我们的个性化需求的目的 5 | * 6 | * @cssResolve: css处理规则,在 webpack-theme-color-replacer 提取 需要替换主题色的 css 后,应用此规则。一般在 7 | * webpack-theme-color-replacer 默认规则无法达到我们的要求时使用。 8 | */ 9 | const cssResolve = require('./resolve.config') 10 | module.exports = {cssResolve} 11 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/BlankView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/CommonLayout.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 43 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/PageView.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 45 | 46 | 56 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/footer/PageFooter.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 46 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/header/HeaderAvatar.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 42 | 43 | 61 | -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/tabs/i18n.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | messages: { 3 | CN: { 4 | closeLeft: '关闭左侧', 5 | closeRight: '关闭右侧', 6 | closeOthers: '关闭其它', 7 | refresh: '刷新页面', 8 | warn: '这是最后一页,不能再关闭了', 9 | }, 10 | HK: { 11 | closeLeft: '關閉左側', 12 | closeRight: '關閉右側', 13 | closeOthers: '關閉其它', 14 | refresh: '刷新頁面', 15 | warn: '這是最後一頁,不能再關閉了', 16 | }, 17 | US: { 18 | closeLeft: 'close left', 19 | closeRight: 'close right', 20 | closeOthers: 'close others', 21 | refresh: 'refresh the page', 22 | warn: 'This is the last page, you can\'t close it', 23 | }, 24 | } 25 | } -------------------------------------------------------------------------------- /smqtt-ui/src/layouts/tabs/index.js: -------------------------------------------------------------------------------- 1 | import TabsView from './TabsView' 2 | export default TabsView 3 | -------------------------------------------------------------------------------- /smqtt-ui/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import {initRouter} from './router' 4 | import './theme/index.less' 5 | import Antd from 'ant-design-vue' 6 | import '@/mock' 7 | import store from './store' 8 | import 'animate.css/source/animate.css' 9 | import Plugins from '@/plugins' 10 | import {initI18n} from '@/utils/i18n' 11 | import bootstrap from '@/bootstrap' 12 | import 'moment/locale/zh-cn' 13 | 14 | const router = initRouter(store.state.setting.asyncRoutes) 15 | const i18n = initI18n('CN', 'US') 16 | 17 | Vue.use(Antd) 18 | Vue.config.productionTip = false 19 | Vue.use(Plugins) 20 | 21 | bootstrap({router, store, i18n, message: Vue.prototype.$message}) 22 | 23 | new Vue({ 24 | router, 25 | store, 26 | i18n, 27 | render: h => h(App), 28 | }).$mount('#app') 29 | -------------------------------------------------------------------------------- /smqtt-ui/src/mock/common/activityData.js: -------------------------------------------------------------------------------- 1 | import {users, groups} from './index' 2 | 3 | const events = [ 4 | { 5 | type: 0, 6 | event: '八月迭代' 7 | }, 8 | { 9 | type: 1, 10 | event: '留言' 11 | }, 12 | { 13 | type: 2, 14 | event: '项目进展' 15 | } 16 | ] 17 | 18 | const activities = users.map((user, index) => { 19 | return { 20 | user: Object.assign({}, user, {group: groups[user.groupId]}), 21 | activity: events[index % events.length], 22 | template: '' 23 | } 24 | }) 25 | 26 | const templates = [ 27 | (user, activity) => { return `${user.name} 在 ${user.group} 新建项目 ${activity.event}` }, 28 | (user, activity) => { return `${user.name} 在 ${user.group} 发布了 ${activity.event}` }, 29 | (user, activity) => { return `${user.name} 将 ${activity.event} 更新至已发布状态` } 30 | ] 31 | 32 | export {activities, templates} 33 | -------------------------------------------------------------------------------- /smqtt-ui/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs' 2 | import '@/mock/user/current' 3 | 4 | // 设置全局延时 5 | Mock.setup({ 6 | timeout: '200-400' 7 | }) 8 | -------------------------------------------------------------------------------- /smqtt-ui/src/mock/user/current.js: -------------------------------------------------------------------------------- 1 | import Mock from 'mockjs' 2 | import '@/mock/extend' 3 | 4 | const welcome = Mock.mock({ 5 | timeFix: '@TIMEFIX', 6 | message: '@WELCOME' 7 | }) 8 | 9 | Mock.mock('/user/welcome', 'get', () => { 10 | return welcome 11 | }) 12 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/components/TaskCard.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 33 | 34 | 51 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/components/table/index.js: -------------------------------------------------------------------------------- 1 | import Table from './Table' 2 | export default Table -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/acl/index.js: -------------------------------------------------------------------------------- 1 | import Console from "./Acl"; 2 | export default Console 3 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/clusters/Clusters.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/clusters/index.js: -------------------------------------------------------------------------------- 1 | import Clusters from "./Clusters"; 2 | export default Clusters -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/connections/index.js: -------------------------------------------------------------------------------- 1 | import Connections from "./Connections"; 2 | export default Connections -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/console/index.js: -------------------------------------------------------------------------------- 1 | import Console from "./Console"; 2 | export default Console -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/publish/index.js: -------------------------------------------------------------------------------- 1 | import Console from "./Publish"; 2 | export default Console -------------------------------------------------------------------------------- /smqtt-ui/src/pages/dashboard/subscribes/index.js: -------------------------------------------------------------------------------- 1 | import Subscribes from "./Subscribes"; 2 | export default Subscribes -------------------------------------------------------------------------------- /smqtt-ui/src/pages/exception/403.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/exception/404.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/exception/500.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/login/index.js: -------------------------------------------------------------------------------- 1 | import Login from './Login' 2 | export default Login 3 | -------------------------------------------------------------------------------- /smqtt-ui/src/pages/rule/index.js: -------------------------------------------------------------------------------- 1 | import RuleEditor from './RuleEditor' 2 | export default RuleEditor 3 | -------------------------------------------------------------------------------- /smqtt-ui/src/plugins/i18n-extend.js: -------------------------------------------------------------------------------- 1 | // 语句模式 2 | const MODE = { 3 | STATEMENTS: 's', //语句模式 4 | PHRASAL: 'p', //词组模式 5 | } 6 | 7 | const VueI18nPlugin = { 8 | install: function (Vue) { 9 | Vue.mixin({ 10 | methods: { 11 | $ta(syntaxKey, mode) { 12 | let _mode = mode || MODE.STATEMENTS 13 | let keys = syntaxKey.split('|') 14 | let _this = this 15 | let locale = this.$i18n.locale 16 | let message = '' 17 | let splitter = locale == 'US' ? ' ' : '' 18 | // 拼接 message 19 | keys.forEach(key => { 20 | message += _this.$t(key) + splitter 21 | }) 22 | // 英文环境语句模式下,转换单词大小写 23 | if (keys.length > 0 && _mode == MODE.STATEMENTS && locale == 'US') { 24 | message = message.charAt(0).toUpperCase() + message.toLowerCase().substring(1) 25 | } 26 | return message 27 | } 28 | } 29 | }) 30 | } 31 | } 32 | export default VueI18nPlugin 33 | -------------------------------------------------------------------------------- /smqtt-ui/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | import VueI18nPlugin from './i18n-extend' 2 | import AuthorityPlugin from './authority-plugin' 3 | import TabsPagePlugin from './tabs-page-plugin' 4 | 5 | const Plugins = { 6 | install: function (Vue) { 7 | Vue.use(VueI18nPlugin) 8 | Vue.use(AuthorityPlugin) 9 | Vue.use(TabsPagePlugin) 10 | } 11 | } 12 | export default Plugins 13 | -------------------------------------------------------------------------------- /smqtt-ui/src/plugins/tabs-page-plugin.js: -------------------------------------------------------------------------------- 1 | const TabsPagePlugin = { 2 | install(Vue) { 3 | Vue.mixin({ 4 | methods: { 5 | $closePage(closeRoute, nextRoute) { 6 | const event = new CustomEvent('page:close', {detail:{closeRoute, nextRoute}}) 7 | window.dispatchEvent(event) 8 | }, 9 | $refreshPage(route) { 10 | const path = typeof route === 'object' ? route.path : route 11 | const event = new CustomEvent('page:refresh', {detail:{pageKey: path}}) 12 | window.dispatchEvent(event) 13 | }, 14 | $openPage(route, title) { 15 | this.$setPageTitle(route, title) 16 | this.$router.push(route) 17 | }, 18 | $setPageTitle(route, title) { 19 | if (title) { 20 | let path = typeof route === 'object' ? route.path : route 21 | path = path && path.split('?')[0] 22 | this.$store.commit('setting/setCustomTitle', {path, title}) 23 | } 24 | } 25 | }, 26 | computed: { 27 | customTitle() { 28 | const customTitles = this.$store.state.setting.customTitles 29 | const path = this.$route.path.split('?')[0] 30 | const custom = customTitles.find(item => item.path === path) 31 | return custom && custom.title 32 | } 33 | } 34 | }) 35 | } 36 | } 37 | 38 | export default TabsPagePlugin 39 | -------------------------------------------------------------------------------- /smqtt-ui/src/router/async/config.async.js: -------------------------------------------------------------------------------- 1 | import routerMap from './router.map' 2 | import {parseRoutes} from '@/utils/routerUtil' 3 | 4 | // 异步路由配置 5 | const routesConfig = [ 6 | 'login', 7 | 'root', 8 | { 9 | router: 'exp404', 10 | path: '*', 11 | name: '404' 12 | }, 13 | { 14 | router: 'exp403', 15 | path: '/403', 16 | name: '403' 17 | } 18 | ] 19 | 20 | const options = { 21 | routes: parseRoutes(routesConfig, routerMap) 22 | } 23 | 24 | export default options 25 | -------------------------------------------------------------------------------- /smqtt-ui/src/router/async/router.map.js: -------------------------------------------------------------------------------- 1 | // 视图组件 2 | const view = { 3 | tabs: () => import('@/layouts/tabs'), 4 | blank: () => import('@/layouts/BlankView'), 5 | page: () => import('@/layouts/PageView') 6 | } 7 | 8 | // 路由组件注册 9 | const routerMap = { 10 | login: { 11 | authority: '*', 12 | path: '/login', 13 | component: () => import('@/pages/login') 14 | }, 15 | root: { 16 | path: '/', 17 | name: '首页', 18 | redirect: '/login', 19 | component: view.tabs 20 | }, 21 | dashboard: { 22 | name: 'Dashboard', 23 | component: view.blank 24 | } 25 | } 26 | export default routerMap 27 | 28 | -------------------------------------------------------------------------------- /smqtt-ui/src/router/i18n.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | messages: { 3 | CN: { 4 | home: {name: '首页'}, 5 | }, 6 | US: { 7 | home: {name: 'home'}, 8 | }, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smqtt-ui/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import {formatRoutes} from '@/utils/routerUtil' 4 | 5 | Vue.use(Router) 6 | 7 | // 不需要登录拦截的路由配置 8 | const loginIgnore = { 9 | names: ['404', '403'], //根据路由名称匹配 10 | paths: ['/login'], //根据路由fullPath匹配 11 | /** 12 | * 判断路由是否包含在该配置中 13 | * @param route vue-router 的 route 对象 14 | * @returns {boolean} 15 | */ 16 | includes(route) { 17 | return this.names.includes(route.name) || this.paths.includes(route.path) 18 | } 19 | } 20 | 21 | /** 22 | * 初始化路由实例 23 | * @param isAsync 是否异步路由模式 24 | * @returns {VueRouter} 25 | */ 26 | function initRouter(isAsync) { 27 | const options = isAsync ? require('./async/config.async').default : require('./config').default 28 | formatRoutes(options.routes) 29 | return new Router(options) 30 | } 31 | export {loginIgnore, initRouter} 32 | -------------------------------------------------------------------------------- /smqtt-ui/src/services/api.js: -------------------------------------------------------------------------------- 1 | //跨域代理前缀 2 | const API_PROXY_PREFIX='/api' 3 | const BASE_URL = process.env.NODE_ENV === 'production' ? process.env.VUE_APP_API_BASE_URL : API_PROXY_PREFIX 4 | const IP = window.location.host.split(':')[0] 5 | module.exports = { 6 | LOGIN: `http://${IP}:60000/auth/login`, 7 | CLUSTERS: `http://${IP}:60000/smqtt/cluster`, 8 | CONNECTIONS: `http://${IP}:60000/smqtt/connection`, 9 | SUBSCRIBES:`http://${IP}:60000/smqtt/subscribe`, 10 | ISCLUESTER:`http://${IP}:60000/smqtt/is/cluster`, 11 | PUBLISH:`http://${IP}:60000/smqtt/publish`, 12 | ROUTES: `${BASE_URL}/routes`, 13 | ACLACTION: `http://${IP}:60000/smqtt/acl/` 14 | } 15 | -------------------------------------------------------------------------------- /smqtt-ui/src/services/index.js: -------------------------------------------------------------------------------- 1 | import userService from './user' 2 | import smqtt from './smqtt' 3 | 4 | export { 5 | userService, 6 | smqtt 7 | } 8 | -------------------------------------------------------------------------------- /smqtt-ui/src/services/smqtt.js: -------------------------------------------------------------------------------- 1 | import {CLUSTERS, CONNECTIONS, SUBSCRIBES, ISCLUESTER, PUBLISH,ACLACTION} from '@/services/api' 2 | import {request, METHOD} from '@/utils/request' 3 | 4 | export function addPolicyAction(params) { 5 | return request(ACLACTION+'policy/add', METHOD.POST, params) 6 | } 7 | 8 | 9 | export function deletePolicyAction(params) { 10 | return request(ACLACTION+'policy/delete', METHOD.POST, params) 11 | } 12 | 13 | 14 | export async function queryPolicyAction(params) { 15 | return request(ACLACTION+'policy/query', METHOD.POST, params) 16 | } 17 | 18 | /** 19 | * 获取当前连接信息 20 | */ 21 | export async function connections() { 22 | return request(CONNECTIONS, METHOD.POST, {}) 23 | 24 | } 25 | /** 26 | * 获取当前集群信息 27 | */ 28 | export async function clusters() { 29 | return request(CLUSTERS, METHOD.POST, {}) 30 | } 31 | 32 | /** 33 | * 获取当前订阅信息 34 | */ 35 | export async function subscribes() { 36 | return request(SUBSCRIBES, METHOD.POST, {}) 37 | } 38 | 39 | /** 40 | * 是否是集群 41 | */ 42 | export async function isCluster() { 43 | return request(ISCLUESTER, METHOD.GET, {}) 44 | } 45 | 46 | /** 47 | * 推送mqtt消息 48 | */ 49 | export async function publish(params){ 50 | return request(PUBLISH,METHOD.POST,params) 51 | } 52 | -------------------------------------------------------------------------------- /smqtt-ui/src/services/user.js: -------------------------------------------------------------------------------- 1 | import {LOGIN, ROUTES} from '@/services/api' 2 | import {request, METHOD, removeAuthorization} from '@/utils/request' 3 | 4 | /** 5 | * 登录服务 6 | * @param name 账户名 7 | * @param password 账户密码 8 | * @returns {Promise>} 9 | */ 10 | export async function login(name, password) { 11 | return request(LOGIN, METHOD.POST, { 12 | username: name, 13 | password: password 14 | }) 15 | } 16 | 17 | export async function getRoutesConfig() { 18 | return request(ROUTES, METHOD.GET) 19 | } 20 | 21 | /** 22 | * 退出登录 23 | */ 24 | export function logout() { 25 | localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY) 26 | localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY) 27 | localStorage.removeItem(process.env.VUE_APP_ROLES_KEY) 28 | removeAuthorization() 29 | } 30 | export default { 31 | login, 32 | logout, 33 | getRoutesConfig 34 | } 35 | -------------------------------------------------------------------------------- /smqtt-ui/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import modules from './modules' 4 | 5 | Vue.use(Vuex) 6 | const store = new Vuex.Store({modules}) 7 | 8 | export default store 9 | -------------------------------------------------------------------------------- /smqtt-ui/src/store/modules/index.js: -------------------------------------------------------------------------------- 1 | import account from './account' 2 | import setting from './setting' 3 | 4 | export default {account, setting} -------------------------------------------------------------------------------- /smqtt-ui/src/theme/antd/ant-menu.less: -------------------------------------------------------------------------------- 1 | .ant-menu-inline-collapsed-tooltip a{ 2 | color: @text-color-inverse; 3 | } -------------------------------------------------------------------------------- /smqtt-ui/src/theme/antd/ant-message.less: -------------------------------------------------------------------------------- 1 | .ant-message{ 2 | z-index: 1100; 3 | } 4 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/antd/ant-table.less: -------------------------------------------------------------------------------- 1 | 2 | .ant-table-thead{ 3 | tr{ 4 | th{ 5 | &.ant-table-column-has-actions{ 6 | &.ant-table-column-has-sorters:hover{ 7 | background-color: @background-color-base; 8 | } 9 | &.ant-table-column-has-filters{ 10 | &:hover{ 11 | .anticon-filter, .anticon-filter:hover{ 12 | background-color: @background-color-base; 13 | } 14 | } 15 | .anticon-filter.ant-table-filter-open{ 16 | background-color: @background-color-base; 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/antd/ant-time-picker.less: -------------------------------------------------------------------------------- 1 | .ant-time-picker-panel-input{ 2 | background-color: @component-background; 3 | } 4 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/antd/index.less: -------------------------------------------------------------------------------- 1 | @import "ant-time-picker"; 2 | @import "ant-message"; 3 | @import "ant-table"; 4 | @import "ant-menu"; -------------------------------------------------------------------------------- /smqtt-ui/src/theme/default/color.less: -------------------------------------------------------------------------------- 1 | @import '~ant-design-vue/lib/style/themes/default'; 2 | 3 | @gray-1: #ffffff; 4 | @gray-2: #fafafa; 5 | @gray-3: #f5f5f5; 6 | @gray-4: #f0f0f0; 7 | @gray-5: #d9d9d9; 8 | @gray-6: #bfbfbf; 9 | @gray-7: #8c8c8c; 10 | @gray-8: #595959; 11 | @gray-9: #434343; 12 | @gray-10: #262626; 13 | @gray-11: #1f1f1f; 14 | @gray-12: #141414; 15 | @gray-13: #000000; 16 | 17 | @primary-color: @primary-color; 18 | @success-color: @success-color; 19 | @warning-color: @warning-color; 20 | @error-color: @warning-color; 21 | 22 | @title-color: @heading-color; 23 | @text-color: @text-color; 24 | @text-color-second: @text-color-secondary; 25 | 26 | @layout-bg-color: @layout-body-background; 27 | @base-bg-color: @body-background; 28 | @hover-bg-color: rgba(0, 0, 0, 0.025); 29 | @border-color: @border-color-split; 30 | @shadow-color: @shadow-color; 31 | 32 | @text-color-inverse: @text-color-inverse; 33 | @hover-bg-color-light: @hover-bg-color; 34 | @hover-bg-color-dark: @primary-7; 35 | @hover-bg-color-night: rgba(255, 255, 255, 0.025); 36 | @header-bg-color-dark: @layout-header-background; 37 | 38 | @shadow-down: @shadow-1-down; 39 | @shadow-up: @shadow-1-up; 40 | @shadow-left: @shadow-1-left; 41 | @shadow-right: @shadow-1-right; 42 | 43 | @theme-list: light, dark, night; 44 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/default/index.less: -------------------------------------------------------------------------------- 1 | @import "color"; 2 | @import "style"; 3 | @import "nprogress"; 4 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/default/style.less: -------------------------------------------------------------------------------- 1 | .week-mode{ 2 | overflow: hidden; 3 | filter: invert(80%); 4 | } 5 | .beauty-scroll{ 6 | scrollbar-color: @primary-color @primary-2; 7 | scrollbar-width: thin; 8 | -ms-overflow-style:none; 9 | position: relative; 10 | &::-webkit-scrollbar{ 11 | width: 3px; 12 | height: 1px; 13 | } 14 | &::-webkit-scrollbar-thumb { 15 | border-radius: 3px; 16 | background: @primary-color; 17 | } 18 | &::-webkit-scrollbar-track { 19 | -webkit-box-shadow: inset 0 0 1px rgba(0,0,0,0); 20 | border-radius: 3px; 21 | background: @primary-3; 22 | } 23 | } 24 | .split-right{ 25 | &:not(:last-child) { 26 | border-right: 1px solid rgba(98, 98, 98, 0.2); 27 | } 28 | } 29 | .disabled{ 30 | cursor: not-allowed; 31 | color: @disabled-color; 32 | pointer-events: none; 33 | } 34 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/index.less: -------------------------------------------------------------------------------- 1 | @import '~ant-design-vue/dist/antd.less'; 2 | @import "default/index"; 3 | @import "antd/index"; 4 | -------------------------------------------------------------------------------- /smqtt-ui/src/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "default/index"; 2 | -------------------------------------------------------------------------------- /smqtt-ui/src/utils/Objects.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 给对象注入属性 3 | * @param keys 属性key数组, 如 keys = ['config', 'path'] , 则会给对象注入 object.config.path 的属性 4 | * @param value 属性值 5 | * @returns {Object} 6 | */ 7 | Object.defineProperty(Object.prototype, 'assignProps', { 8 | writable: false, 9 | enumerable: false, 10 | configurable: true, 11 | value: function (keys, value) { 12 | let props = this 13 | for (let i = 0; i < keys.length; i++) { 14 | let key = keys[i] 15 | if (i == keys.length - 1) { 16 | props[key] = value 17 | } else { 18 | props[key] = props[key] == undefined ? {} : props[key] 19 | props = props[key] 20 | } 21 | } 22 | return this 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /smqtt-ui/src/utils/util.js: -------------------------------------------------------------------------------- 1 | import enquireJs from 'enquire.js' 2 | 3 | export function isDef (v){ 4 | return v !== undefined && v !== null 5 | } 6 | 7 | /** 8 | * Remove an item from an array. 9 | */ 10 | export function remove (arr, item) { 11 | if (arr.length) { 12 | const index = arr.indexOf(item) 13 | if (index > -1) { 14 | return arr.splice(index, 1) 15 | } 16 | } 17 | } 18 | 19 | export function isRegExp (v) { 20 | return _toString.call(v) === '[object RegExp]' 21 | } 22 | 23 | export function enquireScreen(call) { 24 | const handler = { 25 | match: function () { 26 | call && call(true) 27 | }, 28 | unmatch: function () { 29 | call && call(false) 30 | } 31 | } 32 | enquireJs.register('only screen and (max-width: 767.99px)', handler) 33 | } 34 | 35 | const _toString = Object.prototype.toString 36 | --------------------------------------------------------------------------------