pax_global_header00006660000000000000000000000064123106041700014504gustar00rootroot0000000000000052 comment=bb2468b2e5a5669080709ab472908d591aae1842 mqtt-client-mqtt-client-project-1.10/000077500000000000000000000000001231060417000175715ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/.gitignore000066400000000000000000000004061231060417000215610ustar00rootroot00000000000000#java *.class #general *~ *.lock *.DS_Store *.log #idea .idea .idea/* *.iml *.ipr *.iws *.svn: #Eclipse *.classpath *.settings *.project #maven target # OS Stuff *.swp .DS_Store mqtt-client/dump.txt mqtt-client/in/ mqtt-client/lib/ mqtt-client/usage.txt mqtt-client-mqtt-client-project-1.10/license.txt000066400000000000000000000261371231060417000217650ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/000077500000000000000000000000001231060417000241275ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/pom.xml000066400000000000000000000143461231060417000254540ustar00rootroot00000000000000 4.0.0 org.fusesource.mqtt-client mqtt-client-project 1.10 org.fusesource.mqtt-client mqtt-client-java1.4-uber 1.10 ${project.artifactId} The ${project.artifactId} module is a Java 1.4 compatible version of the mqtt-client uber jar file. org.osgi org.osgi.core ${osgi-version} true org.osgi org.osgi.compendium ${osgi-version} true asm asm-tree ${asm-version} true org.apache.maven.plugins maven-dependency-plugin 2.4 unpack process-resources unpack org.fusesource.mqtt-client mqtt-client ${project.version} uber jar true ${project.build.directory}/classes net.sf.retrotranslator retrotranslator-runtime 1.2.9 jar true ${project.build.directory}/classes backport-util-concurrent backport-util-concurrent 3.1 jar true ${project.build.directory}/classes true true org.codehaus.mojo retrotranslator-maven-plugin 1.0-alpha-4 compile translate ${project.build.directory}/classes **/*.class true false ${java14.rt.jar} net.sf.retrotranslator retrotranslator-transformer 1.2.9 com.github.wvengen proguard-maven-plugin 2.0.5 net.sf.proguard proguard-base 4.8 runtime package proguard 4.8 ${project.build.finalName}.jar ${project.build.finalName}.jar ${rt.jar.path} ${jsse.jar.path} false mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/000077500000000000000000000000001231060417000247165ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/000077500000000000000000000000001231060417000256425ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/java/000077500000000000000000000000001231060417000265635ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/java/org/000077500000000000000000000000001231060417000273525ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/java/org/fusesource/000077500000000000000000000000001231060417000315355ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/java/org/fusesource/mqtt/000077500000000000000000000000001231060417000325225ustar00rootroot00000000000000All.java000066400000000000000000000013141231060417000340150ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-java1.4-uber/src/main/java/org/fusesource/mqtt/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt; public class All { }mqtt-client-mqtt-client-project-1.10/mqtt-client-website/000077500000000000000000000000001231060417000234725ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/.gitignore000066400000000000000000000000201231060417000254520ustar00rootroot00000000000000.DS_Store targetmqtt-client-mqtt-client-project-1.10/mqtt-client-website/ext/000077500000000000000000000000001231060417000242725ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/ext/ScalatePackage.scala000066400000000000000000000022641231060417000301330ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.fusesource.scalate.support.TemplatePackage import org.fusesource.scalate.{Binding, TemplateSource} /** * Defines the template package of reusable imports, attributes and methods across templates */ class ScalatePackage extends TemplatePackage { def header(source: TemplateSource, bindings: List[Binding]) = """ // common imports go here import _root_.Website._; """ } mqtt-client-mqtt-client-project-1.10/mqtt-client-website/ext/Website.scala000066400000000000000000000023231231060417000267010ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.fusesource.scalate.RenderContext package /** *

*

* * @author Hiram Chirino */ object Website { val project_name= "MQTT-Client" val project_description= "The Java MQTT client API" val project_logo= "/images/project-logo.png" val project_keywords= "mqtt,messaging,mom,middleware,specification,java" val website_base_url= "http://mqtt-client.fusesource.org" }mqtt-client-mqtt-client-project-1.10/mqtt-client-website/ext/scalate/000077500000000000000000000000001231060417000257065ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/ext/scalate/Boot.scala000066400000000000000000000040161231060417000276170ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package scalate import org.fusesource.scalate.util.Logging import java.util.concurrent.atomic.AtomicBoolean import _root_.Website._ import org.fusesource.scalate.TemplateEngine import org.fusesource.scalamd.{MacroDefinition, Markdown} import java.util.regex.Matcher import org.fusesource.scalate.wikitext.Pygmentize class Boot(engine: TemplateEngine) extends Logging { private var _initialised = new AtomicBoolean(false) def run: Unit = { if (_initialised.compareAndSet(false, true)) { def pygmentize(m:Matcher):String = Pygmentize.pygmentize(m.group(2), m.group(1)) // add some macros to markdown. Markdown.macros :::= List( MacroDefinition("""\{pygmentize::(.*?)\}(.*?)\{pygmentize\}""", "s", pygmentize, true), MacroDefinition("""\{pygmentize\_and\_compare::(.*?)\}(.*?)\{pygmentize\_and\_compare\}""", "s", pygmentize, true), MacroDefinition("""\$\{website_base_url\}""", "", _ => website_base_url.toString, true) ) for( ssp <- engine.filter("ssp"); md <- engine.filter("markdown") ) { engine.pipelines += "ssp.md"-> List(ssp, md) engine.pipelines += "ssp.markdown"-> List(ssp, md) } info("Bootstrapped website gen for: %s".format(project_name)) } } }mqtt-client-mqtt-client-project-1.10/mqtt-client-website/pom.xml000066400000000000000000000150011231060417000250040ustar00rootroot00000000000000 4.0.0 org.fusesource.mqtt-client mqtt-client-project 1.10 org.fusesource.mqtt-client mqtt-client-website 1.10 war ${project.artifactId} mqtt-client provides an ASL 2.0 licensed API to MQTT. It takes care of automatically reconnecting to your MQTT server and restoring your client session if any network failures occur. Applications can use a blocking API style, a futures based API, or a callback/continuations passing API style. versions/${project.version}/website 2.9.1 2.14 1.5.3 1.5 1.6.0 org.scala-lang scala-library ${scala-version} org.scala-lang scala-compiler ${scala-version} org.fusesource.scalate scalate-wikitext ${scalate-version} org.fusesource.scalate scalate-page ${scalate-version} org.fusesource.scalamd scalamd ${scalamd-version} org.slf4j slf4j-log4j12 ${slf4j-version} ext org.scala-tools maven-scala-plugin ${scala-plugin-version} compile -Xmx1024m ${scala-version} org.fusesource.scalate maven-scalate-plugin ${scalate-version} sitegen sitegen package deploy deploy deploy ${basedir}/src website.fusesource.org dav:http://fusesource.com/forge/dav/${forge-project-id}/${website-root} org.fusesource.scalamd scalamd ${scalamd-version} org.apache.maven.plugins maven-war-plugin 2.0.2 ${basedir}/src org.mortbay.jetty jetty-maven-plugin 7.0.1.v20091125 ${basedir}/src scalate.editor ${env.SCALATE_EDITOR} scalate.workdir ${basedir}/target/_scalate scalate.mode development 0 org.fusesource.mvnplugins maven-linkchecker-plugin 1.12 http://github.com/ http://git.or.cz/ http://localhost:8080/ http://repo.fusesource.com/ http://search.twitter.com/ http://www.chengin.com/ mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/000077500000000000000000000000001231060417000242615ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/WEB-INF/000077500000000000000000000000001231060417000253105ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/WEB-INF/scalate/000077500000000000000000000000001231060417000267245ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/WEB-INF/scalate/layouts/000077500000000000000000000000001231060417000304245ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/WEB-INF/scalate/layouts/default.jade000066400000000000000000000043761231060417000327070ustar00rootroot00000000000000!!! Basic :plain - response.setContentType("text/html") -@ var title : String = "" -@ var body: String = null -@ var overview: String = null -@ var spot: String = null -@ var blog: String = null -@ var head: String = null - val include_console = engine.isDevelopmentMode && engine.resourceLoader.exists("/org/fusesource/scalate/console/console_head.scaml") html(lang="en") head meta(content="text/html; charset=utf-8" http-equiv="Content-Type") meta(content="#{project_description}" name="description") meta(content="#{project_keywords}" name="keywords") meta(content="#{project_name}" name="author") link(type="text/css" rel="stylesheet" href={uri("/styles/impact/css/pygmentize.css")}) link(type="text/css" rel="stylesheet" href={uri("/styles/impact/css/site.css")}) - if (head!=null) !~~ head title= title body div#navigation div.wrapper - include("/_navigation.ssp.md") - if (overview!=null) div#overview div.wrapper -if ( project_logo!=null ) div.logo img(src="#{uri(project_logo)}" alt="#{project_name} logo") div.message !~~ overview - if (spot!=null) div#spot div.wrapper !~~ spot - if (body!=null) div#content div.wrapper !~~ body - if (blog!=null) div#blog div.wrapper !~~ blog mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/WEB-INF/web.xml000066400000000000000000000027501231060417000266130ustar00rootroot00000000000000 TemplateEngineFilter org.fusesource.scalate.servlet.TemplateEngineFilter TemplateEngineFilter /* index.page 500 /WEB-INF/scalate/errors/500.scaml mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/_navigation.ssp.md000066400000000000000000000001211231060417000276770ustar00rootroot00000000000000 * [Home](${uri("/")}) mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/dev-guide.md000066400000000000000000000003141231060417000264520ustar00rootroot00000000000000# STOMP-JMS Developer Guide, Version 1.1 {:toc:2-5} ## Overview This dev guide still needs some serious work! ## Creating Connections ## Sending Messages ## Receiving Messages ## Using Transactionsmqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/images/000077500000000000000000000000001231060417000255265ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/images/project-logo-vector.png000066400000000000000000002345061231060417000321520ustar00rootroot00000000000000PNG  IHDRNETsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS5q6tEXtCreation Time6/18/10p'nprVWx_v0k4Z<zlͼv;,`{$hPh xe mg& mkC{xu|K tR)n~}V\W IWW;5uNM&_ gS~? QRت|'/Te$&!ËF/tg{ڿڥoXL~Qnv VIZףahXX a8_|u.'"3>ʻ4|*ǎ HW+>)Sl"~:_OX@7K`v9Z9izu?X u?nyݿD_?;+`6߉~tC^t6t5톮ژݶܗb'E/^'=ߺ/_?7HmkBF)3<mkTSx}sF/N8|wþ֩*;`DRCP 6OxYO_w l#5_^4of m;)ng _PM{2Yd/Lth;طT݁uzCnfßj&}/%[z-5t%K{t܃`/+u4u1^tm֦ltكO4}:`!m5\u,.ߡ4i3wZ}8vCՇߤh[yixFEvP\hX9yf ]HaDJ"|yc.t}Q(DGYRѠ c@`\Mz+^``8lwPB|L=GSMn9TFHetFHgtR,ba wòNhG ]}Ezi6H!Tv(m+Sm >k$)> @wBJ_HsTĨUܴz [Cf$Ig{fn,5Se,5eR>aL.ɠMjIYY~qzGE HtɌ=oZ,-"NȦ) J?PԎi~fJczIu5z%שc*3:exjuX&L}d۠1\LZ4o"E/ES~.Rz! ̴{,?(ᆪ1b q)d|WIG1s:̉DN }n@M|>˳F, lx_!u.KsBwԹ0Sapl:2fIc>fe tRTyl c;e}St;>t8|ouE(3USX)DKSЪ1Z5FC P9fpXǻ2X#1H&ZE("X*ƈqTh" q@R(^Mh^MRaJJŹ24q/h194<,V6 pU&O"lAJ)FI*Jm ?'uM8 a{- Hc [/餉)AfhdFfhdF ͣT1'W_摑q+>$f+ % &a24bFMZn"פ(%_RO|JyL"bL,6ȩN~!n8sdL6y!;02C 0VQj%z@$M9bȲߔ0dS#bވh]lEQL |Yخ"IhR$ɜn5 Yq  q  D|m+ -FeЛYs-=W B'K%G8%RM}#VcGǒ‰ 1|#Fa:V9b`)F,#Uj,61"x )p5Xd`mmu2D8W_S | qZp]( Z&|箻fJta=H=44M0)?/|x)(WyoQKPFcD֢Llpkz1p=Ǐb1=,1o$暦Dhr8Bzzpy~!9(I0@PF'=P~oIuUgP{/\K> QE5{2{743\ȱ\̖k7-3oo$yC7|d;CnK9*X(``brE/95 ?'դBf1S߈1fPg8,hdL$`lA#_&8XP}L[-K"鯙 m NBӶ̳ILIcoH5@KD[3Ҽu_#?>fD#;kSщZ(yUTMC/3$= BzK>H&etba-T=L5jx鷌Uia0UTjT證4Oxd Xd"緮oXŋ澯[4G%_ؾ6¾/}CsGr#^^`]4DzĹw=w& Ӓ?m;, ]kF#ExkMclo_ i} (bo?LUO;߇f뺘묡KtΕ7XĖ9N] yҩKV`"+C&)TL΋{Ϲ詏 +W='3RiODb3qy_,H0y 쿦עO1œ34|=s\Z6b:k|t La`KX186+tn\+}\xDb./!n"qj,eJ:|Bo R0,𰫏ؕ.>rIv=%!|h[~ c !2rH RVl~d`SNQ&QŎYSjKrI! T1"M֡$. o}!H0Z*3+ehﻝnf i!X;%:$cZxO:ͬ0 '- t`u\av^7H=X55嚤r8[cס%+mS-<^t~[|#~Wt+2熪J^a|(%/U6AFDw_EoaK@ԨpM9i,>_ =@6t(obB|*ǔ;[Bq h'x՝Ω+'@WdA\mtǜ8V(dKH60FbAM9MXtJt^R41O3ڔ6v _N=ߎ םΩ+'@Dצ4${?]P_cVBvjdKl鑭! ╶R8= c(Ӄd&6dy(?7~΃@lg\~+}ZZÒ}JԢp[+kA%Va#"Ϭօ1m޾QT%ޢ\d2N)'(ZىW78 \e;nm4e% 䅕xrV7úXf#]P6t"nfm6Ȱ"u6O -sP7n1Na ByVe RS6?j8*A'֝A7RJCzG#G ފcE~:˧?.s`?{^() M;o~w埡Ex@/<>~Œmx8*8oax-h;LHqe^; 靥⧵":p8GhNU >Q0Iˡ&91,'_>]ᝰ:;vEOONigZn_h E}OjEHb,rqh-zW FhԮiXyי{Vy3w3:~$wH Sj.4N@wMmA'/h_¾08(;;o$芣WzGW]P+v^9;;W\svl*z ڊ+zC5+^5C*b BW ]1Zb芡s0(8$M+^5ggW]q)Uf);o;Ww;hmk̼8z8ʼ8"בyW6syWsy˼zʼb" dU ]eU ]1tz2*2*:CWwgogWwgWpvB sv#GGo Ig.kq\G19{QuX~3c.zf\}NOZtӧ݈=oZ*_bџYXQ?cm{$-<E g4&[L%Ǧ-*sDخ,l~~)0t[0pN~ 5+b*V\~4я#Rܥ~B ,9Յxg/1xb26?Ļ:w?RvCȰ}^,1N@G ?jM 5> !Mڅ̅ўh+?ᮗg \)>VJ)i Ș \E&[FrD$uȦ;N95]sMwcWs֦te|HݮJk[ hVu5Q$uIkïa4ΔxBog->+MHsawفz=__iftd^>NYx׏IFHޯgYLkߣq*yv?F>N:"co/uqFKk4Q*t/DVS[3EQrxa3O[ݺ;O2}Kqq&'(n<3ѱ~!'-Bmڦm7]4w9xWA=ofgN+.`jkbଏK=Ḍe{M iV'hy['}Zn:"EdC%۾̈́g>m؊wܜ|e~!)c\ zy.]XZY+OR:eF͕YGO}~Jٳh{S}ٯiJnOnh{JV)3y73<ɎȎ8;Ta6l!;5Y*nflugnd}yOnw#f '\wlrzslYrHt %Y{9#uo$';M tpVN|.~3?. rè6\*`8d"JU-j^K,XZS:^ޣvf p'}28{':#w{мqɓ va;0uC6{`%\d`z]ÿ6|k}ͩSY2kmЀ-v<^~q;ND]A/IH#2R/n Yt\EiY"S%[/p~庿A\7q?Ynp"|/̿QqvҡGedUtCQQzMmxLr >^D+^U3_{d7gֻʽ '$n'l7g=PgC1*bUŜbέn'0= 'T ;dvNh9rF4}r.!~p q̞i*|y_{28"oA=Xnowvox,熢7t0KdEܓU* 15[\B^{^ RgjneU8=Pg6L\ 4$U8_R|3h亭>\G5d ZL3׍Fa֒s4$[TBc}18ƾ ^PZXt]X#:o5cn5޶1qBOdi쾺SQKLMS&PZ]c{]wM|>r6{0hP!FE[AK|3 6Ay~8l ubSXn݂@GoE+T ~W_QM{2n1/@*ȝu}tr`՛-l5w3Lc&O美K.9S{hA)(QF6{= 44{ԕOY5./h 0i67[6yni9-IMmixFEGAkwT.4,Ehr12B*#3B:#Vw=' :E0/0D oHKQ@* : @i %_j#-rhE+.>AD^Slz [Cf$Ig{fn,5Se,*]0tMdPK$僬,@8u0@#@8[Hfybn!pB6EHVTRZv(B\5SճNѳF8pN=b1c]FQ7o2[gmҿiS_^j"#]\C6i=Y~P Uc@TS>P<ct퉜@&$d8"|g Y}Ad. C|7\挅sa|2FmWu:e|館s d[->}P:0v475:v|.iY*ouE(3USX)DKSЪ1Z5FC P9fpXǻ2X#1H&ZE("X*ƈqTh" q@R(^Mh^MR)cƖ(2sie>9]-i0D=^:CcrixYmoPMAE؂pR2\ғT$'uM8 i'm88]Pxa%41% 9yBb5D^^<22!2nEه"v+ % &a24bFңekWz`,l$T)dN y7bX{΅Ըaꃅ8NuKxH\d]&'7&-Zzj#N8Jp% KG)_ƞ%b4H L|Dm37ɚ4cTUjDĈx^a2d`m\LI1 CV2\& /HI.c!:]}:caOF%!("M8L>` =^N@/9ax^27c#ʬȷee[Ӌ8~T3ŏ1d%74%B{(# ׃3 AM(Ԁ68y8}TW|2^]'/}j $4dwZ>S%#zp"r1[ݴD̼i>ULsgm41G  SL.h"%<2t}'%I酲b֧9b ̈́.LpY0/) 4e}';O&8XP}L[-K"鯙 m NBӶ̳ILIcoH5@KD[3Ҽu_#?>fD#;kSщZ(yUTMC/3$= BzK~C< CZQkzjo(aB Ԩ[7?h"|wEK4Eo]&}_%hKx}mN}_ LL c=\{WĻ;_iTK65DRGƑ"rK5fxkx67?BUOS`Fa/{+az>4[d]g %=dװ`ExΟ]3t"qbh̓N]Y2 L1g< &d{f&K.3^(<0J=ĩY4 iw9?]6`c6O^zj̜^tϯ`"RKU†]rRgXNi`<,s +&fu kŴ9_+~NjaLY^BܼyL}D !"+0YZt!(٥HEa )0XaWG}+]z}}!zJB:%$vdCe|p)G)JH]` ?JWS$1kBmI.)dj"F:%BkV/:I|?wEV 8*ū_WX':JKxUMйklz]R|e5ħJ|%Ho ^?S#_Tiǜ8`G,Q%K\ @'8tN]9,@-F l~icnERIdkD)6Xf/'5fTBdnڡ7N9"?_NhuZ-7Yx f/'4fVB+!Bh]4헇BLiG.y@9p"PeN<>ʸQWY*Sэ pk-+Y&/[K7֍B70邲v7m{!F}PO-a<|ohN2qqw tOz5-ǡ)IiZ N g)8ohя5ĬT8Z|,8u?Yp6V2~,?Xͼ3V7K؁##I4%b93udNf|+m/ǐ#OWu%ƕ;YRLtD9ؑD# 9k9Y-~ A sGZ/Ak9~Z~к;vp7CW r*b }/ВZqt+h芣+.]٨عb犝 8\CkCW ]1tA09SĿ8Yqv٫l슳+.`U8b芡Wqb诙S4̼S*vv2*v9۰חyW160tyW1tyk̼8z8ʼ8"1#bm`*b犝8̻̻+U]U]g̻̻+ GW: ב#ෆg38uw/rԸx:c;!_9c|ϐY=נzSFDx!ZX4^e`JZiRFHG#(r59~XR$i_dud)xZ)!G#Mxw H.{}m=j3k%ZS>}FzG{T&9c\wvDђ0>vC#=b UB/twP]FL#b! C sAb&z oq5=筰gl$ 90t|@=Ư4ϾSV%7kY6w3(Ew|DݏOcLGd,y.cyi{=JbECY,Q wcf~t XwLۃ JXX4#w7(1=IZ wC"::)g~(cWs֦t^viLH'tlrGul< ԱQ$2IQZ㜮EъZ]Y4.O a> "_K(A!^ L}жtnh]H4v܃>zκ-W\>0x/~qĈ2 yz<ԫnўJԗØGr}kuڞQM}+dxB5y!ϺlxGlLOߛҾOmU ;(6j)~-ٌ_6`KhdB#E&[E%DJ&>?~ 㮈z vYQhQm(uZEAPXV΋{ܣ~~3S&PLpumA$foG>.ux6%A/7 GLh[vZ7!N6V^#_FDϡcw ?P+? B/t$z#ayOܤx˔F8[&gx\4_I֥>.".9rcоĩ6<7c}_~sYs R*j ռ˧RSNH[ hIvOO)C-[/{ҠO51-~$tNQ*YmV9zSZƔ$;";NLtzP3x>^s/3r7x_&!غ)m.er9~eqm{x!{mEP2ݳ]=᠗J?K?ѧ'c|7<{E$۔I^Z!U }F!h\gF 3ۨ =[}k\H ev#AvH[zA?JiDA *NHo:73Rpp! (;xI*v ^}da"=Z/z 78;N:2|ɊΌmj)P)L%o56˗mėP/h'^vu{0,byj `{f`z*ˏ]㡘Y1b^Uu1L@ip޾yBŰCjd6nhp,h@ 'Cl7̙=T 4dpDHFC߂z,V1>o{ &Y EoۓqOVPd.>Ԍlq uzy+2\KcQMV^(B9X3p#LwoO^ѐTsrL҃tI+qGCmu :C)&rfn4  !YǤ 2xAEkaocwUۦb蠾B0KkTDWzD7=W !48yɦ.ȆFkF-lLMS&PZ]c{]wMB~;۽0a>ZaZoB'ACtۿ ?|3|q_g +L|?"zeT'bNmkBSx]N0QʫajohlU&fnÃsfd,>Op3]E1T яjV2ڃ-p uyGpodl`d/e>v 9]Aݩ6ٞGÃT{1H QlH':iуŏpa'D:__CEymkBT8x횉m0]HI!)$FR?6c>>~sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/rˆ_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{G}?v✽3X~j{zTAO^ʰ>?sy|G)P|OW0ûo7\ɌGagygٗ2aB;:'ʜ.dx2&tqSEߩkɌG!8?b{+8+ffZÄ"j˧yKB7ȹ Fp(u%KŜߕ.q!e„*u qQ?K97B7ʺ F`9Jgp!]Ä#Y AwL0ƨ9ܣ݁Z\ƙ1z>:흲7LZ?\.t eTڞĬ8;tu!;^bBwF\x?؞K֙ yx qA`-?5w j|_ZװFZ~}neDHc3<|A~xߺ}Lo4 vxy\~ ޓw?GDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDOށ#mkBTsxQQFёJ@B%  H@•J@pP܄tOd aҜtp).......................yeV.:i{O6+:2?Cl pl`3|wk5o6 n pl`? ;_~l&?76 n pl`?76׽ h7f%7fo{e9F6S:$K7f9 Y6 Ye6+cl|?W,ރa:7A>eKog_¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]¿]"I$I$I$I$I$I$I$I$I$I$:wTmkBTtrxq@E_ .A%-%Jp *ҁЌLо 3s>2.wy ,}{/?U///‘\qfYDX~@2aۯ9%wB/n]>]eu##&1'ɫ-Zg?W\̈sD:bF(=vZ?V\̈(sq}pr }C%Ō[MblZ/ǔs鱿L~_ísOh#Y,_{,ܘBwſ#yv5ze -߁/_-s?ϩOYzNܞ ynߏ=L}2[DͷzŮSNkV/9^ѣ'.Hr bV Nk8LBqYș}i ep, kdŎiǜh~YȈfq=g8U߇S}ESAFS*ۭU];n͉ᓐ#'*5%{+n߯ns% ] z0.=tBjNr {==(LBNr I݊ 3Bzc_BNr I݊oߗ{]wBf̿%G}~{beMY1{ Oڲn& ]\q!'=1cɳÅr)6r}|&?/J_Ps YB 9Yζ)Nv׻gI@XjjgiЃ`0 `0 ?ϟ|:seQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/ D:3D&򈼹e^Hyi#/OGzϪ߯_~ :sMe#M3Y#=2 QЙ[\s=E8}E>GȩT ڲTg-}VfoSVwzV}./>~!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-k dW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ: `0 :8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV U?)V>ғ)x|Yҁgi\yi^cUo*= !TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x )/OS yUo2e)Ve3'wgGg=J^`0  ľu kU,Ksؑ5nY,bXw{ w&3QהNQev ]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fzt|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz `0 *\?W8GY:Dgcg< 2+'W6qn؟{ru"wU쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP ~n%hUG4(_sn|W}Tg&x^c,Fѭ+ <#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3 `0Q[ veO\k^8֔v<Zbz\Opbn$~}oz3ј mK vU]^iNWA#x딫jt q :E= z%օq)CcYEqyRG-+u (K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_Eб Vq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7 `0]kIu+eL]ւoA^;=GR?v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{ ?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0 leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR( VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l? `0 `0 `{~i`oLy>uoi\qK|}7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;y`$j?tU mkBT~x흍8 FSHI!)$FRHnw HYx3ꇤsaaaaxIǏ'U{o_ھgW9 o'GW {>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O- 92b?Tlk%?_21B sY5>:>c=1Ow y^- ڶ,XzusM#גU]>H_yYv!ۉ_mi Rus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, l gX #vQg Bٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'-(W? źvƔOʙRv[K?[A}?-wmՑ}g\=c}M ggg DŽ-B^k_g?F? v0||؎=ǧHPgs/hؑI t~{n^}ZyD5XWvO)"c0vY Z|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8gʱL{? 0 0 _k3>z_\S |<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu l+6v<ï k7]/lc[`On}򚄫 G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ 1Gg{+ҏlw<=}GݽFƨ^)zIpG K֜{{e G12ۭqiumf>.}~a? 0 0 [u+7Svq֭y΅ ?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo 9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3 _[_*mtcmC>qSL=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^U O7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU? 0 0 0 0 0 0 0.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwx b)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-tĒyNAgC \NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`% Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=o G<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy czA;w9zszWHVax3 ף"mkBT6xs^g?98$!@H( $pHj[V7[dY{7nuKd߹;xc P5˲&oܼyV07. #c7齶&u)Y* Vbc 74 cy®` ,9Gc sWKBbS.S-G^oOVp흀_TNnn6Iߵ-fyQH!XM0;x-&&8ޠk Y#W %%D5pt?0{I?3)`Vt16+>pMnV] Gh+>|*z \/3wd.fTHzv/Usp6h]X>4~23P5۷Ikےd橩hD@RR;au\\ȅK_L$4f+Ygdj=F in_z’a HOi$2P͆ݝ4HI(,04u$s-jhdtKYׅ e.g+}U E=P[;+qay>VB#*sT3JZ;l8#+3.36u> ݷES˪rqr_@vNcLXT9q9G,11.2.vQќS15-)+mYճ2F'5zqs.O 2 kAC< !33T JOAksΐ:DB|Q:ETL^~/C칶3@<~O@-fNt "c5jjNAelQ0/')~kD_m%RΙ8&d'Y'd-MaWftYрd]Ɔa@ 7)-N~dIyN|} pwMO)47-0'3`IɆ85)@4̟ d1rIH*?]]dF7coZrMfÊ̐8DLhV푋S v :&p/Ajfɱ[ naDr@UK4lQ]BAi׈n_1ΎIXY74׻ż 3}[%4.~ckWRWݭO77mkAcu+TWʜ](kUfBtd'᭄7{ WlR1/,5#}KN(ECӽGSe䏓=L\l)J&7怲ߠ<dlGAgheB'.?} P-zoӰEWk7ִ!޾)z K%O>J\L/WŻr+Opd;Ѐ٣}$e¡2χ=;;[V5;*'yUՀ{&~;]>ä¡M'w/Xgfݘ1]za]!9|NuH8;Gэ4K8Ҁ¿CuƆu$o掫>\/R=eYs4}}Ga;?l7KCw!tg-3Ywp?}1B[Þ̂=Zu/9}>g5C D+V?c !qORɻIguH&n:Mo?E9K'9LDd?^^eX'qt z{-KܕIIuRF%* s\Ok6 sS?.O!mg_0-Zp>c>[O=GL<^[W6))zIɆS2eP_MmCoN7HdX.Vbaq-mfgxT[.5UdeL/q+&AuY9#wy˝SO&{{,8F/#2Dkރ="O[c?4lrט:^Nâf(/IztØCz ۣ\4m9}U'-.>NJ1x5bk訶zQ=?p ~S ?e waC zwK&G=dWy`}wxќȸ̂(~ҒM2Hۨj"s"$k}G3@ɂ)*X #uiP]̄&5c;W>~4%f bq h@3 { 3 =fA(fYM ,*pj(o!B: .sgBqsɥ R 迆%Y|<ɓYKD!gTr4|ynٗ} lͱ[@`x z_4 T/лGM,9uK>o.XOK)S)}a]D e*s$HO5iT< V{/<ꂺ[di<Xr/0B2D1;w럷RSN=#XX!KZʌ0GcKV08!=ac}M~_8} \ʢFۧ[AM&kT6ޤ&u2 ! 7Z 7O"&he_Uz`m:ͭ7iڥyK$'ޏ_zhm? %s̾c73O9y -1Gmd>Xs^4p>pN:Yɇ ;շ~LC 9+ J&?i٢jmj/4J`l?:L9cScIT!hmAM:M䗮!9#6nnEXi3bK_8}ǧ{Jŗ0}#3suO 3BN߅b[Ny,=5,ަ%]'KOg=dw}08Ι`@:S5w(-ZS 7ɘ"L4pY4`\q I tm!>QZM~*2?\W=?p=۷p}g] q؊[MSe&R=&C>ye[=w]1??K'ï ]z^e[Pi9 f8O-\L^=G9@Ɩ]]J5 ҅Bcb9C_ܿ7!>+:c5, ^x#|.8-3G-9`E!|eW*?dX`{GcxÁq.QqDKcXw97lBָ4`^ uPсt4s;ؽHy I UChVܡvDL=ka% J iWߧJSp@b0#5U;_Z?̅z.o 6OK&-g=JWVϐ=ls.Nvқˀ](sQh >czrӱ1ID'k^M}jM򼤤rih[ Q\|;_,~eH6t~K'E2 <):x+fX,1FK6ّO K&c VXGM!$g.*Y vWq/\?O Wе-+Lce?ATD1q믡~|0޼ʥS.zIՀwqp+I&pZ>fCV½ٻ$ eJ_0y\¯Io1i~C**dl*n~.aiY6qB( Py- gHqOp(O'~([ u^`Sv2Q5`-_Ӏ+?fG]d2Zɓ9 JYӢmYFۉe!zɸ9@GvPYutqi=?٫s\,I|/w|+_r w\Npx٫P L3#,VrAĈRx@@Q.K$-!}ݩc4EuY_O,?wH\,Q Az\9F\S2H~B௃ ?h/꠰`MшE!x]j#} ^1cWNy6!}EGN C4߆р-p_ѣ3Ӈk§*6/w 4\$ U{ BnٹL,I̘F!2oPQ(3@8a[@i!C e0o^ x]p{Y3;Jxǭ0{hX9#Pr_Bb7GGگ)Ң}Jӂig j=7_^: CjeUHaĞO3>j X7 5s%\% dgV_Wg?@y7\0֯]!Ҵ<2k*D [ql2^k;5u[*e?3|K!8gDN'T?$J&!H.*?"Yz ޳ΘP2埳󙤻z$ U(퀔$owK}X96bdY'zo+4?P=v܂~cVAWnDY+];IfAa>2 b?&T& ^pYaG¸Z^C?ܾ}p7Obe,uAڪ00xoz`r撚2@[/\z`%M(vm5E`U2/EY9}*JHC[qv٤9dQ@>ޑgt?hߊW\x ?t {'o#farBT?`_7NJxd**cWi/WAN.9[Ħ.4G+f|i Ul=qi :uJwRєIV`))YAu$)y J/kxhp.FW//eۼ7]=;a f:qsߐl+?T*y#&3tuҲVHJ[j|;TR15QjBeUӴvEwԿĈnV)1G<IyфibA$'8c}'0{lڂO#|yN=tS d/cn^: n$3jOzyr+.$chDb}hn]a`dw}{v_;DFF:#M3z("147I%Rd@}?Ÿxodk2_ue[οhιL9?ǩ'#>?_9͇:ǩcB̘a-)('3K9߷W< b8IibhlEx7yoP7+7>3_W>~opW_}v_;...Ԕgޱ+[oU+k+RwAy. Ln29q{&ijꡦ=VaU6Z9dw^>3[R=֖a!8f'7[c|d C -cܤ^O;)uDF7KBDxE +r=UkG+{-l31aZGhhFRn@oGܕ<ZF싟 /8>sӻLouZelx VM~v~ePOlt~i[Cu8#}-tI &V>c_kq**)&5Dnjb vXIiu˲'ozn9zců-0ǢhbVgt}7e4-uFXꟑN||#UAPP /Iݕ> $qKj8/>>':ax6+inuʚ rHJn"reD{;vzsOz-O#u%u6sR#񃥥㼶).fCzGz6SGLL{oc^wS(Uc#H͒: pu'($23gI?3%`Nt1>'>p-zoV] [Oh+1Bjz ZF_㛈.,B~)Mj!_okbjZ4q̬3P5׿E{DzdE[dT@JJ' \Z̥+Yx_N&c;vPY;KqEd5QfÜOz-O#ɞt>SXGs9"nJEߺ,3kR զijmLL؁x޾-::W8Iq\_j\ #*v2Ӓ gLnjO1:y!#oҶ&zk*"7YrIiDjJDL%#+ ^:\}qN:dJ|[L.9#*3Ry={wH>\vNw(>o17IzgshzWhh9j -Ĥr'*"-Nbzq+/k `e,.i\/!'v: ْi^C[2K>/Mٷ5KJ6,#=~bC4YM}Ì#,_ S%cR"3G\B9u'(*"WjrYCD&K&,Kx唉[~^ل˚uԸĿ[R#fg=96mSV,+R f1R0Gl\Et\IiD[i]z܊[mU 5@J0q7N|ݳqsLI.zZdF= s32ω$M1>.]imCyLi,2/=`YɆ:=%@4æh`F28$TZF^zsKfUYO֚uʫץ7J~_ oa»n&$ ?|KK}ze}mi_zM-ɊW'Fl'z3+t)]^3/{wArœ o10p@o>-͛TQT8A^ _D盋[ բ-6oAy|}ChmR='2ZF`v|ަm614ٴNG˦xmj6)-_ ?CF q}mAU*> ':Ȧ0AٷsHymJ?4vhlXQ5P?&/y]Հw6~~;1to S2n11Ķx*= ǵO.J`SP\4IN?]2#fRPp^߿.ؠ桓^ b\I5R9Fg-&jn.̈&ƺ|߫;sсIϜ>DT&]211UfZ%oLk@C} jk$oO>%|\]R *Q3Y9sNz-O#_78OWu< : 'gC =Z-t4K/ا]U28z7,O&gϊd~Y!݆}[ϨΒ#M򠢁4ꨮS5 v-% ZFн7x26_Hm]$_,^x^y@|(^GemKWʝ%M "k-^%Z2 )T~ mw[tq2o J&'(\LN5y[=+T4#WfΎTWd1Bz amxcfMb#JyG8w7o<j(,Y'1eB|&!׻]jɹ;dbbhkd\z̉ə=j6RU||NO\LA |io&sg}Ϯn׷vkyǞx1S?cރ{/:cz ?o*iz&>n)>`/r[L_ ^Q)5^#;}$Q\>CH˷噯̅dzz|U޿Id+0 Qqky! &^2;>S.8<戽\0~Vz5FsQ28ۯnjOE H?kڢq;ݡAŌyB"{ +LSK)Z9Px9a;vQt܂eRS爊 0Yho{ky9.W_r8?*pI;l ,w`E <%K6v_=>?tu]h[eH2ay]65P'a^ Q)cҵs89Ń3kߠeu$g'ǫۄ^c]l^}._ >3}l>Θ/?l-Hx|pEk3V=m0 #̱ʬ9z%v\,vmYDdAѽ_M&]% muSzA~::}e,*$#s;Nz-O#cWp%<^˾ϻ Nu^R|q{a|t1g?i̇>b1yٛs!p67 Ȟnݥd]=*".kUр{ &i$ bh??ֱz@hA ֈqjIiؾ!}߾x}U >x<)^Q X*=ጝe>#Fq]1'? dv/Pt7AmŶz.T^Kr"9sD$_K1R3M8(ܶ'ߧvrFlё]\T|ky!d΅=G'|{_z# W1"`grFZlTQ\˧ lS r%G7UW[OB°7BjOz-O#DX%K?<~7Z0W?>_ӉxoAgld[] ۨgFdFaK?%yyw̾ӛ!YaHYcDmR]*+Ml a6\񩢼`~!Z{IN![blTIi(\ޒ|~rCU.K|]:P I+=je% OqZXZFE*{ P!ٱzK?ILTIi8,t 'xE ̕q+W%V ! '!\Iȿih=T a7~.}2R JJHO_&-Q2/xan!@&QSz_yN04BRj͵3}'LhBFC z?+ZZ<~ky!+0\L 0fn&J&O7~jꏂE\h_NV3|T-8 #P97tP/}IH)n C)tHh>Ar7ϯ wZL̲u.%9kCG7IMU-Z?NBr,"ʲ D/$^_>ؿ~hZz d_/>P%(\XRzH\Y2aOok?/p}p'Nx;g\Y^{>eg<} 뇥bu3:a;&_`|A 9R2VC!`M!o6L 5RQH^qIi/CS.l.Gw߲ {Wf?$2sk|_j+}ח|q|ϸbgd?(~[lC6AS>e޼!ٳ5:+WGf6+ӎm=K %e[X߼Mi􄉓^-rBI+$ͫ\*RH."LI?:+s_Rd>L/dp,}E/]%9a&ڨύ3%xb=>S2Jg* #g[܈R@Zw#t,g:yp ~giF-i]I Ŧ@f4l!qhޖV(>'q/_vEW̟wY?enjዼy{^'>z߆Rt52_XL0AWp$SSeغNk*}/m02>]II,h!XjQAC]}_~ ץ׿ū\|ɚ /Zr93=uw?=W~]zmy+xXu014R-E d(v ZI DC 0{RCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?W9*mkBTx}+(H,"H$"#X$,QԈZs>U{ ..T}6ڳ-F`p]k߅~b  О$wݓٱ|sCoA+q3lOx@(0a+? T,_7s\Ϙ^Bl1)C+k(FyN"8dPC_9>O0&l4Im+nwGrŰ)/tihf ѸX>E)<,6s45zb?J\<OM%O#(76:= ӋYAƒH Ls6MXBcX&ǘJte. 3.je(??Lj=%wZizFTx$kP8Em jAOހ>~؆B9 ֤8UKCvjbL Cy ;mj P. DkwUE€3ܨ8xUJs\ɟ+;}sFQ(KIXݛƨ 1 +KdX];Jģcx$D׷X`i @l̏rnm$^9΄zBGϞQ=nfkDe; <a>,⢞jk0B[p($Ǡp4 nq`XƓ vϵ.xHnorJ5Hu뇗 f a[Z:>36[g RL؍?( &w.7C#~B{] UW 71jk~ecGrD.=K@WDZM0倐0\xvqNZ ># BE )&yA}t?B Ym(WIpɱ |2+\2 )l8tl@Z.Be񅋍RSƃm>dIl'N adĢG3%#)?$s _5=YBR#-k"qGP-e"f%֩-ϓ378M9ϊ,_*n;HEBƱcl~ ˝[/sagIE2,z1t:kLș壋G){7ond{@rP>kwk׽ #kXfyEAB9uM4P=_lgW؇N#_nGpp ,ZUu6ȓVӰ0EK7*|]{75F\ԶzQz! uH>upT٣o3P)[^6` -d&*=%fY<^ط`_6|h3ء>2 Pq7ώ ,NsjF=B` 큳CiU)R鐏@LҮǧmb<2FHRqùFXi䎲OmGA}:*u f:@ʫRH.66jcGOpO- 6HKJU:Jǃv,3DZEƮqq7p?ȌK%ȧ$;?Qr6pP7`a^=R_)m>D3#£ _' Iɭu͋C-Rne㯄ssL<ȭ/R)|Lt_1Lk=rr 4/gEr~PnB[\g[{gYvRW' {Fem1{ wL;7&$xc0 n&u@5sCCձm8Heft x{q(aтa?Q%l4ςxmWI׆GC1kQ3iJh,KRO`ʲ4)%b6B8\pe;u)ko)#WSncRx{[sXv195_0Kՙ7>Tp5ٴl3S"؝LX睫[5m Q="u}pϘ*xbՉ#iM+@Z! Ϯ~jYݬ$?5mtu] %@݅:4h8ۃtu3; ΑO1A/r R*5i&j#Y2:$Z(ad@>'z L뇶6Z8|`6"X1_z' F-я?X^ A:?1;h/KVB' vOnFS ƤQ{=kh7MwXQp\v͓O/. N3HKRlK"q^Wh1wt h@3e6N|I;y?8t[[! $,ήLe"z%IކAkRl!3u8ځy?_W)AbCO!rza5Sn֗#<43y6"R߃CQ&>[# BHǽ{vekOTlq(UH͵h ݔ8,@tՂL{p/*L"d_y k,4 G̖bD>,.ok"D;|7[.DCA#ilϟI֬Dq]+eE _-- ڰc^Lq1~CCC9gNH8BkhJ#Z-`VoMa 9r$պZ-hkh ?C$ ^tď9d(8P݅]ڶw[wl;dn׆oKd Hބ(DInI M_(5)6H/Y1 QRk,nXHʉ?>df&6^EJmt{CCc`0ʅv5x<\9Yc}106"״!֏9dl:' 1H"z'7QqɌ#KR./CVgQȬ\ `?d1yuM6Ƶ8ZX]8^pwQE &1frRKi$GݜЕh3'{;;~FK37ku<pdʎ+C RMzƏ7)nҀ lEGyl:̑IoBS%|ЕsTulebA}Aʹ10A{KʘӺtjdLI=r PRg_LbR Şl?␔)![Fo wi&k^CV(t@pW2{hxHGRn͉eCbxԉ6GQd27\ثdS=\Ff*0ۣOP5(rZߙxQZ>~GAeN-jY7Ҿn;n?ӹ"Px}/NW:݊&׾:x" ꭥу;R펔 c䛅љElmG§a= h¨BG_uYnZ쫭FYs U"zM&:Gnu.DX5Xn;}ԫ%XO?~2&Frjj8 yA*W I9/ub)Zl: s 85J>~iI3Yԕ;:#hELם[ROd^GA˩f~Y!En0~/A Km>^WYq"<цF*c:xw|͞w%ehRgd9̕v3v Dgh>>?3hYDkgC(ʹƒԕSԜ| 2Q94(?OGQ34 fccPopTYaW(>@tX4`LGٞpɄaŰl\[9c26U M6f,'C4i?W~psϠ?kAKrŵk@I|>^xs?\`,D̒5W^w DMXf_8<%|8_왉pP1Wlm߃f?4:́_Ԕv M;k:p_sj؎qw]$F}y ,b'N=o0, ~M YR46+!}@~ujctCP.Y(x׎z?70WXFܣo3z0c8RGg0 TU򄽻w"/4֏CQ`[{Ocn]+{{ N!33+5]qpj' r9FDȬ)~: 9Gmx2-?sraG"yvUpa;Ră A\& ?#n 0eed~oq嶭!!DzP^H)>oȑ.ļԶ=Hy7S-M ?8ycߧq|#5"2Б lm#UeΤVbM͘jAc7Z ]> 4gb s 2WRsKg6 's8qzTT[R[w)I95xWj #!nN+zPڔ KgTE,?{^RDݥ=Ru^zîc&D'i74SJߔ&HUG[crͦ<׿~4}څh;lpAZ%XZ;tQ?yk1+Ƴu6[ Dc4Ɯ*dB#!}e>samhG3c^8u9󼵕⸈߂UyB;f "Yi=D =4&|C3g]~WgjhSIXU"1A5Fr4{AljwTt6</N \Rta| i>T.Wo>>xϯY{緷m,J{gg}v~)]s!?wXGFl!7U|Cnfﳅ:.@mq%臔Ru?.:aBֺE#Gg'yXDuSWNJD)21ѵVagWPqȒ s?¶@g")s\T{f3go^w:^"{d#!φt},nyWFKv„X4|VB~,˘_&fjp/WԍwaO H 3I`u1ͤ+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_W|+_Wݚw)mkBT1x휁8E%-%XBJP Yڰΐ8/ ɑh G45jOzpmϽGgБ+u?~fё+uZG`u)^:rȓz&b2|1O̓?:sR߹1ԙGߴ{1obˁq>#b_Vj]_$ s){mdF=GzƱÜl)!GU4Ԧ89ߝw auxkğ+}K0Es<+:dn⍄Ro;/ cHB e 弉G]1xhZ'}`m߸YCEGM[{ex NnPC92sƻO|~89í]+sB52wkZu-0ڳ(/JI2ޱ|~y}-cX& 6+ju2TCSm5-x֮W,cH9D?Foniv IC}k.{/O'}ɉYyNֶg}{YTEQl}gdk_SwވxJLϺ{T/vcw%elgݽ9ZBǚ0 o˻5 }wտ-bx{dN(ƒxg'Z{s bwg1Y_UU>3lD\~/U/qd_OEew3%FUr}$;~nyc$;A5~/83ɎrϭsƲś{+Xıda,n.8G6}v2$#XoR+ecy\nw}'xMg0&xN^$qX/g2#iTXtXML:com.adobe.xmp Adobe Fireworks CS5 11.0.0.484 Macintosh 2010-06-18T14:38:20Z 2011-12-20T22:59:44Z image/png \ IDATxsG~?y@! iklqy}}pF؏KGl>Olx}Hsj4q}VUP HhXʮo/Kὧⴢ'q!$.SQQQQQ16yg(TBVQQQQqTS YEEEEũSM%dJ*****N5UTTTTj*!8TBVQQQQqec-7,ys89XkIӔpHq[EEEE(#[[[( )婎C97;?t`1j.}lno!81x~1t;};`2Kn 8pkPѨ'LMG8Yp/o839rܐ 3T&DL^܇1CVTTTT,27~2_@s&IPPH%ޡ9K$ ^Nw0$:[-yzL0`ggH+****N/lOoPY5J %M8 |ay$ u$ gΑ)n^ /Ti!04#Bd#FZ10K&llu+bEEEŗWu|*cvvqi΁GA 3!%Y69O>M6E'-RJÔY Vkᷟb*שa0<7H) 3< "ÜX(.\^|huxqgEEXm?TWY Rq-⫯1?7gm* Q%Ahc(%PJ5zFrm-jy}8ږ5W:ߟG9Tc ٳga0=JlmtX}ݻ!? qsճ;;35J =J)<@JYy9du%oU.vZ ٝ׭ss)%Q }L&$AҜ?Pt]ǽʵrXCw<+"4z+eԦ9\EqzR|ޯ#6=ݳy.x&r?eY`w 3xy8!T+CW R"`e~< ]VV7yx!z4_ȥ+Z$`Vc SvzDQ ) -3rm8,43($k+< ցs\*@)Ng'" ѡFW׎<]'dN:#%YĿ{4mߧ2ff()*rXxǹʈ)cG 0qK,$_%Iawno~)VWX^>ë_W33[x2FQ,!B@g"5^9VkM,nsUG; 8zN3/{ŋ2CuTST,e[e*>nCl$Kpͽ5 /P ٩gl!K Mr?S5/L!a8wn  \r/07)1.GH( AH% QV`@ʕ+9Vth4vwp3==C3DqOHaJ'ay|\\ޣ0TPN95HZˎ=0BjG ̰Fa*i!XL1BSSMPfڭΧuկ:QFZjv5Hu:d~~VKjmO~1F\ !ymBz#q$IDnBTgN,Ż'dLgǐ24y<~ҫ83lL-w)+,X/c Y:PgFGu©~kzQQa$SyNף뱱9/?}+KјyE`q &z 8@Hoo?^3@ob&r̉Cȼ',qCq>qǻ;>v}{UX~fR܎5r>X-dͩ^N64YEzQL x/AhaJgdC?蟸orWM`rC,I(rX# cov 秉4@Ijޑqo}av/Sqpr-E MQ -]ƫ<*18!ko)Lg@0cd:&@b8!Z{0"͆(QA@Ǥ^p?/XY]xihhm?"RAZˑPy661&w-Μ#c{0X[cqOCYGV)mιcW"6E%rg7mneXnOK7In2NXmO6LvC'wxž?|[Vn?DѨՉcRۈ m/ S P$$a$0$&j5Zܹc _U5"Z- {yH>[ۛܽ{i*ͦד7R heRnI {oI}eGoٓ(/f|/ˌ?nsnPNI.Yڔsi|BL;{n>4+N?&@=+L7̞G a9Hm1+ۻV֎] BTRSAw~[; L*F+9$)ezjgϞGA5|2rhxZk~,ަX(y2?~Y{cg>׸^qNEŁ-dkVY{F$Iĥj6=7O Q]D2 p LRbLZ֚N|r)BhN+XeNZ A 4 )%+++lop;(pt!d[?jEo4#7aw@:{ ʛڮS :埝5X|Hkco}4\0e$7/6kwsbqeg|!'[L/"Ox$Vj8s,󯜥y S3uTX;ȝG#A(Te 1 ff Q\msC4_4q )̢$yS׋aVk07w-67 D WPYB8&UgȻ,d#&qq7(ީ*&ˍE9 8oO|7|Ei{;_Yr y7v2{,|_ rן^iaАxEZO$0$ BRDARAQO15Dngn-%(B\]2P gA Mszso޽z (ƃb߯TEGHg-8M㗍qT^G.E¹B1r 8 oߥZ+cȺm6 sFXe966\b-~ԵƎ+*ʜdN9F{%]?H}})0CJcjj % #fffq_|BO#^ atY&-=e"KLƤSV4gܤyqT%'2^M!fL{rNGOqs*92o.ɲeX·qD#D ;k[ =Hn_{\ RӍ:^!QnIkA 4o|.ZE|[9tBvvr};r8SU.Ҙ:OQ'78]!c+sA$zK%QVŒ<<&n2My~V~nrJ{fc āxk!:n pR@PQiǥ+̜o%Cktc %V IH y뭷LO99nj8'ȲS8o>cvɥb?c~{Ͳq,S 1q\j?0' R20O"։2@R@I "0&;lwnw1;Cd x[_X=\je)67HbiAHΝܹ >g?Cjb=Zk8z>"3(w @-8Hbn%|,}vIK0*SQ3IG59)}K^,":ׁ"QH+PFo DR` 0P|FUU^nXJؼr֑F}3Z8w3gj$ XJy< e{k{wp WN,[f"o.pݥ}ttD9Ӭ(GY+.bPnӼfFԓ{H)q"4uLk?kbU҃ p#:-Byp2c,nvER*.EBAL) 5β9~hpSV2 ^bnOo15seZ% i_PUrPci`cgZ<5eP{ű4;GMRcQJ J33ݤ'H6X^a[mYW?}Ƞ7D 1#7:QB%SaHܽ{WιQ,E0 X'mz)%wΝ;8auؿx{wlTV<wN .q̍4N\Pؓcλw%PL( $:Q@d&9aQ(s,0Y d݌WY~l@QA OѠ1=MܨӘejv`ȇ?iBAB<aZ 4anwx`8]ko+*/ lXŒ9[v56-u$DT8cAKS` BIo@I"kz최_=&!5fecְG<3Ôᣟ׮^YE iJF)aȍ ՙ;ǝ;'_eɖ=Ut_*s,qAeޅ#{Y`oeʉ2'-A{nTr12 D:U1~f=FQ- r3\YOcI}nYfg:ΛLX13TD1OIF@ 2 :jPJ#+Dո-%'[bfŃX.yQ*'Y,y"/K[8l,8{ӘD/h1_FBF/e aqɬZqhT=ⓟ||s_}0fc `i͵u4p/h4vuZ\"YC `#p|7Hi,oys~)×0Ɇic2y`eXK/dJK8<9is/ p-/s9zǙ3tkuKg5}7 II/R@c[-ݻG&)J'Ԛ<$ A1ɮGK|dOcLP.~̔L `2_^lykA=uK2!Q5:SSSt}{{ p%aVQՎ8{i{i̊ˇ#V^4Pe WL?{~82{-BTDhGHܴDϏ3K)Q gAt0lۻ[G<5SPBI)II\;AbsmthHbA0aXDOd\!;LW1G8,<]nV)+dgcq+x?7d=B8+0$ H7%u!6 74'ӜiS31 pzpȰ2U#lmbjq $Rz*EeϬx\kDU!Y`1½TBv0q<5K$>/ߒ;'9v;Ɉ:/ ȜP`%B 8 h-yY%z%"VzLOOsiBHIB tt4$1sԧTx'pQLV(_i!u`2oߣ2,yA5o\;<~&^>at' O8 ,28`$^8 %Vz,,x ]<.wzP!]@͝OnOs@]O>XBㄠјF:Of촶Yy^c9[gR!ϟ1]iM,yJ }\Ɵy|skWLo\WۛYĬLbf}C:vPBh1r(]PxA!=B=#o;:ҝ;[B4A$b09Q f"HdGA[^pQz9G^nR.*7tsk_HB3Í130xn$ǝBwj(,t$*Pwďb5:dma(΢paGg[ymL'@yPB3U1Rj(*kCܻ&*)4HP^} og\3R jb7(iY72ylܢZZ3nr/˔Z8w}|bAaxrB#K0#38PB Ho,{\f0Ì͇KW4QN@*%qバ®$f~sisbts&CY XFA@h@?گxK/Ahk-i֑vܻڃ`=g@"8)WW֎<$BHN=VIV^KQI=|Ie9m$7wBV@zaZG˴A B,<>BD EDAlhVb6ۛ-+a#dBҡ9| %Oe 4[yׄQ9:-|HQXyߠhM&t B!:4*rm8Nh p2#PZЪ m@HQN}2R5dJ;%݁ <^JTޜc Isn8 $"*,cez3ﮘ [2%;[8kׁ4 ^9;-dA@Xrb$$GFh^K-(VjaDQq(VB9P*@ rGKG<w:yc]N^{tOP|(k=y)su Q{w-2~!d,S&ie^1q'c4=LYF9v<S{Իre$}\nhx:Q2=+z;d rAb;C;x 713 Ya;)x8㰹+gYlnpIO!iz^yuիcAkhbtlm"?9:6&23Sp0;,$=vA~Yaukc+bc(=4Ms3ءv '=RK/ by ox 6Rts$S b Y^QiG,h0y^w gFQc8igsvh>m*;&*ǜhY~1Fγ=܆  /̅|2,+X0*Ke8b?Cazސiw@d14;t[ -bA/,Ƥ``7@beAV hLEv}R,Sxsݠ0\g^Z%bGiq0 z=!Εvxx2ilmmQ~;o_"fxK+[\槊 Skqcc4s*)/"B8&Iߺuϟw~d:\>xJ***[EE Q ?pT1+**&A%dρ [x٨2PzlߋTω[QQQQQqTBVQQQQqTS YEEEEũSM%dJ*****N5UTTTTj?_UFIENDB`mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/images/project-logo.png000066400000000000000000000243251231060417000306460ustar00rootroot00000000000000PNG  IHDRNETsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS5q6tEXtCreation Time6/18/10p'n IDATxsG~?y@! iklqy}}pF؏KGl>Olx}Hsj4q}VUP HhXʮo/Kὧⴢ'q!$.SQQQQQ16yg(TBVQQQQqTS YEEEEũSM%dJ*****N5UTTTTj*!8TBVQQQQqec-7,ys89XkIӔpHq[EEEE(#[[[( )婎C97;?t`1j.}lno!81x~1t;};`2Kn 8pkPѨ'LMG8Yp/o839rܐ 3T&DL^܇1CVTTTT,27~2_@s&IPPH%ޡ9K$ ^Nw0$:[-yzL0`ggH+****N/lOoPY5J %M8 |ay$ u$ gΑ)n^ /Ti!04#Bd#FZ10K&llu+bEEEŗWu|*cvvqi΁GA 3!%Y69O>M6E'-RJÔY Vkᷟb*שa0<7H) 3< "ÜX(.\^|huxqgEEXm?TWY Rq-⫯1?7gm* Q%Ahc(%PJ5zFrm-jy}8ږ5W:ߟG9Tc ٳga0=JlmtX}ݻ!? qsճ;;35J =J)<@JYy9du%oU.vZ ٝ׭ss)%Q }L&$AҜ?Pt]ǽʵrXCw<+"4z+eԦ9\EqzR|ޯ#6=ݳy.x&r?eY`w 3xy8!T+CW R"`e~< ]VV7yx!z4_ȥ+Z$`Vc SvzDQ ) -3rm8,43($k+< ցs\*@)Ng'" ѡFW׎<]'dN:#%YĿ{4mߧ2ff()*rXxǹʈ)cG 0qK,$_%Iawno~)VWX^>ë_W33[x2FQ,!B@g"5^9VkM,nsUG; 8zN3/{ŋ2CuTST,e[e*>nCl$Kpͽ5 /P ٩gl!K Mr?S5/L!a8wn  \r/07)1.GH( AH% QV`@ʕ+9Vth4vwp3==C3DqOHaJ'ay|\\ޣ0TPN95HZˎ=0BjG ̰Fa*i!XL1BSSMPfڭΧuկ:QFZjv5Hu:d~~VKjmO~1F\ !ymBz#q$IDnBTgN,Ż'dLgǐ24y<~ҫ83lL-w)+,X/c Y:PgFGu©~kzQQa$SyNף뱱9/?}+KјyE`q &z 8@Hoo?^3@ob&r̉Cȼ',qCq>qǻ;>v}{UX~fR܎5r>X-dͩ^N64YEzQL x/AhaJgdC?蟸orWM`rC,I(rX# cov 秉4@Ijޑqo}av/Sqpr-E MQ -]ƫ<*18!ko)Lg@0cd:&@b8!Z{0"͆(QA@Ǥ^p?/XY]xihhm?"RAZˑPy661&w-Μ#c{0X[cqOCYGV)mιcW"6E%rg7mneXnOK7In2NXmO6LvC'wxž?|[Vn?DѨՉcRۈ m/ S P$$a$0$&j5Zܹc _U5"Z- {yH>[ۛܽ{i*ͦד7R heRnI {oI}eGoٓ(/f|/ˌ?nsnPNI.Yڔsi|BL;{n>4+N?&@=+L7̞G a9Hm1+ۻV֎] BTRSAw~[; L*F+9$)ezjgϞGA5|2rhxZk~,ަX(y2?~Y{cg>׸^qNEŁ-dkVY{F$Iĥj6=7O Q]D2 p LRbLZ֚N|r)BhN+XeNZ A 4 )%+++lop;(pt!d[?jEo4#7aw@:{ ʛڮS :埝5X|Hkco}4\0e$7/6kwsbqeg|!'[L/"Ox$Vj8s,󯜥y S3uTX;ȝG#A(Te 1 ff Q\msC4_4q )̢$yS׋aVk07w-67 D WPYB8&UgȻ,d#&qq7(ީ*&ˍE9 8oO|7|Ei{;_Yr y7v2{,|_ rן^iaАxEZO$0$ BRDARAQO15Dngn-%(B\]2P gA Mszso޽z (ƃb߯TEGHg-8M㗍qT^G.E¹B1r 8 oߥZ+cȺm6 sFXe966\b-~ԵƎ+*ʜdN9F{%]?H}})0CJcjj % #fffq_|BO#^ atY&-=e"KLƤSV4gܤyqT%'2^M!fL{rNGOqs*92o.ɲeX·qD#D ;k[ =Hn_{\ RӍ:^!QnIkA 4o|.ZE|[9tBvvr};r8SU.Ҙ:OQ'78]!c+sA$zK%QVŒ<<&n2My~V~nrJ{fc āxk!:n pR@PQiǥ+̜o%Cktc %V IH y뭷LO99nj8'ȲS8o>cvɥb?c~{Ͳq,S 1q\j?0' R20O"։2@R@I "0&;lwnw1;Cd x[_X=\je)67HbiAHΝܹ >g?Cjb=Zk8z>"3(w @-8Hbn%|,}vIK0*SQ3IG59)}K^,":ׁ"QH+PFo DR` 0P|FUU^nXJؼr֑F}3Z8w3gj$ XJy< e{k{wp WN,[f"o.pݥ}ttD9Ӭ(GY+.bPnӼfFԓ{H)q"4uLk?kbU҃ p#:-Byp2c,nvER*.EBAL) 5β9~hpSV2 ^bnOo15seZ% i_PUrPci`cgZ<5eP{ű4;GMRcQJ J33ݤ'H6X^a[mYW?}Ƞ7D 1#7:QB%SaHܽ{WιQ,E0 X'mz)%wΝ;8auؿx{wlTV<wN .q̍4N\Pؓcλw%PL( $:Q@d&9aQ(s,0Y d݌WY~l@QA OѠ1=MܨӘejv`ȇ?iBAB<aZ 4anwx`8]ko+*/ lXŒ9[v56-u$DT8cAKS` BIo@I"kz최_=&!5fecְG<3Ôᣟ׮^YE iJF)aȍ ՙ;ǝ;'_eɖ=Ut_*s,qAeޅ#{Y`oeʉ2'-A{nTr12 D:U1~f=FQ- r3\YOcI}nYfg:ΛLX13TD1OIF@ 2 :jPJ#+Dո-%'[bfŃX.yQ*'Y,y"/K[8l,8{ӘD/h1_FBF/e aqɬZqhT=ⓟ||s_}0fc `i͵u4p/h4vuZ\"YC `#p|7Hi,oys~)×0Ɇic2y`eXK/dJK8<9is/ p-/s9zǙ3tkuKg5}7 II/R@c[-ݻG&)J'Ԛ<$ A1ɮGK|dOcLP.~̔L `2_^lykA=uK2!Q5:SSSt}{{ p%aVQՎ8{i{i̊ˇ#V^4Pe WL?{~82{-BTDhGHܴDϏ3K)Q gAt0lۻ[G<5SPBI)II\;AbsmthHbA0aXDOd\!;LW1G8,<]nV)+dgcq+x?7d=B8+0$ H7%u!6 74'ӜiS31 pzpȰ2U#lmbjq $Rz*EeϬx\kDU!Y`1½TBv0q<5K$>/ߒ;'9v;Ɉ:/ ȜP`%B 8 h-yY%z%"VzLOOsiBHIB tt4$1sԧTx'pQLV(_i!u`2oߣ2,yA5o\;<~&^>at' O8 ,28`$^8 %Vz,,x ]<.wzP!]@͝OnOs@]O>XBㄠјF:Of촶Yy^c9[gR!ϟ1]iM,yJ }\Ɵy|skWLo\WۛYĬLbf}C:vPBh1r(]PxA!=B=#o;:ҝ;[B4A$b09Q f"HdGA[^pQz9G^nR.*7tsk_HB3Í130xn$ǝBwj(,t$*Pwďb5:dma(΢paGg[ymL'@yPB3U1Rj(*kCܻ&*)4HP^} og\3R jb7(iY72ylܢZZ3nr/˔Z8w}|bAaxrB#K0#38PB Ho,{\f0Ì͇KW4QN@*%qバ®$f~sisbts&CY XFA@h@?گxK/Ahk-i֑vܻڃ`=g@"8)WW֎<$BHN=VIV^KQI=|Ie9m$7wBV@zaZG˴A B,<>BD EDAlhVb6ۛ-+a#dBҡ9| %Oe 4[yׄQ9:-|HQXyߠhM&t B!:4*rm8Nh p2#PZЪ m@HQN}2R5dJ;%݁ <^JTޜc Isn8 $"*,cez3ﮘ [2%;[8kׁ4 ^9;-dA@Xrb$$GFh^K-(VjaDQq(VB9P*@ rGKG<w:yc]N^{tOP|(k=y)su Q{w-2~!d,S&ie^1q'c4=LYF9v<S{Իre$}\nhx:Q2=+z;d rAb;C;x 713 Ya;)x8㰹+gYlnpIO!iz^yuիcAkhbtlm"?9:6&23Sp0;,$=vA~Yaukc+bc(=4Ms3ءv '=RK/ by ox 6Rts$S b Y^QiG,h0y^w gFQc8igsvh>m*;&*ǜhY~1Fγ=܆  /̅|2,+X0*Ke8b?Cazސiw@d14;t[ -bA/,Ƥ``7@beAV hLEv}R,Sxsݠ0\g^Z%bGiq0 z=!Εvxx2ilmmQ~;o_"fxK+[\槊 Skqcc4s*)/"B8&Iߺuϟw~d:\>xJ***[EE Q ?pT1+**&A%dρ [x٨2PzlߋTω[QQQQQqTBVQQQQqTS YEEEEũSM%dJ*****N5UTTTTj?_UFIENDB`mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/index.page000066400000000000000000000003531231060417000262270ustar00rootroot00000000000000--- title: MQTT-Client --- name:overview An Open Source Java MQTT v3.1 Client --- name:content pipeline:jade - include("/../../../readme.md") :markdown ## Reference * [MQTT 3.1 Specification](http://mqtt.org/documentation) mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/styles/000077500000000000000000000000001231060417000256045ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/styles/impact/000077500000000000000000000000001231060417000270615ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/styles/impact/css/000077500000000000000000000000001231060417000276515ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client-website/src/styles/impact/css/site.css000066400000000000000000000111331231060417000313260ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ body, html { font-family:Georgia, Arial, sans-serif; color: #666666; } body, html, table, tr, td, tbody { padding:0; margin:0; vertical-align: top; } body { padding-top: 20px; } h1, h2, h3, h4, h5, h6 { font-family: 'Graublau Web', Helvetica, sans-serif; overflow: visible; color: #993333; } h2 { border-top: 4px solid #E0E0E0 !important; margin-top: 1.5em !important; padding-top: 0.5em !important; } p { margin-bottom:0px; } a { color: #990000; font-weight:bold; text-decoration: none; } a:hover { color: #ff3333; text-decoration: underline; } img { border: none; /* padding-right:2em */ } .wrapper { min-width: 762px; width: 762px; margin: 0 auto; } #navigation { width: 100%; float: left; font-family: Helvetica,Verdana,Arial,sans-serif; background: black; text-align:center; padding: 8px 0 8px 0; color: #b55; font-size: 10pt; font-weight: bold; position: absolute; top: 0px; } #navigation a { color: white; } #navigation ul { display: block; margin:0; padding:0; } #navigation li { list-style-type: none; display: inline; margin:0 5px 0 5px;} #overview { width: 100%; padding-top:20px} #overview div.message { font-size: 11pt; margin-top: -5px; padding-left: 50px; width: 350px; } #overview div.message h1{ margin-bottom: 5px; display:none; } #overview div.message p{ margin-top: 0px; padding-bottom:14px; } #spot { width: 100%; float: left; margin-top: 15px; background:transparent url(../images/spot-banner.gif) repeat-x scroll 0 0; height: 277px; } #spot div.title { text-align:center; height:25px; text-align:center; padding-top: 2px; color: white; font-size: 10pt; font-weight: bold; font-family: HelveticaNeue,"Helvetica Neue",Helvetica,Arial,Verdana,sans-serif; } #spot div.content table { width: 100%; text-align:center; color: black; font-size: 10pt; } #spot a:hover {text-decoration: none; } #spot div.spot-balloon { background:transparent url( ../../../images/spot-get-involved.gif ) no-repeat; background-position:center; height: 121px; text-align:left; padding-top: 25px; padding-left: 35px; } #spot div.spot-balloon li { /* list-style: none; */ list-style: disc; } /* #spot div.spot-balloon { height: 120px; text-align:left; padding-top: 20px; padding-left: 15px; } */ #content { width: 100%; float: left; padding-bottom: 20px; } #content .wrapper { min-width: 700px; width: 700px; margin: 0 auto; padding-top: 1em} #content div.left { float:left; width:200px; text-align:right; font-size: 18pt; clear:both; } #content h1 { font-size: 18pt; } #content div.right { float:right; width:450px; text-align:left; } #content .post h2 { margin-bottom:5px; } #content .post .details { color: #ccc; font-size: 10pt; font-family: HelveticaNeue,"Helvetica Neue",Helvetica,Arial,Verdana,sans-serif; margin-top:0px; } .clear { clear:both; } code { font-size: .9em; font-family: 'Droid Sans Mono', 'Courier New', monospace !important; } pre { background-color: #F8F8FF; overflow:auto; -moz-background-clip:border; -moz-background-inline-policy:continuous; -moz-background-origin:padding; margin: 1em 0 1em 0; border:1px solid #DDDDDD; border-top-left-radius: 8px; -webkit-border-top-left-radius: 8px; -moz-border-radius-topleft: 8px; border-top-right-radius: 8px; -webkit-border-top-right-radius: 8px; -moz-border-radius-topright: 8px; border-style: solid; border-width: 1px; border-color: #dedede !important; padding: 1em; } pre code { font-family:Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace; font-weight:normal; font-style:normal; } table.clients td { border:1px solid #DDDDDD; padding:10px; } table.clients td p { margin:0px; } mqtt-client-mqtt-client-project-1.10/mqtt-client/000077500000000000000000000000001231060417000220325ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/pom.xml000077500000000000000000000135621231060417000233610ustar00rootroot00000000000000 4.0.0 org.fusesource.mqtt-client mqtt-client-project 1.10 org.fusesource.mqtt-client mqtt-client 1.10 bundle ${project.artifactId} mqtt-client provides an ASL 2.0 licensed API to MQTT. It takes care of automatically reconnecting to your MQTT server and restoring your client session if any network failures occur. Applications can use a blocking API style, a futures based API, or a callback/continuations passing API style. org.fusesource.hawtdispatch hawtdispatch-transport ${hawtdispatch-version} org.fusesource.hawtbuf hawtbuf ${hawtbuf-version} org.osgi org.osgi.core ${osgi-version} true org.osgi org.osgi.compendium ${osgi-version} true asm asm-tree ${asm-version} true org.apache.activemq apollo-broker test ${apollo-version} org.apache.activemq apollo-mqtt ${apollo-version} test org.apache.activemq apollo-leveldb ${apollo-version} test org.apache.activemq apollo-web ${apollo-version} test org.eclipse.jetty.aggregate jetty-all-server 7.1.6.v20100715 test junit junit test ${junit-version} org.slf4j slf4j-log4j12 ${slf4j-version} test com.github.wvengen proguard-maven-plugin 2.0.5 net.sf.proguard proguard-base 4.8 runtime package proguard 4.8 ${project.build.finalName}.jar ${project.build.finalName}-uber.jar true uber ${rt.jar.path} ${jsse.jar.path} org.fusesource.hawtdispatch hawtdispatch-transport org.fusesource.hawtdispatch hawtdispatch org.fusesource.hawtbuf hawtbuf false mqtt-client-mqtt-client-project-1.10/mqtt-client/src/000077500000000000000000000000001231060417000226215ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/000077500000000000000000000000001231060417000235455ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/000077500000000000000000000000001231060417000244665ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/000077500000000000000000000000001231060417000252555ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/000077500000000000000000000000001231060417000274405ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/000077500000000000000000000000001231060417000304255ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/cli/000077500000000000000000000000001231060417000311745ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/cli/Listener.java000066400000000000000000000241211231060417000336240ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.cli; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.Task; import org.fusesource.mqtt.client.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.concurrent.CountDownLatch; /** *

*

* * @author Hiram Chirino */ public class Listener { private final MQTT mqtt = new MQTT(); private final ArrayList topics = new ArrayList(); private boolean debug; private boolean showTopic; private static void displayHelpAndExit(int exitCode) { stdout(""); stdout("This is a simple mqtt client that will subscribe to topics and print all messages it receives."); stdout(""); stdout("Arguments: [-h host] [-k keepalive] [-c] [-i id] [-u username [-p password]]"); stdout(" [--will-topic topic [--will-payload payload] [--will-qos qos] [--will-retain]]"); stdout(" [-d] [-s]"); stdout(" ( [-q qos] -t topic )+"); stdout(""); stdout(""); stdout(" -h : mqtt host uri to connect to. Defaults to tcp://localhost:1883."); stdout(" -k : keep alive in seconds for this client. Defaults to 60."); stdout(" -c : disable 'clean session' (store subscription and pending messages when client disconnects)."); stdout(" -i : id to use for this client. Defaults to a random id."); stdout(" -u : provide a username (requires MQTT 3.1 broker)"); stdout(" -p : provide a password (requires MQTT 3.1 broker)"); stdout(" --will-topic : the topic on which to publish the client Will."); stdout(" --will-payload : payload for the client Will, which is sent by the broker in case of"); stdout(" unexpected disconnection. If not given and will-topic is set, a zero"); stdout(" length message will be sent."); stdout(" --will-qos : QoS level for the client Will."); stdout(" --will-retain : if given, make the client Will retained."); stdout(" -d : dispaly debug info on stderr"); stdout(" -s : show message topics in output"); stdout(" -q : quality of service level to use for the subscription. Defaults to 0."); stdout(" -t : mqtt topic to subscribe to. May be repeated multiple times."); stdout(" -v : MQTT version to use 3.1 or 3.1.1. (default: 3.1)"); stdout(""); System.exit(exitCode); } private static void stdout(Object x) { System.out.println(x); } private static void stderr(Object x) { System.err.println(x); } private static String shift(LinkedList argl) { if(argl.isEmpty()) { stderr("Invalid usage: Missing argument"); displayHelpAndExit(1); } return argl.removeFirst(); } public static void main(String[] args) throws Exception { Listener main = new Listener(); // Process the arguments QoS qos = QoS.AT_MOST_ONCE; LinkedList argl = new LinkedList(Arrays.asList(args)); while (!argl.isEmpty()) { try { String arg = argl.removeFirst(); if ("--help".equals(arg)) { displayHelpAndExit(0); } else if ("-v".equals(arg)) { main.mqtt.setVersion(shift(argl)); } else if ("-h".equals(arg)) { main.mqtt.setHost(shift(argl)); } else if ("-k".equals(arg)) { main.mqtt.setKeepAlive(Short.parseShort(shift(argl))); } else if ("-c".equals(arg)) { main.mqtt.setCleanSession(false); } else if ("-i".equals(arg)) { main.mqtt.setClientId(shift(argl)); } else if ("-u".equals(arg)) { main.mqtt.setUserName(shift(argl)); } else if ("-p".equals(arg)) { main.mqtt.setPassword(shift(argl)); } else if ("--will-topic".equals(arg)) { main.mqtt.setWillTopic(shift(argl)); } else if ("--will-payload".equals(arg)) { main.mqtt.setWillMessage(shift(argl)); } else if ("--will-qos".equals(arg)) { int v = Integer.parseInt(shift(argl)); if( v > QoS.values().length ) { stderr("Invalid qos value : " + v); displayHelpAndExit(1); } main.mqtt.setWillQos(QoS.values()[v]); } else if ("--will-retain".equals(arg)) { main.mqtt.setWillRetain(true); } else if ("-d".equals(arg)) { main.debug = true; } else if ("-s".equals(arg)) { main.showTopic = true; } else if ("-q".equals(arg)) { int v = Integer.parseInt(shift(argl)); if( v > QoS.values().length ) { stderr("Invalid qos value : " + v); displayHelpAndExit(1); } qos = QoS.values()[v]; } else if ("-t".equals(arg)) { main.topics.add(new Topic(shift(argl), qos)); } else { stderr("Invalid usage: unknown option: " + arg); displayHelpAndExit(1); } } catch (NumberFormatException e) { stderr("Invalid usage: argument not a number"); displayHelpAndExit(1); } } if (main.topics.isEmpty()) { stderr("Invalid usage: no topics specified."); displayHelpAndExit(1); } main.execute(); System.exit(0); } private void execute() { final CallbackConnection connection = mqtt.callbackConnection(); final CountDownLatch done = new CountDownLatch(1); // Handle a Ctrl-C event cleanly. Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { setName("MQTT client shutdown"); if(debug) { stderr("Disconnecting the client."); } connection.getDispatchQueue().execute(new Task() { public void run() { connection.disconnect(new Callback() { public void onSuccess(Void value) { done.countDown(); } public void onFailure(Throwable value) { done.countDown(); } }); } }); } }); connection.listener(new org.fusesource.mqtt.client.Listener() { public void onConnected() { if (debug) { stderr("Connected"); } } public void onDisconnected() { if (debug) { stderr("Disconnected"); } } public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack) { try { if (showTopic) { stdout(""); stdout("Topic: " + topic); body.writeTo(System.out); stdout(""); } else { body.writeTo(System.out); } ack.run(); } catch (IOException e) { onFailure(e); } } public void onFailure(Throwable value) { if (debug) { value.printStackTrace(); } else { stderr(value); } System.exit(2); } }); connection.resume(); connection.connect(new Callback() { public void onFailure(Throwable value) { if (debug) { value.printStackTrace(); } else { stderr(value); } System.exit(2); } public void onSuccess(Void value) { final Topic[] ta = topics.toArray(new Topic[topics.size()]); connection.subscribe(ta, new Callback() { public void onSuccess(byte[] value) { if(debug) { for (int i = 0; i < value.length; i++) { stderr("Subscribed to Topic: " + ta[i].name() + " with QoS: " + QoS.values()[value[i]]); } } } public void onFailure(Throwable value) { stderr("Subscribe failed: " + value); if(debug) { value.printStackTrace(); } System.exit(2); } }); } }); try { done.await(); } catch (Exception e) { e.printStackTrace(); } System.exit(0); } } Publisher.java000066400000000000000000000306371231060417000337260ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/cli/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.cli; import org.fusesource.hawtbuf.AsciiBuffer; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.ByteArrayOutputStream; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.Task; import org.fusesource.mqtt.client.*; import java.io.File; import java.io.RandomAccessFile; import java.util.Arrays; import java.util.LinkedList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** *

*

* * @author Hiram Chirino */ public class Publisher { private final MQTT mqtt = new MQTT(); private QoS qos = QoS.AT_MOST_ONCE; private UTF8Buffer topic; private Buffer body; private boolean debug; private boolean retain; private long count = 1; private long sleep; private boolean prefixCounter; private static void displayHelpAndExit(int exitCode) { stdout(""); stdout("This is a simple mqtt client that will publish to a topic."); stdout(""); stdout("Arguments: [-h host] [-k keepalive] [-c] [-i id] [-u username [-p password]]"); stdout(" [--will-topic topic [--will-payload payload] [--will-qos qos] [--will-retain]]"); stdout(" [-d] [-n count] [-s sleep] [-q qos] [-r] -t topic ( -pc | -m message | -z | -f file )"); stdout(""); stdout(""); stdout(" -h : mqtt host uri to connect to. Defaults to tcp://localhost:1883."); stdout(" -k : keep alive in seconds for this client. Defaults to 60."); stdout(" -c : disable 'clean session'."); stdout(" -i : id to use for this client. Defaults to a random id."); stdout(" -u : provide a username (requires MQTT 3.1 broker)"); stdout(" -p : provide a password (requires MQTT 3.1 broker)"); stdout(" --will-topic : the topic on which to publish the client Will."); stdout(" --will-payload : payload for the client Will, which is sent by the broker in case of"); stdout(" unexpected disconnection. If not given and will-topic is set, a zero"); stdout(" length message will be sent."); stdout(" --will-qos : QoS level for the client Will."); stdout(" --will-retain : if given, make the client Will retained."); stdout(" -d : display debug info on stderr"); stdout(" -n : the number of times to publish the message"); stdout(" -s : the number of milliseconds to sleep between publish operations (defaut: 0)"); stdout(" -q : quality of service level to use for the publish. Defaults to 0."); stdout(" -r : message should be retained."); stdout(" -t : mqtt topic to publish to."); stdout(" -m : message payload to send."); stdout(" -z : send a null (zero length) message."); stdout(" -f : send the contents of a file as the message."); stdout(" -pc : prefix a message counter to the message"); stdout(" -v : MQTT version to use 3.1 or 3.1.1. (default: 3.1)"); stdout(""); System.exit(exitCode); } private static void stdout(Object x) { System.out.println(x); } private static void stderr(Object x) { System.err.println(x); } private static String shift(LinkedList argl) { if(argl.isEmpty()) { stderr("Invalid usage: Missing argument"); displayHelpAndExit(1); } return argl.removeFirst(); } public static void main(String[] args) throws Exception { Publisher main = new Publisher(); // Process the arguments LinkedList argl = new LinkedList(Arrays.asList(args)); while (!argl.isEmpty()) { try { String arg = argl.removeFirst(); if ("--help".equals(arg)) { displayHelpAndExit(0); } else if ("-v".equals(arg)) { main.mqtt.setVersion(shift(argl)); } else if ("-h".equals(arg)) { main.mqtt.setHost(shift(argl)); } else if ("-k".equals(arg)) { main.mqtt.setKeepAlive(Short.parseShort(shift(argl))); } else if ("-c".equals(arg)) { main.mqtt.setCleanSession(false); } else if ("-i".equals(arg)) { main.mqtt.setClientId(shift(argl)); } else if ("-u".equals(arg)) { main.mqtt.setUserName(shift(argl)); } else if ("-p".equals(arg)) { main.mqtt.setPassword(shift(argl)); } else if ("--will-topic".equals(arg)) { main.mqtt.setWillTopic(shift(argl)); } else if ("--will-payload".equals(arg)) { main.mqtt.setWillMessage(shift(argl)); } else if ("--will-qos".equals(arg)) { int v = Integer.parseInt(shift(argl)); if( v > QoS.values().length ) { stderr("Invalid qos value : " + v); displayHelpAndExit(1); } main.mqtt.setWillQos(QoS.values()[v]); } else if ("--will-retain".equals(arg)) { main.mqtt.setWillRetain(true); } else if ("-d".equals(arg)) { main.debug = true; } else if ("-n".equals(arg)) { main.count = Long.parseLong(shift(argl)); } else if ("-s".equals(arg)) { main.sleep = Long.parseLong(shift(argl)); } else if ("-q".equals(arg)) { int v = Integer.parseInt(shift(argl)); if( v > QoS.values().length ) { stderr("Invalid qos value : " + v); displayHelpAndExit(1); } main.qos = QoS.values()[v]; } else if ("-r".equals(arg)) { main.retain = true; } else if ("-t".equals(arg)) { main.topic = new UTF8Buffer(shift(argl)); } else if ("-m".equals(arg)) { main.body = new UTF8Buffer(shift(argl)+"\n"); } else if ("-z".equals(arg)) { main.body = new UTF8Buffer(""); } else if ("-f".equals(arg)) { File file = new File(shift(argl)); RandomAccessFile raf = new RandomAccessFile(file, "r"); try { byte data[] = new byte[(int) raf.length()]; raf.seek(0); raf.readFully(data); main.body = new Buffer(data); } finally { raf.close(); } } else if ("-pc".equals(arg)) { main.prefixCounter = true; } else { stderr("Invalid usage: unknown option: " + arg); displayHelpAndExit(1); } } catch (NumberFormatException e) { stderr("Invalid usage: argument not a number"); displayHelpAndExit(1); } } if (main.topic == null) { stderr("Invalid usage: no topic specified."); displayHelpAndExit(1); } if (main.body == null) { stderr("Invalid usage: -z -m or -f must be specified."); displayHelpAndExit(1); } main.execute(); System.exit(0); } private void execute() { final CallbackConnection connection = mqtt.callbackConnection(); final CountDownLatch done = new CountDownLatch(1); // Handle a Ctrl-C event cleanly. Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { setName("MQTT client shutdown"); connection.getDispatchQueue().execute(new Task() { public void run() { connection.disconnect(new Callback() { public void onSuccess(Void value) { done.countDown(); } public void onFailure(Throwable value) { done.countDown(); } }); } }); } }); connection.listener(new org.fusesource.mqtt.client.Listener() { public void onConnected() { if (debug) { stderr("Connected"); } } public void onDisconnected() { if (debug) { stderr("Disconnected"); } } public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack) { } public void onFailure(Throwable value) { if (debug) { value.printStackTrace(); } else { stderr(value); } System.exit(2); } }); connection.resume(); connection.connect(new Callback() { public void onFailure(Throwable value) { if (debug) { value.printStackTrace(); } else { stderr(value); } System.exit(2); } public void onSuccess(Void value) { } }); new Task() { long sent = 0; public void run() { final Task publish = this; Buffer message = body; if(prefixCounter) { long id = sent + 1; ByteArrayOutputStream os = new ByteArrayOutputStream(message.length + 15); os.write(new AsciiBuffer(Long.toString(id))); os.write(':'); os.write(body); message = os.toBuffer(); } connection.publish(topic, message, qos, retain, new Callback() { public void onSuccess(Void value) { sent ++; if(debug) { stdout("Sent message #"+sent); } if( sent < count ) { if(sleep>0) { System.out.println("Sleeping"); connection.getDispatchQueue().executeAfter(sleep, TimeUnit.MILLISECONDS, publish); } else { connection.getDispatchQueue().execute(publish); } } else { connection.disconnect(new Callback() { public void onSuccess(Void value) { done.countDown(); } public void onFailure(Throwable value) { done.countDown(); } }); } } public void onFailure(Throwable value) { stderr("Publish failed: " + value); if(debug) { value.printStackTrace(); } System.exit(2); } }); } }.run(); try { done.await(); } catch (Exception e) { e.printStackTrace(); } System.exit(0); } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/000077500000000000000000000000001231060417000317035ustar00rootroot00000000000000BlockingConnection.java000066400000000000000000000065461231060417000362520ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.Task; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.fusesource.hawtbuf.Buffer.utf8; /** *

* A blocking Connection interface to MQTT. *

* * @author Hiram Chirino */ public class BlockingConnection { private final FutureConnection next; public BlockingConnection(FutureConnection next) { this.next = next; } public boolean isConnected() { return next.isConnected(); } public void connect() throws Exception { this.next.connect().await(); } public void disconnect() throws Exception { this.next.disconnect().await(); } public void kill() throws Exception { this.next.kill().await(); } public byte[] subscribe(final Topic[] topics) throws Exception { return this.next.subscribe(topics).await(); } public void unsubscribe(final String[] topics) throws Exception { this.next.unsubscribe(topics).await(); } public void unsubscribe(final UTF8Buffer[] topics) throws Exception { this.next.unsubscribe(topics).await(); } public void publish(final UTF8Buffer topic, final Buffer payload, final QoS qos, final boolean retain) throws Exception { this.next.publish(topic, payload, qos, retain).await(); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); //To change body of overridden methods use File | Settings | File Templates. } public void publish(final String topic, final byte[] payload, final QoS qos, final boolean retain) throws Exception { publish(utf8(topic), new Buffer(payload), qos, retain); } public Message receive() throws Exception { return this.next.receive().await(); } /** * @return null if the receive times out. */ public Message receive(long amount, TimeUnit unit) throws Exception { Future receive = this.next.receive(); try { return receive.await(amount, unit); } catch (TimeoutException e) { // Put it back on the queue.. receive.then(new Callback() { public void onSuccess(final Message value) { next.putBackMessage(value); } public void onFailure(Throwable value) { } }); return null; } } public void resume() { next.resume(); } public void suspend() { next.suspend(); } } Callback.java000066400000000000000000000016641231060417000341720ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; /** *

* Function Result that carries one value. *

* * @author Hiram Chirino */ public interface Callback { public void onSuccess(T value); public void onFailure(Throwable value); } CallbackConnection.java000066400000000000000000000775571231060417000362300ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.HexSupport; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.Dispatch; import org.fusesource.hawtdispatch.DispatchQueue; import org.fusesource.hawtdispatch.Task; import org.fusesource.hawtdispatch.transport.*; import org.fusesource.mqtt.codec.MessageSupport.Acked; import org.fusesource.mqtt.codec.*; import javax.net.ssl.SSLContext; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ProtocolException; import java.net.SocketAddress; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.fusesource.hawtbuf.Buffer.utf8; import static org.fusesource.hawtdispatch.Dispatch.createQueue; /** *

* A callback based non/blocking Connection interface to MQTT. *

* * @author Hiram Chirino */ public class CallbackConnection { private static class Request { final MQTTFrame frame; private final short id; final Callback cb; Request(int id, MQTTFrame frame, Callback cb) { this.id = (short) id; this.cb = cb; this.frame = frame; } } private static final Listener DEFAULT_LISTENER = new Listener(){ public void onConnected() { } public void onDisconnected() { } public void onPublish(UTF8Buffer utf8Buffer, Buffer buffer, Runnable runnable) { this.onFailure(createListenerNotSetError()); } public void onFailure(Throwable value) { Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), value); } }; private final DispatchQueue queue; private final MQTT mqtt; private Transport transport; private Listener listener = DEFAULT_LISTENER; private Runnable refiller; private HashMap requests = new HashMap(); private LinkedList overflow = new LinkedList(); private HashSet processed = new HashSet(); private Throwable failure; private boolean disconnected = false; private HeartBeatMonitor heartBeatMonitor; private long pingedAt; private long reconnects = 0; private AtomicInteger suspendCount = new AtomicInteger(0); private AtomicInteger suspendChanges = new AtomicInteger(0); private HashMap activeSubs = new HashMap(); public CallbackConnection(MQTT mqtt) { this.mqtt = mqtt; if(this.mqtt.dispatchQueue == null) { this.queue = createQueue("mqtt client"); } else { this.queue = this.mqtt.dispatchQueue; } } public void connect(final Callback cb) { assert cb !=null : "Callback should not be null."; if( transport!=null ) { cb.onFailure(new IllegalStateException("Already connected")); return; } try { createTransport(new LoginHandler(cb, true)); } catch (Throwable e) { // This error happens when the MQTT config is invalid, reattempting // wont fix this case. cb.onFailure(e); } } void reconnect() { try { // And reconnect. createTransport(new LoginHandler(new Callback() { public void onSuccess(Void value) { mqtt.tracer.debug("Restoring MQTT connection state"); // Setup a new overflow so that the replay can be sent out before the original overflow list. LinkedList originalOverflow = overflow; HashMap originalRequests = requests; overflow = new LinkedList(); requests = new HashMap(); // Restore any active subscriptions. if (!activeSubs.isEmpty()) { ArrayList topics = new ArrayList(activeSubs.size()); for (Map.Entry entry : activeSubs.entrySet()) { topics.add(new Topic(entry.getKey(), entry.getValue())); } send(new SUBSCRIBE().topics(topics.toArray(new Topic[topics.size()])), null); } // Replay any un-acked requests.. for (Map.Entry entry : originalRequests.entrySet()) { MQTTFrame frame = entry.getValue().frame; frame.dup(true); // set the dup flag as these frames were previously transmitted. send(entry.getValue()); } // Replay the original overflow for (Request request : originalOverflow) { // Stuff in the overflow never got sent out.. so no need to set the dup flag send(request); } } public void onFailure(Throwable value) { handleFatalFailure(value); } }, false)); } catch (Throwable e) { handleFatalFailure(e); } } void handleSessionFailure(Throwable error) { // Socket failure, should we try to reconnect? if( !disconnected && (mqtt.reconnectAttemptsMax<0 || reconnects < mqtt.reconnectAttemptsMax ) ) { mqtt.tracer.debug("Reconnecting transport"); // Cleanup the previous transport. if(heartBeatMonitor!=null) { heartBeatMonitor.stop(); heartBeatMonitor = null; } final Transport t = transport; transport = null; if(t!=null) { t.stop(new Task() { public void run() { listener.onDisconnected(); reconnect(); } }); } else { reconnect(); } } else { // nope. handleFatalFailure(error); } } void reconnect(final Callback onConnect) { long reconnectDelay = mqtt.reconnectDelay; if( reconnectDelay> 0 && mqtt.reconnectBackOffMultiplier > 1.0 ) { reconnectDelay = (long) Math.pow(mqtt.reconnectDelay*reconnects, mqtt.reconnectBackOffMultiplier); } reconnectDelay = Math.min(reconnectDelay, mqtt.reconnectDelayMax); reconnects += 1; queue.executeAfter(reconnectDelay, TimeUnit.MILLISECONDS, new Task() { public void run() { if(disconnected) { onConnect.onFailure(createDisconnectedError()); } else { try { createTransport(onConnect); } catch (Exception e) { onConnect.onFailure(e); } } } }); } /** * Creates and start a transport to the MQTT server. Passes it to the onConnect * once the transport is connected. * * @param onConnect * @throws Exception */ void createTransport(final Callback onConnect) throws Exception { mqtt.tracer.debug("Connecting"); String scheme = mqtt.host.getScheme(); final Transport transport; if( "tcp".equals(scheme) ) { transport = new TcpTransport(); } else if( SslTransport.protocol(scheme)!=null ) { SslTransport ssl = new SslTransport(); if( mqtt.sslContext == null ) { mqtt.sslContext = SSLContext.getDefault(); } ssl.setSSLContext(mqtt.sslContext); transport = ssl; } else { throw new Exception("Unsupported URI scheme '"+scheme+"'"); } if( mqtt.blockingExecutor == null ) { mqtt.blockingExecutor = mqtt.getBlockingThreadPool(); } transport.setBlockingExecutor(mqtt.blockingExecutor); transport.setDispatchQueue(queue); transport.setProtocolCodec(new MQTTProtocolCodec()); if( transport instanceof TcpTransport ) { TcpTransport tcp = (TcpTransport)transport; tcp.setMaxReadRate(mqtt.maxReadRate); tcp.setMaxWriteRate(mqtt.maxWriteRate); tcp.setReceiveBufferSize(mqtt.receiveBufferSize); tcp.setSendBufferSize(mqtt.sendBufferSize); tcp.setTrafficClass(mqtt.trafficClass); tcp.setUseLocalHost(mqtt.useLocalHost); tcp.connecting(mqtt.host, mqtt.localAddress); } transport.setTransportListener(new DefaultTransportListener(){ public void onTransportConnected() { mqtt.tracer.debug("Transport connected"); if(disconnected) { onFailure(createDisconnectedError()); } else { onConnect.onSuccess(transport); } } public void onTransportFailure(final IOException error) { mqtt.tracer.debug("Transport failure: %s", error); onFailure(error); } private void onFailure(final Throwable error) { if(!transport.isClosed()) { transport.stop(new Task() { public void run() { onConnect.onFailure(error); } }); } } }); transport.start(NOOP); } class LoginHandler implements Callback { final Callback cb; private final boolean initialConnect; LoginHandler(Callback cb, boolean initialConnect) { this.cb = cb; this.initialConnect = initialConnect; } public void onSuccess(final Transport transport) { transport.setTransportListener(new DefaultTransportListener() { @Override public void onTransportFailure(IOException error) { mqtt.tracer.debug("Transport failure: %s", error); transport.stop(NOOP); onFailure(error); } public void onTransportCommand(Object command) { MQTTFrame response = (MQTTFrame) command; mqtt.tracer.onReceive(response); try { switch (response.messageType()) { case CONNACK.TYPE: CONNACK connack = new CONNACK().decode(response); switch (connack.code()) { case CONNECTION_ACCEPTED: mqtt.tracer.debug("MQTT login accepted"); onSessionEstablished(transport); cb.onSuccess(null); listener.onConnected(); queue.execute(new Task() { public void run() { drainOverflow(); } }); break; default: mqtt.tracer.debug("MQTT login rejected"); // Bad creds or something. No point in reconnecting. transport.stop(NOOP); cb.onFailure(new IOException("Could not connect: " + connack.code())); } break; default: mqtt.tracer.debug("Received unexpected MQTT frame: %d", response.messageType()); // Naughty MQTT server? No point in reconnecting. transport.stop(NOOP); cb.onFailure(new IOException("Could not connect. Received unexpected command: " + response.messageType())); } } catch (ProtocolException e) { mqtt.tracer.debug("Protocol error: %s", e); transport.stop(NOOP); cb.onFailure(e); } } }); transport.resumeRead(); if( mqtt.connect.clientId() == null ) { String id = hex(transport.getLocalAddress())+Long.toHexString(System.currentTimeMillis()/1000); if(id.length() > 23) { id = id.substring(0,23); } mqtt.connect.clientId(utf8(id)); } MQTTFrame encoded = mqtt.connect.encode(); boolean accepted = transport.offer(encoded); mqtt.tracer.onSend(encoded); mqtt.tracer.debug("Logging in"); assert accepted: "First frame should always be accepted by the transport"; } private boolean tryReconnect() { if(initialConnect) { return mqtt.connectAttemptsMax<0 || reconnects < mqtt.connectAttemptsMax; } else { return mqtt.reconnectAttemptsMax<0 || reconnects < mqtt.reconnectAttemptsMax; } } public void onFailure(Throwable value) { // Socket failure, should we try to reconnect? if( !disconnected && tryReconnect() ) { reconnect(this); } else { // nope. cb.onFailure(value); } } } boolean onRefillCalled =false; public void onSessionEstablished(Transport transport) { this.transport = transport; if( suspendCount.get() > 0 ) { this.transport.suspendRead(); } this.transport.setTransportListener(new DefaultTransportListener() { public void onTransportCommand(Object command) { MQTTFrame frame = (MQTTFrame) command; mqtt.tracer.onReceive(frame); processFrame(frame); } public void onRefill() { onRefillCalled =true; drainOverflow(); } public void onTransportFailure(IOException error) { handleSessionFailure(error); } }); pingedAt = 0; if(mqtt.getKeepAlive()>0) { heartBeatMonitor = new HeartBeatMonitor(); heartBeatMonitor.setWriteInterval((mqtt.getKeepAlive() * 1000) / 2); heartBeatMonitor.setTransport(this.transport); heartBeatMonitor.suspendRead(); // to match the suspended state of the transport. heartBeatMonitor.setOnKeepAlive(new Task() { public void run() { // Don't care if the offer is rejected, just means we have data outbound. if(!disconnected && pingedAt==0) { MQTTFrame encoded = new PINGREQ().encode(); if(CallbackConnection.this.transport.offer(encoded)) { mqtt.tracer.onSend(encoded); final long now = System.currentTimeMillis(); final long suspends = suspendChanges.get(); pingedAt = now; queue.executeAfter(CallbackConnection.this.mqtt.getKeepAlive(), TimeUnit.SECONDS, new Task() { public void run() { if (now == pingedAt) { // if the connection remained suspend we will never get the ping response.. // Looks like the user has forgoton to resume the connection if (suspends == suspendChanges.get() && suspendCount.get() > 0) { handleFatalFailure(new IllegalStateException("The connection has remained suspended for an extended period of time so it cannot do proper keep alive processing. Did you forget to resume the connection?")); } else { mqtt.tracer.debug("Ping timeout"); handleSessionFailure(new ProtocolException("Ping timeout").fillInStackTrace()); } } } }); } } } }); heartBeatMonitor.start(); } } public Transport transport() { return transport; } public DispatchQueue getDispatchQueue() { return queue; } public void resume() { suspendChanges.incrementAndGet(); if( suspendCount.decrementAndGet() == 0 && this.transport!=null ) { this.transport.resumeRead(); if(this.heartBeatMonitor!=null){ this.heartBeatMonitor.resumeRead(); } } } public void suspend() { suspendChanges.incrementAndGet(); if( suspendCount.incrementAndGet() == 1 && this.transport!=null ) { this.transport.suspendRead(); if(this.heartBeatMonitor!=null){ this.heartBeatMonitor.suspendRead(); } } } public CallbackConnection refiller(Runnable refiller) { queue.assertExecuting(); this.refiller = refiller; return this; } public CallbackConnection listener(Listener listener) { this.listener = listener; return this; } public boolean full() { queue.assertExecuting(); return this.transport.full(); } public Throwable failure() { queue.assertExecuting(); return failure; } public void disconnect(final Callback onComplete) { if( disconnected ) { if(onComplete!=null){ onComplete.onSuccess(null); } return; } disconnected = true; final short requestId = getNextMessageId(); final Runnable stop = new Runnable() { boolean executed = false; public void run() { if(!executed) { executed = true; requests.remove(requestId); if(heartBeatMonitor!=null) { heartBeatMonitor.stop(); heartBeatMonitor = null; } transport.stop(new Task() { public void run() { listener.onDisconnected(); if (onComplete != null) { onComplete.onSuccess(null); } } }); } } }; Callback cb = new Callback() { public void onSuccess(Void v) { // To make sure DISCONNECT has been flushed out to the socket onRefillCalled = false; refiller = new Runnable() { public void run() { if(onRefillCalled) { stop.run(); } } }; if(transport != null){ transport.flush(); } } public void onFailure(Throwable value) { stop.run(); } }; // Pop the frame into a request so it we get notified // of any failures so we continue to stop the transport. if(transport!=null) { MQTTFrame frame = new DISCONNECT().encode(); send(new Request(getNextMessageId(), frame, cb)); } else { cb.onSuccess(null); } } /** * Kills the connection without a graceful disconnect. * @param onComplete */ public void kill(final Callback onComplete) { if( disconnected ) { if(onComplete!=null){ onComplete.onSuccess(null); } return; } disconnected = true; if(heartBeatMonitor!=null) { heartBeatMonitor.stop(); heartBeatMonitor = null; } transport.stop(new Task() { public void run() { listener.onDisconnected(); if (onComplete != null) { onComplete.onSuccess(null); } } }); } public void publish(String topic, byte[] payload, QoS qos, boolean retain, Callback cb) { publish(utf8(topic), new Buffer(payload), qos, retain, cb); } public void publish(UTF8Buffer topic, Buffer payload, QoS qos, boolean retain, Callback cb) { queue.assertExecuting(); if( disconnected ) { cb.onFailure(createDisconnectedError()); return; } PUBLISH command = new PUBLISH().qos(qos).retain(retain); command.topicName(topic).payload(payload); send(command, cb); } public void subscribe(final Topic[] topics, Callback cb) { if(topics==null) { throw new IllegalArgumentException("topics must not be null"); } queue.assertExecuting(); if( disconnected ) { cb.onFailure(createDisconnectedError()); return; } if( listener == DEFAULT_LISTENER ) { cb.onFailure(createListenerNotSetError()); } else { send(new SUBSCRIBE().topics(topics), new ProxyCallback(cb){ public void onSuccess(byte[] value) { for (Topic topic : topics) { activeSubs.put(topic.name(), topic.qos()); } if(next!=null) { next.onSuccess(value); } } }); } } public void unsubscribe(final UTF8Buffer[] topics, Callback cb) { queue.assertExecuting(); if( disconnected ) { cb.onFailure(createDisconnectedError()); return; } send(new UNSUBSCRIBE().topics(topics), new ProxyCallback(cb){ public void onSuccess(Object value) { for (UTF8Buffer topic : topics) { activeSubs.remove(topic); } if(next!=null) { next.onSuccess(value); } } }); } private void send(Acked command, Callback cb) { short id = 0; if(command.qos() != QoS.AT_MOST_ONCE) { id = getNextMessageId(); command.messageId(id); } send(new Request(id, command.encode(), cb)); } private void send(Request request) { if( failure !=null ) { if( request.cb!=null ) { request.cb.onFailure(failure); } } else { if( overflow.isEmpty() && transport!=null && transport.offer(request.frame) ) { mqtt.tracer.onSend(request.frame); if(request.id==0) { if( request.cb!=null ) { ((Callback)request.cb).onSuccess(null); } } else { this.requests.put(request.id, request); } } else { overflow.addLast(request); } } } short nextMessageId = 1; private short getNextMessageId() { short rc = nextMessageId; nextMessageId++; if(nextMessageId==0) { nextMessageId=1; } return rc; } private void drainOverflow() { queue.assertExecuting(); if( overflow.isEmpty() || transport==null ){ return; } Request request; while((request=overflow.peek())!=null) { if( this.transport.offer(request.frame) ) { mqtt.tracer.onSend(request.frame); overflow.removeFirst(); if(request.id==0) { if( request.cb!=null ) { ((Callback)request.cb).onSuccess(null); } } else { this.requests.put(request.id, request); } } else { break; } } if( overflow.isEmpty() ) { if( refiller!=null ) { try { refiller.run(); } catch (Throwable e) { Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); } } } } private void completeRequest(short id, byte originalType, Object arg) { Request request = requests.remove(id); if( request!=null ) { assert originalType==request.frame.messageType(); if(request.cb!=null) { if( arg==null ) { ((Callback)request.cb).onSuccess(null); } else { ((Callback)request.cb).onSuccess(arg); } } } else { handleFatalFailure(new ProtocolException("Command from server contained an invalid message id: " + id)); } } private void processFrame(MQTTFrame frame) { try { switch(frame.messageType()) { case PUBLISH.TYPE: { PUBLISH publish = new PUBLISH().decode(frame); toReceiver(publish); break; } case PUBREL.TYPE:{ PUBREL ack = new PUBREL().decode(frame); processed.remove(ack.messageId()); PUBCOMP response = new PUBCOMP(); response.messageId(ack.messageId()); send(new Request(0, response.encode(), null)); break; } case PUBACK.TYPE:{ PUBACK ack = new PUBACK().decode(frame); completeRequest(ack.messageId(), PUBLISH.TYPE, null); break; } case PUBREC.TYPE:{ PUBREC ack = new PUBREC().decode(frame); PUBREL response = new PUBREL(); response.messageId(ack.messageId()); send(new Request(0, response.encode(), null)); break; } case PUBCOMP.TYPE:{ PUBCOMP ack = new PUBCOMP().decode(frame); completeRequest(ack.messageId(), PUBLISH.TYPE, null); break; } case SUBACK.TYPE: { SUBACK ack = new SUBACK().decode(frame); completeRequest(ack.messageId(), SUBSCRIBE.TYPE, ack.grantedQos()); break; } case UNSUBACK.TYPE: { UNSUBACK ack = new UNSUBACK().decode(frame); completeRequest(ack.messageId(), UNSUBSCRIBE.TYPE, null); break; } case PINGRESP.TYPE: { pingedAt = 0; break; } default: throw new ProtocolException("Unexpected MQTT command type: "+frame.messageType()); } } catch (Throwable e) { handleFatalFailure(e); } } static public final Task NOOP = Dispatch.NOOP; private void toReceiver(final PUBLISH publish) { if( listener !=null ) { try { Runnable cb = NOOP; switch( publish.qos() ) { case AT_LEAST_ONCE: cb = new Runnable() { public void run() { PUBACK response = new PUBACK(); response.messageId(publish.messageId()); send(new Request(0, response.encode(), null)); } }; break; case EXACTLY_ONCE: cb = new Runnable() { public void run() { PUBREC response = new PUBREC(); response.messageId(publish.messageId()); processed.add(publish.messageId()); send(new Request(0, response.encode(), null)); } }; // It might be a dup. if( processed.contains(publish.messageId()) ) { cb.run(); return; } break; case AT_MOST_ONCE: } listener.onPublish(publish.topicName(), publish.payload(), cb); } catch (Throwable e) { handleFatalFailure(e); } } } private void handleFatalFailure(Throwable error) { if( failure == null ) { failure = error; mqtt.tracer.debug("Fatal connection failure: %s", error); // Fail incomplete requests. ArrayList values = new ArrayList(requests.values()); requests.clear(); for (Request value : values) { if( value.cb!= null ) { value.cb.onFailure(failure); } } ArrayList overflowEntries = new ArrayList(overflow); overflow.clear(); for (Request entry : overflowEntries) { if( entry.cb !=null ) { entry.cb.onFailure(failure); } } if( listener !=null && !disconnected ) { try { listener.onFailure(failure); } catch (Exception e) { Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); } } } } private static IllegalStateException createListenerNotSetError() { return (IllegalStateException) new IllegalStateException("No connection listener set to handle message received from the server.").fillInStackTrace(); } private static IllegalStateException createDisconnectedError() { return (IllegalStateException) new IllegalStateException("Disconnected").fillInStackTrace(); } static private String hex(SocketAddress address) { if( address instanceof InetSocketAddress ) { InetSocketAddress isa = (InetSocketAddress)address; return HexSupport.toHexFromBuffer(new Buffer(isa.getAddress().getAddress()))+Integer.toHexString(isa.getPort()); } return ""; } } Future.java000066400000000000000000000020111231060417000337330ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import java.util.concurrent.TimeUnit; /** *

A simplified Future function results interface.

* * @author Hiram Chirino */ public interface Future { T await() throws Exception; T await(long amount, TimeUnit unit) throws Exception; void then(Callback callback); } FutureConnection.java000066400000000000000000000135741231060417000357730ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.DispatchQueue; import org.fusesource.hawtdispatch.Task; import java.util.ArrayList; import java.util.LinkedList; import static org.fusesource.hawtbuf.Buffer.utf8; /** *

* A Future based optionally-blocking Connection interface to MQTT. *

* * @author Hiram Chirino */ public class FutureConnection { private final CallbackConnection next; private LinkedList> receiveFutures = new LinkedList>(); private LinkedList receivedFrames = new LinkedList(); volatile boolean connected; public FutureConnection(CallbackConnection next) { this.next = next; this.next.listener(new Listener() { public void onConnected() { connected = true; } public void onDisconnected() { connected = false; } public void onPublish(UTF8Buffer topic, Buffer payload, Runnable onComplete) { getDispatchQueue().assertExecuting(); deliverMessage(new Message(getDispatchQueue(), topic, payload, onComplete)); } public void onFailure(Throwable value) { getDispatchQueue().assertExecuting(); ArrayList> tmp = new ArrayList>(receiveFutures); receiveFutures.clear(); for (Promise future : tmp) { future.onFailure(value); } connected = false; } }); } void deliverMessage(Message msg) { if( receiveFutures.isEmpty() ) { receivedFrames.add(msg); } else { receiveFutures.removeFirst().onSuccess(msg); } } void putBackMessage(Message msg) { if( receiveFutures.isEmpty() ) { receivedFrames.addFirst(msg); } else { receiveFutures.removeFirst().onSuccess(msg); } } public boolean isConnected() { return connected; } public DispatchQueue getDispatchQueue() { return this.next.getDispatchQueue(); } public Future connect() { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.connect(future); } }); return future; } public Future disconnect() { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.disconnect(future); } }); return future; } public Future kill() { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.kill(future); } }); return future; } public Future subscribe(final Topic[] topics) { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.subscribe(topics, future); } }); return future; } public Future unsubscribe(final String[] topics) { UTF8Buffer[] buffers = new UTF8Buffer[topics.length]; for (int i = 0; i < buffers.length; i++) { buffers[i] = new UTF8Buffer(topics[i]); } return unsubscribe(buffers); } public Future unsubscribe(final UTF8Buffer[] topics) { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.unsubscribe(topics, future); } }); return future; } public Future publish(final String topic, final byte[] payload, final QoS qos, final boolean retain) { return publish(utf8(topic), new Buffer(payload), qos, retain); } public Future publish(final UTF8Buffer topic, final Buffer payload, final QoS qos, final boolean retain) { final Promise future = new Promise(); next.getDispatchQueue().execute(new Task() { public void run() { next.publish(topic, payload, qos, retain, future); } }); return future; } public Future receive() { final Promise future = new Promise(); getDispatchQueue().execute(new Task(){ public void run() { if( next.failure()!=null ) { future.onFailure(next.failure()); } else { if( receivedFrames.isEmpty() ) { receiveFutures.add(future); } else { future.onSuccess(receivedFrames.removeFirst()); } } } }); return future; } public void resume() { next.resume(); } public void suspend() { next.suspend(); } } Listener.java000066400000000000000000000020741231060417000342570ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.UTF8Buffer; /** *

*

* * @author Hiram Chirino */ public interface Listener { public void onConnected(); public void onDisconnected(); public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack); public void onFailure(Throwable value); } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/MQTT.java000066400000000000000000000260041231060417000333350ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.DispatchQueue; import org.fusesource.hawtdispatch.transport.*; import org.fusesource.mqtt.codec.CONNECT; import javax.net.ssl.SSLContext; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.List; import java.util.concurrent.*; import static org.fusesource.hawtbuf.Buffer.utf8; import static org.fusesource.hawtdispatch.Dispatch.createQueue; /** *

*

* * @author Hiram Chirino */ public class MQTT { private static final long KEEP_ALIVE = Long.parseLong(System.getProperty("mqtt.thread.keep_alive", ""+1000)); private static final long STACK_SIZE = Long.parseLong(System.getProperty("mqtt.thread.stack_size", ""+1024*512)); private static ThreadPoolExecutor blockingThreadPool; public synchronized static ThreadPoolExecutor getBlockingThreadPool() { if( blockingThreadPool == null ) { blockingThreadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE, KEEP_ALIVE, TimeUnit.MILLISECONDS, new SynchronousQueue(), new ThreadFactory() { public Thread newThread(Runnable r) { Thread rc = new Thread(null, r, "MQTT Task", STACK_SIZE); rc.setDaemon(true); return rc; } }) { @Override public void shutdown() { // we don't ever shutdown since we are shared.. } @Override public List shutdownNow() { // we don't ever shutdown since we are shared.. return Collections.emptyList(); } }; } return blockingThreadPool; } public synchronized static void setBlockingThreadPool(ThreadPoolExecutor pool) { blockingThreadPool = pool; } private static final URI DEFAULT_HOST = createDefaultHost(); private static URI createDefaultHost() { try { return new URI("tcp://127.0.0.1:1883"); } catch (URISyntaxException e) { return null; } } URI host = DEFAULT_HOST; URI localAddress; SSLContext sslContext; DispatchQueue dispatchQueue; Executor blockingExecutor; int maxReadRate; int maxWriteRate; int trafficClass = TcpTransport.IPTOS_THROUGHPUT; int receiveBufferSize = 1024*64; int sendBufferSize = 1024*64; boolean useLocalHost = true; CONNECT connect = new CONNECT(); long reconnectDelay = 10; long reconnectDelayMax = 30*1000; double reconnectBackOffMultiplier = 2.0f; long reconnectAttemptsMax = -1; long connectAttemptsMax = -1; Tracer tracer = new Tracer(); public MQTT() { } public MQTT(MQTT other) { this.host = other.host; this.localAddress = other.localAddress; this.sslContext = other.sslContext; this.dispatchQueue = other.dispatchQueue; this.blockingExecutor = other.blockingExecutor; this.maxReadRate = other.maxReadRate; this.maxWriteRate = other.maxWriteRate; this.trafficClass = other.trafficClass; this.receiveBufferSize = other.receiveBufferSize; this.sendBufferSize = other.sendBufferSize; this.useLocalHost = other.useLocalHost; this.connect = new CONNECT(other.connect); this.reconnectDelay = other.reconnectDelay; this.reconnectDelayMax = other.reconnectDelayMax; this.reconnectBackOffMultiplier = other.reconnectBackOffMultiplier; this.reconnectAttemptsMax = other.reconnectAttemptsMax; this.connectAttemptsMax = other.connectAttemptsMax; this.tracer = other.tracer; } public CallbackConnection callbackConnection() { if( !isCleanSession() && ( getClientId()==null || getClientId().length==0 )) { throw new IllegalArgumentException("The client id MUST be configured when clean session is set to false"); } return new CallbackConnection(new MQTT(this)); } public FutureConnection futureConnection() { return new FutureConnection(callbackConnection()); } public BlockingConnection blockingConnection() { return new BlockingConnection(futureConnection()); } public UTF8Buffer getClientId() { return connect.clientId(); } public short getKeepAlive() { return connect.keepAlive(); } public UTF8Buffer getPassword() { return connect.password(); } public byte getType() { return connect.messageType(); } public UTF8Buffer getUserName() { return connect.userName(); } public UTF8Buffer getWillMessage() { return connect.willMessage(); } public QoS getWillQos() { return connect.willQos(); } public UTF8Buffer getWillTopic() { return connect.willTopic(); } public boolean isCleanSession() { return connect.cleanSession(); } public boolean isWillRetain() { return connect.willRetain(); } public void setCleanSession(boolean cleanSession) { connect.cleanSession(cleanSession); } public void setClientId(String clientId) { this.setClientId(utf8(clientId)); } public void setClientId(UTF8Buffer clientId) { connect.clientId(clientId); } public void setKeepAlive(short keepAlive) { connect.keepAlive(keepAlive); } public void setPassword(String password) { this.setPassword(utf8(password)); } public void setPassword(UTF8Buffer password) { connect.password(password); } public void setUserName(String userName) { this.setUserName(utf8(userName)); } public void setUserName(UTF8Buffer userName) { connect.userName(userName); } public void setWillMessage(String willMessage) { connect.willMessage(utf8(willMessage)); } public void setWillMessage(UTF8Buffer willMessage) { connect.willMessage(willMessage); } public void setWillQos(QoS willQos) { connect.willQos(willQos); } public void setVersion(String version) { if( "3.1".equals(version) ) { connect.version(3); } else if( "3.1.1".equals(version) ) { connect.version(4); } } public String getVersion() { switch(connect.version()) { case 3: return "3.1"; case 4: return "3.1.1"; default: return "unknown"; } } public void setWillRetain(boolean willRetain) { connect.willRetain(willRetain); } public void setWillTopic(String willTopic) { this.setWillTopic(utf8(willTopic)); } public void setWillTopic(UTF8Buffer willTopic) { connect.willTopic(willTopic); } public Executor getBlockingExecutor() { return blockingExecutor; } public void setBlockingExecutor(Executor blockingExecutor) { this.blockingExecutor = blockingExecutor; } public DispatchQueue getDispatchQueue() { return dispatchQueue; } public void setDispatchQueue(DispatchQueue dispatchQueue) { this.dispatchQueue = dispatchQueue; } public URI getLocalAddress() { return localAddress; } public void setLocalAddress(String localAddress) throws URISyntaxException { this.setLocalAddress(new URI(localAddress)); } public void setLocalAddress(URI localAddress) { this.localAddress = localAddress; } public int getMaxReadRate() { return maxReadRate; } public void setMaxReadRate(int maxReadRate) { this.maxReadRate = maxReadRate; } public int getMaxWriteRate() { return maxWriteRate; } public void setMaxWriteRate(int maxWriteRate) { this.maxWriteRate = maxWriteRate; } public int getReceiveBufferSize() { return receiveBufferSize; } public void setReceiveBufferSize(int receiveBufferSize) { this.receiveBufferSize = receiveBufferSize; } public URI getHost() { return host; } public void setHost(String host, int port) throws URISyntaxException { this.setHost(new URI("tcp://"+host+":"+port)); } public void setHost(String host) throws URISyntaxException { this.setHost(new URI(host)); } public void setHost(URI host) { this.host = host; } public int getSendBufferSize() { return sendBufferSize; } public void setSendBufferSize(int sendBufferSize) { this.sendBufferSize = sendBufferSize; } public SSLContext getSslContext() { return sslContext; } public void setSslContext(SSLContext sslContext) { this.sslContext = sslContext; } public int getTrafficClass() { return trafficClass; } public void setTrafficClass(int trafficClass) { this.trafficClass = trafficClass; } public boolean isUseLocalHost() { return useLocalHost; } public void setUseLocalHost(boolean useLocalHost) { this.useLocalHost = useLocalHost; } public long getConnectAttemptsMax() { return connectAttemptsMax; } public void setConnectAttemptsMax(long connectAttemptsMax) { this.connectAttemptsMax = connectAttemptsMax; } public long getReconnectAttemptsMax() { return reconnectAttemptsMax; } public void setReconnectAttemptsMax(long reconnectAttemptsMax) { this.reconnectAttemptsMax = reconnectAttemptsMax; } public double getReconnectBackOffMultiplier() { return reconnectBackOffMultiplier; } public void setReconnectBackOffMultiplier(double reconnectBackOffMultiplier) { this.reconnectBackOffMultiplier = reconnectBackOffMultiplier; } public long getReconnectDelay() { return reconnectDelay; } public void setReconnectDelay(long reconnectDelay) { this.reconnectDelay = reconnectDelay; } public long getReconnectDelayMax() { return reconnectDelayMax; } public void setReconnectDelayMax(long reconnectDelayMax) { this.reconnectDelayMax = reconnectDelayMax; } public Tracer getTracer() { return tracer; } public void setTracer(Tracer tracer) { this.tracer = tracer; } } Message.java000066400000000000000000000040501231060417000340520ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.hawtdispatch.DispatchQueue; import org.fusesource.hawtdispatch.TaskWrapper; /** *

*

* * @author Hiram Chirino */ public class Message { private UTF8Buffer topic; private Buffer payload; private Runnable onComplete; private DispatchQueue queue; public Message(DispatchQueue queue, UTF8Buffer topic, Buffer payload, Runnable onComplete) { this.queue = queue; this.payload = payload; this.topic = topic; this.onComplete = onComplete; } public byte[] getPayload() { return payload.toByteArray(); } /** * Using getPayloadBuffer() is lower overhead version of getPayload() * since it avoids a byte array copy. * @return */ public Buffer getPayloadBuffer() { return payload; } public String getTopic() { return topic.toString(); } /** * Using getTopicBuffer is lower overhead version of getTopic() * since it avoid doing UTF-8 decode. * @return */ public UTF8Buffer getTopicBuffer() { return topic; } public void ack() { if(onComplete!=null) { queue.execute(new TaskWrapper(onComplete)); onComplete = null; } } } Promise.java000066400000000000000000000055721231060417000341160ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** *

*

* * @author Hiram Chirino */ public class Promise implements Callback, Future { private final CountDownLatch latch = new CountDownLatch(1); Callback next; Throwable error; T value; public void onFailure(Throwable value) { Callback callback = null; synchronized(this) { error = value; latch.countDown(); callback = next; } if( callback!=null ) { callback.onFailure(value); } } public void onSuccess(T value) { Callback callback = null; synchronized(this) { this.value = value; latch.countDown(); callback = next; } if( callback!=null ) { callback.onSuccess(value); } } public void then(Callback callback) { boolean fire = false; synchronized(this) { next = callback; if( latch.getCount() == 0 ) { fire = true; } } if( fire ) { if( error!=null ) { callback.onFailure(error); } else { callback.onSuccess(value); } } } public T await(long amount, TimeUnit unit) throws Exception { if( latch.await(amount, unit) ) { return get(); } else { throw new TimeoutException(); } } public T await() throws Exception { latch.await(); return get(); } private T get() throws Exception { Throwable e = error; if( e !=null ) { if( e instanceof RuntimeException ) { throw (RuntimeException) e; } else if( e instanceof Exception) { throw (Exception) e; } else if( e instanceof Error) { throw (Error) e; } else { // don't expect to hit this case. throw new RuntimeException(e); } } return value; } } ProxyCallback.java000066400000000000000000000023361231060417000352310ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; /** *

* Function Result that carries one value. *

* * @author Hiram Chirino */ public class ProxyCallback implements Callback { public final Callback next; public ProxyCallback(Callback next) { this.next = next; } public void onSuccess(T value) { if( next!=null ) { next.onSuccess(value); } } public void onFailure(Throwable value) { if( next!=null ) { next.onFailure(value); } } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/QoS.java000066400000000000000000000015351231060417000332540ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; /** *

*

* * @author Hiram Chirino */ public enum QoS { AT_MOST_ONCE, AT_LEAST_ONCE, EXACTLY_ONCE } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/Topic.java000066400000000000000000000035431231060417000336310ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.hawtbuf.UTF8Buffer; /** *

*

* * @author Hiram Chirino */ public class Topic { private final UTF8Buffer name; private final QoS qos; public Topic(String name, QoS qos) { this(new UTF8Buffer(name), qos); } public Topic(UTF8Buffer name, QoS qos) { this.name = name; this.qos = qos; } public UTF8Buffer name() { return name; } public QoS qos() { return qos; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Topic)) return false; Topic topic = (Topic) o; if (name != null ? !name.equals(topic.name) : topic.name != null) return false; if (qos != topic.qos) return false; return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (qos != null ? qos.hashCode() : 0); return result; } @Override public String toString() { return "{ name=" + name + ", qos=" + qos + " }"; } } Tracer.java000066400000000000000000000025101231060417000337050ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import org.fusesource.mqtt.codec.MQTTFrame; /** * A subclass of this can be configured on an MQTT connection to * get more insight into what it's doing. */ public class Tracer { /** * Override to log/capture debug level messages * @param message * @param args */ public void debug(String message, Object...args) { } /** * Called when a MQTTFrame sent to the remote peer. * @param frame */ public void onSend(MQTTFrame frame) { } /** * Called when a MQTTFrame is received from the remote peer. * @param frame */ public void onReceive(MQTTFrame frame) { } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/000077500000000000000000000000001231060417000315025ustar00rootroot00000000000000CONNACK.java000066400000000000000000000050731231060417000333470ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.*; import java.io.IOException; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class CONNACK implements Message { public static final byte TYPE = 2; public static enum Code { CONNECTION_ACCEPTED, CONNECTION_REFUSED_UNACCEPTED_PROTOCOL_VERSION, CONNECTION_REFUSED_IDENTIFIER_REJECTED, CONNECTION_REFUSED_SERVER_UNAVAILABLE, CONNECTION_REFUSED_BAD_USERNAME_OR_PASSWORD, CONNECTION_REFUSED_NOT_AUTHORIZED; } private Code code = Code.CONNECTION_ACCEPTED; public byte messageType() { return TYPE; } public CONNACK decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); is.skip(1); byte c = is.readByte(); if( c >= Code.values().length ) { throw new ProtocolException("Invalid CONNACK encoding"); } code = Code.values()[c]; return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(2); os.writeByte(0); os.writeByte(code.ordinal()); MQTTFrame frame = new MQTTFrame(); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } public Code code() { return code; } public CONNACK code(Code code) { this.code = code; return this; } @Override public String toString() { return "CONNACK{" + "code=" + code + '}'; } } CONNECT.java000066400000000000000000000204311231060417000333570ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.io.IOException; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.Message; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.mqtt.client.QoS; /** *

*

* * @author Hiram Chirino */ public class CONNECT implements Message { public static final byte TYPE = 1; private static final UTF8Buffer V3_PROTOCOL_NAME = new UTF8Buffer("MQIsdp"); private static final UTF8Buffer V4_PROTOCOL_NAME = new UTF8Buffer("MQTT"); private short keepAlive = 30; private UTF8Buffer clientId; private UTF8Buffer willTopic; private UTF8Buffer willMessage = new UTF8Buffer(""); private boolean willRetain; private byte willQos; private boolean cleanSession = true; private UTF8Buffer userName; private UTF8Buffer password; private int version = 3; public CONNECT(){ } public CONNECT(CONNECT other) { this.keepAlive = other.keepAlive; this.clientId = other.clientId; this.willTopic = other.willTopic; this.willMessage = other.willMessage; this.willRetain = other.willRetain; this.willQos = other.willQos; this.cleanSession = other.cleanSession; this.userName = other.userName; this.password = other.password; this.version = other.version; } public byte messageType() { return TYPE; } public CONNECT decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); UTF8Buffer protocolName = MessageSupport.readUTF(is); if (V4_PROTOCOL_NAME.equals(protocolName)) { version = is.readByte() & 0xFF; if( version < 4 ) { throw new ProtocolException("Invalid CONNECT frame: protocol name/version mismatch"); } } else if( V3_PROTOCOL_NAME.equals(protocolName) ) { version = is.readByte() & 0xFF; if( version != 3 ) { throw new ProtocolException("Invalid CONNECT frame: protocol name/version mismatch"); } } else { throw new ProtocolException("Invalid CONNECT frame"); } byte flags = is.readByte(); boolean username_flag = (flags & 0x80) > 0; boolean password_flag = (flags & 0x40) > 0; willRetain = (flags & 0x20) > 0; willQos = (byte) ((flags & 0x18) >>> 3); boolean will_flag = (flags & 0x04) > 0; cleanSession = (flags & 0x02) > 0; keepAlive = is.readShort(); clientId = MessageSupport.readUTF(is); if( clientId.length == 0 ) { clientId = null; } if(will_flag) { willTopic = MessageSupport.readUTF(is); willMessage = MessageSupport.readUTF(is); } if( username_flag ) { userName = MessageSupport.readUTF(is); } if( password_flag ) { password = MessageSupport.readUTF(is); } return this; } public MQTTFrame encode() { try { if( (clientId==null || clientId.length == 0) && !cleanSession ) { throw new IllegalArgumentException("A clean session must be used when no clientId is specified"); } DataByteArrayOutputStream os = new DataByteArrayOutputStream(500); if(version==3) { MessageSupport.writeUTF(os, V3_PROTOCOL_NAME); os.writeByte(version); } else if(version >= 4) { MessageSupport.writeUTF(os, V4_PROTOCOL_NAME); os.writeByte(version); } else { throw new IllegalArgumentException("Invalid version: "+version); } int flags = 0; if(userName!=null) { flags |= 0x80; } if(password!=null) { flags |= 0x40; } if(willTopic!=null && willMessage!=null) { flags |= 0x04; if(willRetain) { flags |= 0x20; } flags |= (willQos << 3) & 0x18; } if(cleanSession) { flags |= 0x02; } os.writeByte(flags); os.writeShort(keepAlive); MessageSupport.writeUTF(os, clientId); if(willTopic!=null && willMessage!=null) { MessageSupport.writeUTF(os, willTopic); MessageSupport.writeUTF(os, willMessage); } if(userName!=null) { MessageSupport.writeUTF(os, userName); } if(password!=null) { MessageSupport.writeUTF(os, password); } MQTTFrame frame = new MQTTFrame(); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } public boolean cleanSession() { return cleanSession; } public CONNECT cleanSession(boolean cleanSession) { this.cleanSession = cleanSession; return this; } public UTF8Buffer clientId() { return clientId; } public CONNECT clientId(UTF8Buffer clientId) { this.clientId = clientId; return this; } public short keepAlive() { return keepAlive; } public CONNECT keepAlive(short keepAlive) { this.keepAlive = keepAlive; return this; } public UTF8Buffer password() { return password; } public CONNECT password(UTF8Buffer password) { this.password = password; return this; } public UTF8Buffer userName() { return userName; } public CONNECT userName(UTF8Buffer userName) { this.userName = userName; return this; } public UTF8Buffer willMessage() { return willMessage; } public CONNECT willMessage(UTF8Buffer willMessage) { this.willMessage = willMessage; return this; } public QoS willQos() { return QoS.values()[willQos]; } public CONNECT willQos(QoS willQos) { this.willQos = (byte) willQos.ordinal(); return this; } public boolean willRetain() { return willRetain; } public CONNECT willRetain(boolean willRetain) { this.willRetain = willRetain; return this; } public UTF8Buffer willTopic() { return willTopic; } public CONNECT willTopic(UTF8Buffer willTopic) { this.willTopic = willTopic; return this; } public int version() { return version; } public CONNECT version(int version) { if(version==3) { this.version = version; } else if(version >= 4) { this.version = version; } else { throw new IllegalArgumentException("Invalid version: "+version); } return this; } @Override public String toString() { return "CONNECT{" + "cleanSession=" + cleanSession + ", keepAlive=" + keepAlive + ", clientId=" + clientId + ", willTopic=" + willTopic + ", willMessage=" + willMessage + ", willRetain=" + willRetain + ", willQos=" + willQos + ", userName=" + userName + ", password=" + password + '}'; } } DISCONNECT.java000066400000000000000000000023751231060417000337260ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class DISCONNECT extends EmptyBase implements Message { public static final byte TYPE = 14; public byte messageType() { return TYPE; } @Override public DISCONNECT decode(MQTTFrame frame) throws ProtocolException { return (DISCONNECT) super.decode(frame); } @Override public String toString() { return "DISCONNECT"; } } MQTTFrame.java000066400000000000000000000075351231060417000340400ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.Buffer; import org.fusesource.mqtt.client.QoS; /** *

*

* * @author Hiram Chirino */ public class MQTTFrame extends MessageSupport.HeaderBase { private static final Buffer[] NO_BUFFERS = new Buffer[0]; public Buffer[] buffers = NO_BUFFERS; public MQTTFrame() { } public MQTTFrame( Buffer buffer) { this(new Buffer[]{buffer}); } public MQTTFrame( Buffer[] buffers) { this.buffers = buffers; } public Buffer[] buffers() { return buffers; } public MQTTFrame buffers(Buffer...buffers) { this.buffers = buffers; return this; } public MQTTFrame buffer(Buffer buffer) { this.buffers = new Buffer[]{buffer}; return this; } @Override public byte header() { return super.header(); } @Override public MQTTFrame header(byte header) { return (MQTTFrame)super.header(header); } @Override public byte messageType() { return super.messageType(); } @Override public MQTTFrame commandType(int type) { return (MQTTFrame)super.commandType(type); } @Override public boolean dup() { return super.dup(); } @Override public MQTTFrame dup(boolean dup) { return (MQTTFrame) super.dup(dup); } @Override public QoS qos() { return super.qos(); } @Override public MQTTFrame qos(QoS qos) { return (MQTTFrame) super.qos(qos); } @Override public boolean retain() { return super.retain(); } @Override public MQTTFrame retain(boolean retain) { return (MQTTFrame) super.retain(retain); } @Override public String toString() { String type = "unknown"; switch(messageType()) { case CONNECT.TYPE: type = "CONNECT"; break; case CONNACK.TYPE: type = "CONNACK"; break; case DISCONNECT.TYPE: type = "DISCONNECT"; break; case PINGREQ.TYPE: type = "PINGREQ"; break; case PINGRESP.TYPE: type = "PINGRESP"; break; case SUBSCRIBE.TYPE: type = "SUBSCRIBE"; break; case UNSUBSCRIBE.TYPE: type = "UNSUBSCRIBE"; break; case UNSUBACK.TYPE: type = "UNSUBACK"; break; case PUBLISH.TYPE: type = "PUBLISH"; break; case SUBACK.TYPE: type = "SUBACK"; break; case PUBACK.TYPE: type = "PUBACK"; break; case PUBREC.TYPE: type = "PUBREC"; break; case PUBREL.TYPE: type = "PUBREL"; break; case PUBCOMP.TYPE: type = "PUBCOMP"; break; default: } return "MQTTFrame { type: "+type+", qos: "+qos()+", dup:"+dup()+" }"; } } MQTTProtocolCodec.java000066400000000000000000000102051231060417000355310ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtdispatch.transport.AbstractProtocolCodec; import org.fusesource.hawtdispatch.util.BufferPools; import java.io.IOException; import java.nio.ByteBuffer; /** *

*

* * @author Hiram Chirino */ public class MQTTProtocolCodec extends AbstractProtocolCodec { private static final BufferPools BUFFER_POOLS = new BufferPools(); private int maxMessageLength = 1024*1024*100; public MQTTProtocolCodec() { this.bufferPools = BUFFER_POOLS; } public int getMaxMessageLength() { return maxMessageLength; } public void setMaxMessageLength(int maxMessageLength) { this.maxMessageLength = maxMessageLength; } @Override protected void encode(Object value) throws IOException { MQTTFrame frame = (MQTTFrame) value; nextWriteBuffer.write(frame.header()); int remaining = 0; for(Buffer buffer : frame.buffers) { remaining += buffer.length; } do { byte digit = (byte) (remaining & 0x7F); remaining >>>= 7; if (remaining > 0) { digit |= 0x80; } nextWriteBuffer.write(digit); } while (remaining > 0); for(Buffer buffer : frame.buffers) { nextWriteBuffer.write(buffer.data, buffer.offset, buffer.length); } } @Override protected Action initialDecodeAction() { return readHeader; } private final Action readHeader = new Action() { public MQTTFrame apply() throws IOException { int length = readLength(); if( length >= 0 ) { if( length > maxMessageLength) { throw new IOException("The maximum message length was exceeded"); } byte header = readBuffer.get(readStart); readStart = readEnd; if( length > 0 ) { nextDecodeAction = readBody(header, length); } else { return new MQTTFrame().header(header); } } return null; } }; private int readLength() throws IOException { readEnd = readStart+2; // Header is at least 2 bytes.. int limit = readBuffer.position(); int length = 0; int multiplier = 1; byte digit; while (readEnd-1 < limit) { // last byte is part of the encoded length.. digit = readBuffer.get(readEnd-1); length += (digit & 0x7F) * multiplier; if( (digit & 0x80) == 0 ) { return length; } // length extends out one more byte.. multiplier <<= 7; readEnd++; } return -1; } Action readBody(final byte header, final int length) { return new Action() { public MQTTFrame apply() throws IOException { int limit = readBuffer.position(); if ((limit - readStart) < length) { readEnd = limit; return null; } else { Buffer body = new Buffer(readBuffer.array(), readStart, length); readEnd = readStart = readStart + length; nextDecodeAction = readHeader; return new MQTTFrame(body).header(header); } } }; } } MessageSupport.java000066400000000000000000000122251231060417000352510ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.io.IOException; import java.net.ProtocolException; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.mqtt.client.QoS; /** *

*

* * @author Hiram Chirino */ public class MessageSupport { /** * All command objects implement this interface. */ static public interface Message { public byte messageType(); public Message decode(MQTTFrame frame) throws ProtocolException; public MQTTFrame encode(); } /** * All command objects that can get acked implement this interface. */ static public interface Acked extends Message { public boolean dup(); public Acked dup(boolean dup); public QoS qos(); public short messageId(); public Acked messageId(short messageId); } static protected UTF8Buffer readUTF(DataByteArrayInputStream is) throws ProtocolException { int size = is.readShort(); Buffer buffer = is.readBuffer(size); if (buffer == null || buffer.length != size) { throw new ProtocolException("Invalid message encoding"); } return buffer.utf8(); } static protected void writeUTF(DataByteArrayOutputStream os, Buffer buffer) throws IOException { os.writeShort(buffer.length); os.write(buffer); } static abstract public class AckBase { short messageId; abstract byte messageType(); protected AckBase decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); messageId = is.readShort(); return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(2); os.writeShort(messageId); MQTTFrame frame = new MQTTFrame(); frame.commandType(messageType()); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } public short messageId() { return messageId; } protected AckBase messageId(short messageId) { this.messageId = messageId; return this; } @Override public String toString() { return getClass().getSimpleName()+"{" + "messageId=" + messageId + '}'; } } static abstract public class EmptyBase { abstract byte messageType(); protected EmptyBase decode(MQTTFrame frame) throws ProtocolException { return this; } public MQTTFrame encode() { return new MQTTFrame().commandType(messageType()); } } /** *

*

* * @author Hiram Chirino */ static public class HeaderBase { protected byte header; protected byte header() { return header; } protected HeaderBase header(byte header) { this.header = header; return this; } protected byte messageType() { return (byte) ((header & 0xF0) >>> 4); } protected HeaderBase commandType(int type) { this.header &= 0x0F; this.header |= (type << 4) & 0xF0; return this; } protected QoS qos() { return QoS.values()[((header & 0x06) >>> 1)]; } protected HeaderBase qos(QoS qos) { this.header &= 0xF9; this.header |= (qos.ordinal() << 1) & 0x06; return this; } protected boolean dup() { return (header & 0x08) > 0; } protected HeaderBase dup(boolean dup) { if(dup) { this.header |= 0x08; } else { this.header &= 0xF7; } return this; } protected boolean retain() { return (header & 0x01) > 0; } protected HeaderBase retain(boolean retain) { if(retain) { this.header |= 0x01; } else { this.header &= 0xFE; } return this; } } } PINGREQ.java000066400000000000000000000023771231060417000334040ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PINGREQ extends MessageSupport.EmptyBase implements Message { public static final byte TYPE = 12; public byte messageType() { return TYPE; } @Override public PINGREQ decode(MQTTFrame frame) throws ProtocolException { return (PINGREQ) super.decode(frame); } @Override public String toString() { return "PINGREQ"; } } PINGRESP.java000066400000000000000000000024031231060417000335140ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PINGRESP extends MessageSupport.EmptyBase implements Message { public static final byte TYPE = 13; public byte messageType() { return TYPE; } @Override public PINGRESP decode(MQTTFrame frame) throws ProtocolException { return (PINGRESP) super.decode(frame); } @Override public String toString() { return "PINGRESP"; } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/PUBACK.java000066400000000000000000000024421231060417000333140ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PUBACK extends MessageSupport.AckBase implements Message { public static final byte TYPE = 4; public byte messageType() { return TYPE; } @Override public PUBACK decode(MQTTFrame frame) throws ProtocolException { return (PUBACK) super.decode(frame); } @Override public PUBACK messageId(short messageId) { return (PUBACK) super.messageId(messageId); } } PUBCOMP.java000066400000000000000000000024501231060417000333740ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PUBCOMP extends MessageSupport.AckBase implements Message { public static final byte TYPE = 7; public byte messageType() { return TYPE; } @Override public PUBCOMP decode(MQTTFrame frame) throws ProtocolException { return (PUBCOMP) super.decode(frame); } @Override public PUBCOMP messageId(short messageId) { return (PUBCOMP) super.messageId(messageId); } } PUBLISH.java000066400000000000000000000102531231060417000333750ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.mqtt.client.QoS; import java.io.IOException; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PUBLISH extends MessageSupport.HeaderBase implements Message, Acked { public static final byte TYPE = 3; private UTF8Buffer topicName; private short messageId; private Buffer payload; public PUBLISH() { qos(QoS.AT_LEAST_ONCE); } public byte messageType() { return TYPE; } public PUBLISH decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); header(frame.header()); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); topicName = MessageSupport.readUTF(is); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { messageId = is.readShort(); } payload = is.readBuffer(is.available()); if( payload == null ) { payload = new Buffer(0); } return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream variableHeader = new DataByteArrayOutputStream(); MessageSupport.writeUTF(variableHeader, topicName); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { variableHeader.writeShort(messageId); } MQTTFrame frame = new MQTTFrame(); frame.header(header()); frame.commandType(TYPE); if(payload==null || payload.length==0) { frame.buffer(variableHeader.toBuffer()); } else { frame.buffers(variableHeader.toBuffer(), payload); } return frame; } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } @Override public boolean dup() { return super.dup(); } @Override public PUBLISH dup(boolean dup) { return (PUBLISH) super.dup(dup); } @Override public QoS qos() { return super.qos(); } @Override public PUBLISH qos(QoS qos) { return (PUBLISH) super.qos(qos); } @Override public boolean retain() { return super.retain(); } @Override public PUBLISH retain(boolean retain) { return (PUBLISH) super.retain(retain); } public short messageId() { return messageId; } public PUBLISH messageId(short messageId) { this.messageId = messageId; return this; } public Buffer payload() { return payload; } public PUBLISH payload(Buffer payload) { this.payload = payload; return this; } public UTF8Buffer topicName() { return topicName; } public PUBLISH topicName(UTF8Buffer topicName) { this.topicName = topicName; return this; } @Override public String toString() { return "PUBLISH{" + "dup=" + dup() + ", qos=" + qos() + ", retain=" + retain() + ", messageId=" + messageId + ", topicName=" + topicName + ", payload=" + payload + '}'; } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/PUBREC.java000066400000000000000000000024431231060417000333300ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PUBREC extends MessageSupport.AckBase implements Message { public static final byte TYPE = 5; public byte messageType() { return TYPE; } @Override public PUBREC decode(MQTTFrame frame) throws ProtocolException { return (PUBREC) super.decode(frame); } @Override public PUBREC messageId(short messageId) { return (PUBREC) super.messageId(messageId); } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/PUBREL.java000066400000000000000000000052461231060417000333450ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.mqtt.client.QoS; import java.io.IOException; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class PUBREL extends MessageSupport.HeaderBase implements Message, Acked { public static final byte TYPE = 6; private short messageId; public byte messageType() { return TYPE; } public PUBREL() { qos(QoS.AT_LEAST_ONCE); } public PUBREL decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); header(frame.header()); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); messageId = is.readShort(); return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(2); os.writeShort(messageId); MQTTFrame frame = new MQTTFrame(); frame.header(header()); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } @Override public boolean dup() { return super.dup(); } @Override public PUBREL dup(boolean dup) { return (PUBREL) super.dup(dup); } @Override public QoS qos() { return super.qos(); } public short messageId() { return messageId; } public PUBREL messageId(short messageId) { this.messageId = messageId; return this; } @Override public String toString() { return "PUBREL{" + "dup=" + dup() + ", qos=" + qos() + ", messageId=" + messageId + '}'; } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/SUBACK.java000066400000000000000000000052061231060417000333200ustar00rootroot00000000000000/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import java.io.IOException; import java.net.ProtocolException; import java.util.Arrays; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class SUBACK implements Message { public static final byte[] NO_GRANTED_QOS = new byte[0]; public static final byte TYPE = 9; private short messageId; private byte grantedQos[] = NO_GRANTED_QOS; public byte messageType() { return TYPE; } public SUBACK decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); messageId = is.readShort(); grantedQos = is.readBuffer(is.available()).toByteArray(); return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(2+grantedQos.length); os.writeShort(messageId); os.write(grantedQos); MQTTFrame frame = new MQTTFrame(); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } public byte[] grantedQos() { return grantedQos; } public SUBACK grantedQos(byte[] grantedQos) { this.grantedQos = grantedQos; return this; } public short messageId() { return messageId; } public SUBACK messageId(short messageId) { this.messageId = messageId; return this; } @Override public String toString() { return "SUBACK{" + "grantedQos=" + Arrays.toString(grantedQos) + ", messageId=" +messageId + '}'; } } SUBSCRIBE.java000066400000000000000000000073151231060417000336150ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.mqtt.client.QoS; import org.fusesource.mqtt.client.Topic; import java.io.IOException; import java.net.ProtocolException; import java.util.ArrayList; import java.util.Arrays; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class SUBSCRIBE extends MessageSupport.HeaderBase implements Message, Acked { public static final byte TYPE = 8; public static final Topic[] NO_TOPICS = new Topic[0]; private short messageId; private Topic topics[] = NO_TOPICS; public SUBSCRIBE() { qos(QoS.AT_LEAST_ONCE); } public byte messageType() { return TYPE; } public SUBSCRIBE decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); header(frame.header()); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { messageId = is.readShort(); } ArrayList list = new ArrayList(); while(is.available() > 0) { Topic topic = new Topic(MessageSupport.readUTF(is), QoS.values()[is.readByte()]); list.add(topic); } topics = list.toArray(new Topic[list.size()]); return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { os.writeShort(messageId); } for(Topic topic: topics) { MessageSupport.writeUTF(os, topic.name()); os.writeByte(topic.qos().ordinal()); } MQTTFrame frame = new MQTTFrame(); frame.header(header()); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } @Override public boolean dup() { return super.dup(); } @Override public SUBSCRIBE dup(boolean dup) { return (SUBSCRIBE) super.dup(dup); } @Override public QoS qos() { return super.qos(); } public short messageId() { return messageId; } public SUBSCRIBE messageId(short messageId) { this.messageId = messageId; return this; } public Topic[] topics() { return topics; } public SUBSCRIBE topics(Topic[] topics) { this.topics = topics; return this; } @Override public String toString() { return "SUBSCRIBE{" + "dup=" + dup() + ", qos=" + qos() + ", messageId=" + messageId + ", topics=" + (topics == null ? null : Arrays.asList(topics)) + '}'; } } UNSUBACK.java000066400000000000000000000025371231060417000335100ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import java.net.ProtocolException; import static org.fusesource.mqtt.codec.MessageSupport.AckBase; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class UNSUBACK extends AckBase implements Message { public static final byte TYPE = 11; public byte messageType() { return TYPE; } @Override public UNSUBACK decode(MQTTFrame frame) throws ProtocolException { return (UNSUBACK) super.decode(frame); } @Override public UNSUBACK messageId(short messageId) { return (UNSUBACK) super.messageId(messageId); } } UNSUBSCRIBE.java000066400000000000000000000072101231060417000340520ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/main/java/org/fusesource/mqtt/codec/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.codec; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.mqtt.client.QoS; import java.io.IOException; import java.net.ProtocolException; import java.util.ArrayList; import java.util.Arrays; import static org.fusesource.mqtt.codec.MessageSupport.*; /** *

*

* * @author Hiram Chirino */ public class UNSUBSCRIBE extends MessageSupport.HeaderBase implements Message, Acked { public static final byte TYPE = 10; public static final UTF8Buffer[] NO_TOPICS = new UTF8Buffer[0]; private short messageId; private UTF8Buffer topics[] = NO_TOPICS; public UNSUBSCRIBE() { qos(QoS.AT_LEAST_ONCE); } public byte messageType() { return TYPE; } public UNSUBSCRIBE decode(MQTTFrame frame) throws ProtocolException { assert(frame.buffers.length == 1); header(frame.header()); DataByteArrayInputStream is = new DataByteArrayInputStream(frame.buffers[0]); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { messageId = is.readShort(); } ArrayList list = new ArrayList(); while(is.available() > 0) { list.add(MessageSupport.readUTF(is)); } topics = list.toArray(new UTF8Buffer[list.size()]); return this; } public MQTTFrame encode() { try { DataByteArrayOutputStream os = new DataByteArrayOutputStream(); QoS qos = qos(); if(qos != QoS.AT_MOST_ONCE) { os.writeShort(messageId); } for(UTF8Buffer topic: topics) { MessageSupport.writeUTF(os, topic); } MQTTFrame frame = new MQTTFrame(); frame.header(header()); frame.commandType(TYPE); return frame.buffer(os.toBuffer()); } catch (IOException e) { throw new RuntimeException("The impossible happened"); } } @Override public boolean dup() { return super.dup(); } @Override public UNSUBSCRIBE dup(boolean dup) { return (UNSUBSCRIBE) super.dup(dup); } @Override public QoS qos() { return super.qos(); } public short messageId() { return messageId; } public UNSUBSCRIBE messageId(short messageId) { this.messageId = messageId; return this; } public UTF8Buffer[] topics() { return topics; } public UNSUBSCRIBE topics(UTF8Buffer[] topics) { this.topics = topics; return this; } @Override public String toString() { return "UNSUBSCRIBE{" + "dup=" + dup() + ", qos=" + qos() + ", messageId=" + messageId + ", topics=" + (topics == null ? null : Arrays.asList(topics)) + '}'; } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/000077500000000000000000000000001231060417000236005ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/000077500000000000000000000000001231060417000245215ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/000077500000000000000000000000001231060417000253105ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/000077500000000000000000000000001231060417000274735ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/000077500000000000000000000000001231060417000304605ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/client/000077500000000000000000000000001231060417000317365ustar00rootroot00000000000000BlockingApiTest.java000066400000000000000000000075621231060417000355560ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import java.util.concurrent.TimeUnit; import static org.fusesource.hawtbuf.Buffer.utf8; import org.fusesource.mqtt.codec.MQTTFrame; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** *

*

* * @author Hiram Chirino */ public class BlockingApiTest extends BrokerTestSupport { private static final Logger LOG = LoggerFactory.getLogger(BlockingApiTest.class); public void testInterface() throws Exception { MQTT mqtt = new MQTT(); mqtt.setHost("localhost", port); BlockingConnection connection = mqtt.blockingConnection(); connection.connect(); Topic[] topics = {new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}; byte[] qoses = connection.subscribe(topics); connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); Message message = connection.receive(); assertEquals("Hello", new String(message.getPayload())) ; // To let the server know that it has been processed. message.ack(); connection.disconnect(); } public void testInvalidClientId() throws Exception { MQTT mqtt = new MQTT(); mqtt.setHost("localhost", port); mqtt.setVersion("3.1.1"); mqtt.setCleanSession(false); mqtt.setClientId((String) null); try { mqtt.blockingConnection(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { } catch (Throwable e) { fail("Unexpected exception: "+e); } // also test "" client id mqtt.setClientId(""); try { mqtt.blockingConnection(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { } catch (Throwable e) { fail("Unexpected exception: "+e); } } public void testReceiveTimeout() throws Exception { MQTT mqtt = new MQTT(); mqtt.setHost("localhost", port); mqtt.setTracer(new Tracer() { @Override public void onReceive(MQTTFrame frame) { LOG.info("Client Received:\n" + frame); } @Override public void onSend(MQTTFrame frame) { LOG.info("Client Sent:\n" + frame); } @Override public void debug(String message, Object... args) { LOG.info(String.format(message, args)); } }); BlockingConnection connection = mqtt.blockingConnection(); connection.connect(); Topic[] topics = {new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}; byte[] qoses = connection.subscribe(topics); // force a receive timeout Message message = connection.receive(1000, TimeUnit.MILLISECONDS); assertNull(message); connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); message = connection.receive(5000, TimeUnit.MILLISECONDS); assertNotNull(message); assertEquals("Hello", new String(message.getPayload())); // To let the server know that it has been processed. message.ack(); connection.disconnect(); } } BrokerTestSupport.java000066400000000000000000000037001231060417000362030ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import junit.framework.TestCase; import org.apache.activemq.apollo.broker.Broker; import org.apache.activemq.apollo.broker.BrokerFactory; import org.apache.activemq.apollo.util.ServiceControl; import java.io.File; import java.net.InetSocketAddress; import java.net.URL; /** *

*

* * @author Hiram Chirino */ public class BrokerTestSupport extends TestCase { public int port = 1883; public Broker broker; protected Broker createBroker() throws Exception { URL resource = getClass().getResource("apollo-mqtt.xml"); return BrokerFactory.createBroker(resource.toURI().toString()); } @Override protected void setUp() throws Exception { if (System.getProperty("basedir") == null) { File file = new File("."); System.setProperty("basedir", file.getAbsolutePath()); } broker = createBroker(); ServiceControl.start(broker, "Starting Apollo Broker"); this.port = ((InetSocketAddress)broker.get_socket_address()).getPort(); } @Override protected void tearDown() throws Exception { if(broker!=null) { ServiceControl.stop(broker, "Stopped Apollo Broker"); broker = null; } } } CallbackApiTest.java000066400000000000000000000071071231060417000355150ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import junit.framework.TestCase; import org.fusesource.hawtbuf.Buffer; import static org.fusesource.hawtbuf.Buffer.*; import org.fusesource.hawtbuf.UTF8Buffer; import org.fusesource.mqtt.codec.MQTTFrame; /** *

*

* * @author Hiram Chirino */ public class CallbackApiTest extends BrokerTestSupport { public void testInterface() throws Exception { final Promise result = new Promise(); MQTT mqtt = new MQTT(); mqtt.setHost("localhost", port); mqtt.setTracer(new Tracer(){ @Override public void onReceive(MQTTFrame frame) { System.out.println("recv: "+frame); } @Override public void onSend(MQTTFrame frame) { System.out.println("send: "+frame); } @Override public void debug(String message, Object... args) { System.out.println(String.format("debug: "+message, args)); } }); final CallbackConnection connection = mqtt.callbackConnection(); // Start add a listener to process subscription messages, and start the // resume the connection so it starts receiving messages from the socket. connection.listener(new Listener() { public void onConnected() { System.out.println("connected"); } public void onDisconnected() { System.out.println("disconnected"); } public void onPublish(UTF8Buffer topic, Buffer payload, Runnable onComplete) { result.onSuccess(payload); onComplete.run(); } public void onFailure(Throwable value) { System.out.println("failure: "+value); result.onFailure(value); connection.disconnect(null); } }); connection.connect(new Callback() { // Once we connect.. public void onSuccess(Void v) { // Subscribe to a topic foo Topic[] topics = {new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}; connection.subscribe(topics, new Callback() { public void onSuccess(byte[] value) { // Once subscribed, publish a message on the same topic. connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false, null); } public void onFailure(Throwable value) { result.onFailure(value); connection.disconnect(null); } }); } public void onFailure(Throwable value) { result.onFailure(value); } }); assertEquals("Hello", new String(result.await().toByteArray())); } } FutureApiTest.java000066400000000000000000000037051231060417000352730ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/java/org/fusesource/mqtt/client/** * Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. * * http://fusesource.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fusesource.mqtt.client; import junit.framework.TestCase; import org.fusesource.hawtbuf.Buffer; import static org.fusesource.hawtbuf.Buffer.ascii; import static org.fusesource.hawtbuf.Buffer.utf8; /** *

*

* * @author Hiram Chirino */ public class FutureApiTest extends BrokerTestSupport { public void testInterface() throws Exception { final Promise result = new Promise(); MQTT mqtt = new MQTT(); mqtt.setHost("localhost", port); FutureConnection connection = mqtt.futureConnection(); Future f1 = connection.connect(); f1.await(); Future f2 = connection.subscribe(new Topic[]{new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}); byte[] qoses = f2.await(); // We can start future receive.. Future receive = connection.receive(); // send the message.. connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); // Then the receive will get the message. Message message = receive.await(); assertEquals("Hello", new String(message.getPayload())); // To let the server know that it has been processed. message.ack(); connection.disconnect().await(); } } mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/000077500000000000000000000000001231060417000256125ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/log4j.properties000066400000000000000000000024561231060417000307560ustar00rootroot00000000000000# # Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. # # http://fusesource.com # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # The logging properties used during tests.. # log4j.rootLogger=INFO, console log4j.logger.org.apache.activemq=INFO # Console will only display warnnings log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%-5p | %t | %m%n log4j.appender.console.threshold=TRACE # File appender will contain all info messages log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n log4j.appender.file.file=target/test.log log4j.appender.file.append=true mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/org/000077500000000000000000000000001231060417000264015ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/org/fusesource/000077500000000000000000000000001231060417000305645ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/org/fusesource/mqtt/000077500000000000000000000000001231060417000315515ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/org/fusesource/mqtt/client/000077500000000000000000000000001231060417000330275ustar00rootroot00000000000000apollo-mqtt.xml000066400000000000000000000021051231060417000357410ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/mqtt-client/src/test/resources/org/fusesource/mqtt/client This broker configuration is what the unit tests in this module load up. localhost mqtt-client-mqtt-client-project-1.10/pom.xml000066400000000000000000000265251231060417000211200ustar00rootroot00000000000000 4.0.0 org.fusesource fusesource-pom 1.10 org.fusesource.mqtt-client mqtt-client-project 1.10 pom ${project.artifactId} mqtt-client provides an ASL 2.0 licensed API to MQTT. It takes care of automatically reconnecting to your MQTT server and restoring your client session if any network failures occur. Applications can use a blocking API style, a futures based API, or a callback/continuations passing API style. mqtt-client UTF-8 4.7 1.6.1 1.10 1.20 1.15 4.2.0 3.1 1.6 http://${forge-project-id}.fusesource.org/ 2010 assembla http://www.assembla.com/spaces/mqtt-client/support/tickets Discussion Group http://groups.google.com/group/mqtt-client mqtt-client@googlegroups.com mqtt-client+subscribe@googlegroups.com mqtt-client+unsubscribe@googlegroups.com Source Control and Issue Tracker Notifications http://groups.google.com/group/mqtt-client-commits mqtt-client-commits@googlegroups.com mqtt-client-commits+subscribe@googlegroups.com mqtt-client-commits+unsubscribe@googlegroups.com The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:git:git://forge.fusesource.com/${forge-project-id}.git scm:git:ssh://git@forge.fusesource.com/${forge-project-id}.git http://github.com/fusesource/mqtt-client/tree/master mqtt-client-project-1.10 website.fusesource.org website dav:http://fusesource.com/forge/dav/${forge-project-id}/maven/${project.version} chirino Hiram Chirino hiram@hiramchirino.com http://hiramchirino.com GMT-5 install org.apache.felix maven-bundle-plugin 1.0.0 true ${project.artifactId} ${project.groupId}.${project.artifactId} org.fusesource.mqtt.* ${project.name} ${project.version} org.apache.maven.plugins maven-surefire-plugin 2.5 true once false ${project.build.directory} **/*Test.java org.apache.maven.plugins maven-compiler-plugin 2.1 1.5 1.5 org.apache.maven.plugins maven-idea-plugin 2.2 true true org.apache.maven.plugins maven-eclipse-plugin 2.5.1 true true org.apache.maven.plugins maven-release-plugin 2.5 false true true false clean install deploy -Prelease download com.fusesource.m2 http://repo.fusesource.com/nexus/content/groups/public/ true false Fusesource Snapshots http://repo.fusesource.com/nexus/content/repositories/snapshots java.net.m2 http://download.java.net/maven/2 true false glassfish-repo-archive http://maven.glassfish.org/content/groups/glassfish true false license com.mycila.maven-license-plugin maven-license-plugin 1.6.0 false
src/main/resources/license-header.txt
true src/** **/pom.xml **/*.scaml **/LICENSE.txt **/LICENSE **/.svn/** **/target/** **/*.jpg **/*.png **/*.gif **/*.ico **/*.keystore false JAVADOC_STYLE DOUBLESLASH_STYLE SCRIPT_STYLE
check
lib/rt.jar ${java.home}/lib/rt.jar ${java.home}/lib/rt.jar ${java.home}/lib/jsse.jar Classes/classes.jar ${java.home}/../Classes/classes.jar ${java.home}/../Classes/classes.jar ${java.home}/../Classes/jsse.jar jre/lib/rt.jar ${java.home}/jre/lib/rt.jar ${java.home}/jre/lib/rt.jar ${java.home}/jre/lib/jsse.jar
mqtt-client mqtt-client-java1.4-uber mqtt-client-website
mqtt-client-mqtt-client-project-1.10/readme.md000077500000000000000000000300161231060417000213530ustar00rootroot00000000000000## Overview MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium. mqtt-client provides an ASL 2.0 licensed API to MQTT. It takes care of automatically reconnecting to your MQTT server and restoring your client session if any network failures occur. Applications can use a blocking API style, a futures based API, or a callback/continuations passing API style. ## Using from Maven Add the following to your maven `pom.xml` file. org.fusesource.mqtt-client mqtt-client 1.7 ## Using from any Other Build System Download the [uber jar file](https://repository.jboss.org/nexus/content/groups/fs-public/org/fusesource/mqtt-client/mqtt-client/1.7/mqtt-client-1.7-uber.jar) and add it to your build. The uber contains all the stripped down dependencies which the mqtt-client depends on from other projects. ## Using on Java 1.4 We also provide an [java 1.4 uber jar file](https://repository.jboss.org/nexus/content/groups/fs-public/org/fusesource/mqtt-client/mqtt-client-java1.4-uber/1.7/mqtt-client-java1.4-uber-1.7.jar) which is compatible with Java 1.4 JVMs. This version of the jar does not support SSL connections since the SSLEngine class used to implement SSL on NIO was not introduced until Java 1.5. ## Configuring the MQTT Connection The blocking, future, and callback APIs all share the same connection setup. You create a new instance of the `MQTT` class and configure it with connection and socket related options. At a minimum the `setHost` method be called before attempting to connect. MQTT mqtt = new MQTT(); mqtt.setHost("localhost", 1883); // or mqtt.setHost("tcp://localhost:1883"); ### Controlling MQTT Options * `setClientId` : Use to set the client Id of the session. This is what an MQTT server uses to identify a session where `setCleanSession(false);` is being used. The id must be 23 characters or less. Defaults to auto generated id (based on your socket address, port and timestamp). * `setCleanSession` : Set to false if you want the MQTT server to persist topic subscriptions and ack positions across client sessions. Defaults to true. * `setKeepAlive` : Configures the Keep Alive timer in seconds. Defines the maximum time interval between messages received from a client. It enables the server to detect that the network connection to a client has dropped, without having to wait for the long TCP/IP timeout. * `setUserName` : Sets the user name used to authenticate against the server. * `setPassword` : Sets the password used to authenticate against the server. * `setWillTopic`: If set the server will publish the client's Will message to the specified topics if the client has an unexpected disconnection. * `setWillMessage`: The Will message to send. Defaults to a zero length message. * `setWillQos` : Sets the quality of service to use for the Will message. Defaults to QoS.AT_MOST_ONCE. * `setWillRetain`: Set to true if you want the Will to be published with the retain option. * `setVersion`: Set to "3.1.1" to use MQTT version 3.1.1. Otherwise defaults to the 3.1 protocol version. ### Controlling Connection Reconnects Connection will automatically reconnect and re-establish messaging session if any network error occurs. You can control how often the reconnect is attempted and define maximum number of attempts of reconnects using the following methods: * `setConnectAttemptsMax` : The maximum number of reconnect attempts before an error is reported back to the client on the first attempt by the client to connect to a server. Set to -1 to use unlimited attempts. Defaults to -1. * `setReconnectAttemptsMax` : The maximum number of reconnect attempts before an error is reported back to the client after a server connection had previously been established. Set to -1 to use unlimited attempts. Defaults to -1. * `setReconnectDelay` : How long to wait in ms before the first reconnect attempt. Defaults to 10. * `setReconnectDelayMax` : The maximum amount of time in ms to wait between reconnect attempts. Defaults to 30,000. * `setReconnectBackOffMultiplier` : The Exponential backoff be used between reconnect attempts. Set to 1 to disable exponential backoff. Defaults to 2. ### Configuring Socket Options You can adjust some socket options by using the following methods: * `setReceiveBufferSize` : Sets the size of the internal socket receive buffer. Defaults to 65536 (64k) * `setSendBufferSize` : Sets the size of the internal socket send buffer. Defaults to 65536 (64k) * `setTrafficClass` : Sets traffic class or type-of-service octet in the IP header for packets sent from the transport. Defaults to `8` which means the traffic should be optimized for throughput. ### Throttling Connections If you want slow down the read or write rate of your connections, use the following methods: * `setMaxReadRate` : Sets the maximum bytes per second that this transport will receive data at. This setting throttles reads so that the rate is not exceeded. Defaults to 0 which disables throttling. * `setMaxWriteRate` : Sets the maximum bytes per second that this transport will send data at. This setting throttles writes so that the rate is not exceeded. Defaults to 0 which disables throttling. ### Using SSL connections If you want to connect over SSL/TLS instead of TCP, use an "ssl://" or "tls://" URI prefix instead of "tcp://" for the `host` field. For finer grained control of which algorithm is used. Supported protocol values are: * `ssl://` - Use the JVM default version of the SSL algorithm. * `sslv*://` - Use a specific SSL version where `*` is a version supported by your JVM. Example: `sslv3` * `tls://` - Use the JVM default version of the TLS algorithm. * `tlsv*://` - Use a specific TLS version where `*` is a version supported by your JVM. Example: `tlsv1.1` The client will use the default JVM `SSLContext` which is configured via JVM system properties unless you configure the MQTT instance using the `setSslContext` method. SSL connections perform blocking operations against internal thread pool unless you call the `setBlockingExecutor` method to configure that executor they will use instead. ### Selecting the Dispatch Queue A [HawtDispatch](http://hawtdispatch.fusesource.org/) dispatch queue is used to synchronize access to the connection. If an explicit queue is not configured via the `setDispatchQueue` method, then a new queue will be created for the connection. Setting an explicit queue might be handy if you want multiple connection to share the same queue for synchronization. ## Using the Blocking API The `MQTT.connectBlocking` method establishes a connection and provides you a connection with an blocking API. BlockingConnection connection = mqtt.blockingConnection(); connection.connect(); Publish messages to a topic using the `publish` method: connection.publish("foo", "Hello".toBytes(), QoS.AT_LEAST_ONCE, false); You can subscribe to multiple topics using the the `subscribe` method: Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)}; byte[] qoses = connection.subscribe(topics); Then receive and acknowledge consumption of messages using the `receive`, and `ack` methods: Message message = connection.receive(); System.out.println(message.getTopic()); byte[] payload = message.getPayload(); // process the message then: message.ack(); Finally to disconnect: connection.disconnect(); ## Using the Future based API The `MQTT.connectFuture` method establishes a connection and provides you a connection with an futures style API. All operations against the connection are non-blocking and return the result via a Future. FutureConnection connection = mqtt.futureConnection(); Future f1 = connection.connect(); f1.await(); Future f2 = connection.subscribe(new Topic[]{new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}); byte[] qoses = f2.await(); // We can start future receive.. Future receive = connection.receive(); // send the message.. Future f3 = connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); // Then the receive will get the message. Message message = receive.await(); message.ack(); Future f4 connection.disconnect(); f4.await(); ## Using the Callback/Continuation Passing based API The `MQTT.connectCallback` method establishes a connection and provides you a connection with an callback style API. This is the most complex to use API style, but can provide the best performance. The future and blocking APIs use the callback api under the covers. All operations on the connection are non-blocking and results of an operation are passed to callback interfaces you implement. Example: final CallbackConnection connection = mqtt.callbackConnection(); connection.listener(new Listener() { public void onDisconnected() { } public void onConnected() { } public void onPublish(UTF8Buffer topic, Buffer payload, Runnable ack) { // You can now process a received message from a topic. // Once process execute the ack runnable. ack.run(); } public void onFailure(Throwable value) { connection.close(null); // a connection failure occured. } }) connection.connect(new Callback() { public void onFailure(Throwable value) { result.failure(value); // If we could not connect to the server. } // Once we connect.. public void onSuccess(Void v) { // Subscribe to a topic Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)}; connection.subscribe(topics, new Callback() { public void onSuccess(byte[] qoses) { // The result of the subcribe request. } public void onFailure(Throwable value) { connection.close(null); // subscribe failed. } }); // Send a message to a topic connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false, new Callback() { public void onSuccess(Void v) { // the pubish operation completed successfully. } public void onFailure(Throwable value) { connection.close(null); // publish failed. } }); // To disconnect.. connection.disconnect(new Callback() { public void onSuccess(Void v) { // called once the connection is disconnected. } public void onFailure(Throwable value) { // Disconnects never fail. } }); } }); Every connection has a [HawtDispatch](http://hawtdispatch.fusesource.org/) dispatch queue which it uses to process IO events for the socket. The dispatch queue is an Executor that provides serial execution of IO and processing events and is used to ensure synchronized access of connection. The callbacks will be executing the dispatch queue associated with the connection so it safe to use the connection from the callback but you MUST NOT perform any blocking operations within the callback. If you need to perform some processing which MAY block, you must send it to another thread pool for processing. Furthermore, if another thread needs to interact with the connection it can only do it by using a Runnable submitted to the connection's dispatch queue. Example of executing a Runnable on the connection's dispatch queue: connection.getDispatchQueue().execute(new Runnable(){ public void run() { connection.publish( ..... ); } }); mqtt-client-mqtt-client-project-1.10/src/000077500000000000000000000000001231060417000203605ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/src/main/000077500000000000000000000000001231060417000213045ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/src/main/resources/000077500000000000000000000000001231060417000233165ustar00rootroot00000000000000mqtt-client-mqtt-client-project-1.10/src/main/resources/license-header.txt000066400000000000000000000011671231060417000267340ustar00rootroot00000000000000Copyright (C) 2010-2012, FuseSource Corp. All rights reserved. http://fusesource.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.