├── .gitignore ├── .travis.yml ├── Dockerfile ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ ├── git.eclipse.org │ └── gitroot │ │ └── paho │ │ └── org.eclipse.paho.mqtt.golang.git │ │ ├── .gitignore │ │ ├── CONTRIBUTING.md │ │ ├── DISTRIBUTION │ │ ├── LICENSE │ │ ├── README.md │ │ ├── about.html │ │ ├── client.go │ │ ├── components.go │ │ ├── edl-v10 │ │ ├── epl-v10 │ │ ├── filestore.go │ │ ├── fvt │ │ ├── README.md │ │ ├── mosquitto.cfg │ │ ├── rsmb.cfg │ │ └── setup_IMA.sh │ │ ├── memstore.go │ │ ├── message.go │ │ ├── messageids.go │ │ ├── net.go │ │ ├── notice.html │ │ ├── oops.go │ │ ├── options.go │ │ ├── packets │ │ ├── connack.go │ │ ├── connect.go │ │ ├── disconnect.go │ │ ├── packets.go │ │ ├── pingreq.go │ │ ├── pingresp.go │ │ ├── puback.go │ │ ├── pubcomp.go │ │ ├── publish.go │ │ ├── pubrec.go │ │ ├── pubrel.go │ │ ├── suback.go │ │ ├── subscribe.go │ │ ├── unsuback.go │ │ └── unsubscribe.go │ │ ├── ping.go │ │ ├── router.go │ │ ├── samples │ │ ├── build.sh │ │ ├── custom_store.go │ │ ├── routing.go │ │ ├── sample.go │ │ ├── samplecerts │ │ │ ├── CAfile.pem │ │ │ ├── README │ │ │ ├── client-crt.pem │ │ │ ├── client-key.pem │ │ │ ├── intermediateCA-crt.pem │ │ │ ├── intermediateCA-key.pem │ │ │ ├── mosquitto.org.crt │ │ │ ├── rootCA-crt.pem │ │ │ ├── rootCA-key.pem │ │ │ ├── server-crt.pem │ │ │ └── server-key.pem │ │ ├── simple.go │ │ ├── ssl.go │ │ ├── stdinpub.go │ │ └── stdoutsub.go │ │ ├── store.go │ │ ├── token.go │ │ ├── topic.go │ │ └── trace.go │ ├── github.com │ ├── Sirupsen │ │ └── logrus │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── entry.go │ │ │ ├── examples │ │ │ ├── basic │ │ │ │ └── basic.go │ │ │ └── hook │ │ │ │ └── hook.go │ │ │ ├── exported.go │ │ │ ├── formatter.go │ │ │ ├── formatters │ │ │ └── logstash │ │ │ │ └── logstash.go │ │ │ ├── hooks.go │ │ │ ├── hooks │ │ │ └── syslog │ │ │ │ ├── README.md │ │ │ │ └── syslog.go │ │ │ ├── json_formatter.go │ │ │ ├── logger.go │ │ │ ├── logrus.go │ │ │ ├── terminal_bsd.go │ │ │ ├── terminal_linux.go │ │ │ ├── terminal_notwindows.go │ │ │ ├── terminal_solaris.go │ │ │ ├── terminal_windows.go │ │ │ ├── text_formatter.go │ │ │ └── writer.go │ ├── codegangsta │ │ └── inject │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── inject.go │ │ │ ├── translations │ │ │ └── README_zh_cn.md │ │ │ └── update_readme.sh │ ├── coreos │ │ └── etcd │ │ │ ├── client │ │ │ ├── README.md │ │ │ ├── auth_role.go │ │ │ ├── auth_user.go │ │ │ ├── cancelreq.go │ │ │ ├── client.go │ │ │ ├── cluster_error.go │ │ │ ├── curl.go │ │ │ ├── discover.go │ │ │ ├── doc.go │ │ │ ├── keys.generated.go │ │ │ ├── keys.go │ │ │ ├── members.go │ │ │ ├── srv.go │ │ │ └── util.go │ │ │ └── pkg │ │ │ ├── pathutil │ │ │ └── path.go │ │ │ └── types │ │ │ ├── doc.go │ │ │ ├── id.go │ │ │ ├── set.go │ │ │ ├── slice.go │ │ │ ├── urls.go │ │ │ └── urlsmap.go │ ├── garyburd │ │ └── redigo │ │ │ ├── internal │ │ │ ├── commandinfo.go │ │ │ └── redistest │ │ │ │ └── testdb.go │ │ │ └── redis │ │ │ ├── conn.go │ │ │ ├── doc.go │ │ │ ├── log.go │ │ │ ├── pool.go │ │ │ ├── pubsub.go │ │ │ ├── redis.go │ │ │ ├── reply.go │ │ │ ├── scan.go │ │ │ └── script.go │ ├── go-martini │ │ └── martini │ │ │ ├── .gitignore │ │ │ ├── Godeps │ │ │ └── Godeps.json │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── env.go │ │ │ ├── go_version.go │ │ │ ├── logger.go │ │ │ ├── martini.go │ │ │ ├── recovery.go │ │ │ ├── response_writer.go │ │ │ ├── return_handler.go │ │ │ ├── router.go │ │ │ ├── static.go │ │ │ ├── translations │ │ │ ├── README_de_DE.md │ │ │ ├── README_es_ES.md │ │ │ ├── README_fr_FR.md │ │ │ ├── README_ja_JP.md │ │ │ ├── README_ko_kr.md │ │ │ ├── README_pl_PL.md │ │ │ ├── README_pt_br.md │ │ │ ├── README_ru_RU.md │ │ │ ├── README_tr_TR.md │ │ │ ├── README_zh_cn.md │ │ │ └── README_zh_tw.md │ │ │ └── wercker.yml │ ├── go-sql-driver │ │ └── mysql │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── CHANGELOG.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── appengine.go │ │ │ ├── buffer.go │ │ │ ├── collations.go │ │ │ ├── connection.go │ │ │ ├── const.go │ │ │ ├── driver.go │ │ │ ├── errors.go │ │ │ ├── infile.go │ │ │ ├── packets.go │ │ │ ├── result.go │ │ │ ├── rows.go │ │ │ ├── statement.go │ │ │ ├── transaction.go │ │ │ └── utils.go │ ├── jinzhu │ │ ├── gorm │ │ │ ├── .codeclimate.yml │ │ │ ├── .gitignore │ │ │ ├── CONTRIBUTING.md │ │ │ ├── License │ │ │ ├── README.md │ │ │ ├── association.go │ │ │ ├── callback.go │ │ │ ├── callback_create.go │ │ │ ├── callback_delete.go │ │ │ ├── callback_query.go │ │ │ ├── callback_query_preload.go │ │ │ ├── callback_save.go │ │ │ ├── callback_update.go │ │ │ ├── dialect.go │ │ │ ├── dialect_common.go │ │ │ ├── dialect_mysql.go │ │ │ ├── dialect_postgres.go │ │ │ ├── dialect_sqlite3.go │ │ │ ├── dialects │ │ │ │ ├── mssql │ │ │ │ │ └── mssql.go │ │ │ │ ├── mysql │ │ │ │ │ └── mysql.go │ │ │ │ ├── postgres │ │ │ │ │ └── postgres.go │ │ │ │ └── sqlite │ │ │ │ │ └── sqlite.go │ │ │ ├── errors.go │ │ │ ├── field.go │ │ │ ├── interface.go │ │ │ ├── join_table_handler.go │ │ │ ├── logger.go │ │ │ ├── main.go │ │ │ ├── model.go │ │ │ ├── model_struct.go │ │ │ ├── scope.go │ │ │ ├── search.go │ │ │ ├── test_all.sh │ │ │ └── utils.go │ │ └── inflection │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── inflections.go │ ├── martini-contrib │ │ ├── binding │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── binding.go │ │ │ ├── errors.go │ │ │ └── wercker.yml │ │ └── render │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── fixtures │ │ │ ├── basic │ │ │ │ ├── admin │ │ │ │ │ └── index.tmpl │ │ │ │ ├── another_layout.tmpl │ │ │ │ ├── content.tmpl │ │ │ │ ├── current_layout.tmpl │ │ │ │ ├── delims.tmpl │ │ │ │ ├── hello.tmpl │ │ │ │ ├── hypertext.html │ │ │ │ └── layout.tmpl │ │ │ └── custom_funcs │ │ │ │ └── index.tmpl │ │ │ ├── render.go │ │ │ └── wercker.yml │ ├── oxtoacart │ │ └── bpool │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bpool.go │ │ │ ├── bufferpool.go │ │ │ ├── bytepool.go │ │ │ └── sizedbufferpool.go │ ├── pborman │ │ └── uuid │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ ├── dce.go │ │ │ ├── doc.go │ │ │ ├── hash.go │ │ │ ├── json.go │ │ │ ├── node.go │ │ │ ├── sql.go │ │ │ ├── time.go │ │ │ ├── util.go │ │ │ ├── uuid.go │ │ │ ├── version1.go │ │ │ └── version4.go │ ├── robfig │ │ └── cron │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── constantdelay.go │ │ │ ├── cron.go │ │ │ ├── doc.go │ │ │ ├── parser.go │ │ │ └── spec.go │ ├── streadway │ │ └── amqp │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── allocator.go │ │ │ ├── auth.go │ │ │ ├── certs.sh │ │ │ ├── channel.go │ │ │ ├── confirms.go │ │ │ ├── connection.go │ │ │ ├── consumers.go │ │ │ ├── delivery.go │ │ │ ├── doc.go │ │ │ ├── fuzz.go │ │ │ ├── gen.sh │ │ │ ├── read.go │ │ │ ├── return.go │ │ │ ├── spec │ │ │ ├── amqp0-9-1.stripped.extended.xml │ │ │ └── gen.go │ │ │ ├── spec091.go │ │ │ ├── types.go │ │ │ ├── uri.go │ │ │ └── write.go │ └── ugorji │ │ └── go │ │ └── codec │ │ ├── 0doc.go │ │ ├── README.md │ │ ├── binc.go │ │ ├── cbor.go │ │ ├── codecgen │ │ ├── README.md │ │ ├── gen.go │ │ └── z.go │ │ ├── decode.go │ │ ├── encode.go │ │ ├── fast-path.generated.go │ │ ├── fast-path.go.tmpl │ │ ├── fast-path.not.go │ │ ├── gen-dec-array.go.tmpl │ │ ├── gen-dec-map.go.tmpl │ │ ├── gen-helper.generated.go │ │ ├── gen-helper.go.tmpl │ │ ├── gen.generated.go │ │ ├── gen.go │ │ ├── helper.go │ │ ├── helper_internal.go │ │ ├── helper_not_unsafe.go │ │ ├── helper_unsafe.go │ │ ├── json.go │ │ ├── msgpack.go │ │ ├── noop.go │ │ ├── prebuild.go │ │ ├── prebuild.sh │ │ ├── rpc.go │ │ ├── simple.go │ │ ├── test-cbor-goldens.json │ │ ├── test.py │ │ ├── tests.sh │ │ └── time.go │ ├── golang.org │ └── x │ │ └── net │ │ ├── context │ │ ├── context.go │ │ └── ctxhttp │ │ │ ├── cancelreq.go │ │ │ ├── cancelreq_go14.go │ │ │ └── ctxhttp.go │ │ └── websocket │ │ ├── client.go │ │ ├── hybi.go │ │ ├── server.go │ │ └── websocket.go │ └── labix.org │ └── v2 │ └── mgo │ ├── .bzrignore │ ├── LICENSE │ ├── Makefile │ ├── auth.go │ ├── bson │ ├── LICENSE │ ├── bson.go │ ├── decode.go │ └── encode.go │ ├── cluster.go │ ├── doc.go │ ├── gridfs.go │ ├── log.go │ ├── queue.go │ ├── sasl │ ├── sasl.c │ └── sasl.go │ ├── saslimpl.go │ ├── saslstub.go │ ├── server.go │ ├── session.go │ ├── socket.go │ ├── stats.go │ ├── testdb │ ├── dropall.js │ ├── init.js │ ├── setup.sh │ ├── supervisord.conf │ └── wait.js │ └── txn │ ├── chaos.go │ ├── debug.go │ ├── flusher.go │ ├── tarjan.go │ └── txn.go ├── LICENSE ├── README.md ├── build └── local │ ├── docker │ ├── base.sh │ └── run.sh │ └── linux │ ├── install.sh │ └── run.sh ├── docs ├── en │ └── README.md ├── img │ └── architecture.jpeg └── zh-cn │ ├── api-doc │ ├── application.md │ └── device.md │ ├── config │ └── product-json-config.md │ ├── contribution │ ├── coding-standard.md │ └── work-flow.md │ ├── environment │ └── golang.md │ ├── quick-start │ ├── README.md │ ├── docker.md │ └── ubuntu.md │ ├── services │ ├── README.md │ ├── apiprovider.md │ ├── controller.md │ ├── devicemanager.md │ ├── httpaccess.md │ ├── mqttaccess.md │ └── registry.md │ └── tools │ └── pdcfg.md ├── make_deps.sh ├── pkg ├── README.md ├── cache │ ├── cache.go │ ├── memcache.go │ └── memcache_test.go ├── generator │ ├── key_gen.go │ ├── key_gen_test.go │ ├── password_gen.go │ ├── password_gen_test.go │ ├── token_gen.go │ └── token_gen_test.go ├── models │ ├── application.go │ ├── device.go │ ├── product.go │ ├── rule.go │ └── vendor.go ├── mongo │ ├── recorder.go │ └── recorder_test.go ├── mqtt │ ├── broker.go │ ├── connection.go │ ├── manager.go │ ├── message.go │ ├── payload.go │ ├── provider.go │ └── utils.go ├── mysql │ ├── client.go │ ├── migrate.go │ └── migrate_test.go ├── online │ ├── online.go │ └── online_test.go ├── productconfig │ ├── productconfig.go │ └── productconfig_test.go ├── protocol │ ├── protocol.go │ ├── protocol_test.go │ └── structure.go ├── queue │ ├── queque_test.go │ └── queue.go ├── redispool │ ├── redispool.go │ └── redispool_test.go ├── rpcs │ ├── access.go │ ├── common.go │ ├── controller.go │ ├── devicemanager.go │ └── registry.go ├── rule │ ├── ifttt.go │ ├── rule_action.go │ └── timer.go ├── serializer │ ├── serializer.go │ └── serializer_test.go ├── server │ ├── README.md │ ├── config.go │ ├── errors.go │ ├── http_server.go │ ├── http_server_test.go │ ├── log.go │ ├── log_test.go │ ├── netif.go │ ├── netif_test.go │ ├── rpc_client.go │ ├── rpc_client_test.go │ ├── rpc_server.go │ ├── rpc_server_test.go │ ├── server.go │ ├── server_manager.go │ ├── server_test.go │ ├── tcp_server.go │ ├── tcp_server_test.go │ ├── testdata │ │ ├── cert.pem │ │ └── key.pem │ ├── timer_task.go │ ├── utils.go │ └── utils_test.go ├── tlv │ ├── tlv.go │ └── tlv_test.go ├── token │ ├── token.go │ └── token_test.go └── utils │ ├── http.go │ └── http_test.go ├── services ├── README.md ├── apiprovider │ ├── actions.go │ ├── flags.go │ ├── main.go │ ├── middleware.go │ ├── middleware_test.go │ ├── notifier.go │ ├── request.go │ ├── response.go │ └── router.go ├── controller │ ├── controller.go │ ├── flags.go │ └── main.go ├── devicemanager │ ├── flags.go │ ├── main.go │ ├── manager.go │ └── manager_test.go ├── httpaccess │ ├── actions.go │ ├── flags.go │ ├── main.go │ ├── response.go │ └── router.go ├── mqttaccess │ ├── access.go │ ├── main.go │ ├── mqtt_provider.go │ └── status.go └── registry │ ├── cache.go │ ├── db.go │ ├── db_test.go │ ├── main.go │ ├── registry.go │ ├── registry_test.go │ ├── utils.go │ └── utils_test.go ├── tests └── device │ ├── device.go │ ├── main.go │ └── utils.go ├── tools └── pdcfg │ ├── README.md │ ├── application.go │ ├── command_handlers.go │ ├── main.go │ ├── product.go │ ├── utils.go │ ├── utils_test.go │ └── vendor.go └── unit_test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | *.project 6 | 7 | # Folders 8 | _obj 9 | _test 10 | 11 | # Architecture specific extensions/prefixes 12 | *.[568vq] 13 | [568vq].out 14 | 15 | *.cgo1.go 16 | *.cgo2.c 17 | _cgo_defun.c 18 | _cgo_gotypes.go 19 | _cgo_export.* 20 | 21 | _testmain.go 22 | 23 | *.exe 24 | *.test 25 | *.prof 26 | *.out 27 | 28 | # ctag files 29 | .tags* 30 | 31 | # Test data output folder 32 | testoutput 33 | 34 | # coverage 35 | *.coverprofile 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.5 4 | services: 5 | - redis-server 6 | - mongodb 7 | - rabbitmq 8 | before_install: 9 | - go get github.com/modocache/gover 10 | - go get github.com/mattn/goveralls 11 | - curl -L https://github.com/coreos/etcd/releases/download/v2.3.1/etcd-v2.3.1-linux-amd64.tar.gz -o etcd-v2.3.1-linux-amd64.tar.gz 12 | - tar xzvf etcd-v2.3.1-linux-amd64.tar.gz 13 | - cp etcd-v2.3.1-linux-amd64/etcd $HOME/gopath/bin 14 | install: 15 | - go get ./... 16 | before_script: 17 | - $HOME/gopath/bin/etcd & 18 | - echo 'CREATE DATABASE PandoCloud' | mysql -uroot 19 | script: 20 | - cd $HOME/gopath/src/github.com/PandoCloud/pando-cloud/ 21 | - ./unit_test.sh 22 | - $HOME/gopath/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.5.2 2 | 3 | MAINTAINER razr razr.china@gmail.com 4 | 5 | ADD . /go/src/github.com/PandoCloud/pando-cloud 6 | 7 | RUN go get github.com/PandoCloud/pando-cloud/... -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | *.msg 25 | *.lok 26 | 27 | samples/trivial 28 | samples/trivial2 29 | samples/sample 30 | samples/reconnect 31 | samples/ssl 32 | samples/custom_store 33 | samples/simple 34 | samples/stdinpub 35 | samples/stdoutsub 36 | samples/routing -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/DISTRIBUTION: -------------------------------------------------------------------------------- 1 | 2 | 3 | Eclipse Distribution License - v 1.0 4 | 5 | Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. 6 | 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 10 | 11 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/components.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * 9 | * Contributors: 10 | * Seth Hoenig 11 | * Allan Stockdill-Mander 12 | * Mike Robertson 13 | */ 14 | 15 | package mqtt 16 | 17 | type component string 18 | 19 | // Component names for debug output 20 | const ( 21 | NET component = "[net] " 22 | PNG component = "[pinger] " 23 | CLI component = "[client] " 24 | DEC component = "[decode] " 25 | MES component = "[message] " 26 | STR component = "[store] " 27 | MID component = "[msgids] " 28 | TST component = "[test] " 29 | STA component = "[state] " 30 | ERR component = "[error] " 31 | ) 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/edl-v10: -------------------------------------------------------------------------------- 1 | 2 | Eclipse Distribution License - v 1.0 3 | 4 | Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 | 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/fvt/mosquitto.cfg: -------------------------------------------------------------------------------- 1 | allow_anonymous true 2 | allow_duplicate_messages false 3 | connection_messages true 4 | log_dest stdout 5 | log_timestamp true 6 | log_type all 7 | persistence false 8 | bind_address 127.0.0.1 9 | 10 | listener 17001 11 | listener 17002 12 | listener 17003 13 | listener 17004 14 | 15 | #capath ../samples/samplecerts 16 | #certfile ../samples/samplecerts/server-crt.pem 17 | #keyfile ../samples/samplecerts/server-key.pem 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/fvt/rsmb.cfg: -------------------------------------------------------------------------------- 1 | allow_anonymous false 2 | bind_address 127.0.0.1 3 | connection_messages true 4 | log_level detail 5 | 6 | listener 17001 7 | #listener 17003 8 | #listener 17004 -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/messageids.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * 9 | * Contributors: 10 | * Seth Hoenig 11 | * Allan Stockdill-Mander 12 | * Mike Robertson 13 | */ 14 | 15 | package mqtt 16 | 17 | import ( 18 | "sync" 19 | ) 20 | 21 | // MId is 16 bit message id as specified by the MQTT spec. 22 | // In general, these values should not be depended upon by 23 | // the client application. 24 | type MId uint16 25 | 26 | type messageIds struct { 27 | sync.RWMutex 28 | index map[uint16]Token 29 | } 30 | 31 | const ( 32 | midMin uint16 = 1 33 | midMax uint16 = 65535 34 | ) 35 | 36 | func (mids *messageIds) freeID(id uint16) { 37 | mids.Lock() 38 | defer mids.Unlock() 39 | delete(mids.index, id) 40 | } 41 | 42 | func (mids *messageIds) getID(t Token) uint16 { 43 | mids.Lock() 44 | defer mids.Unlock() 45 | for i := midMin; i < midMax; i++ { 46 | if _, ok := mids.index[i]; !ok { 47 | mids.index[i] = t 48 | return i 49 | } 50 | } 51 | return 0 52 | } 53 | 54 | func (mids *messageIds) getToken(id uint16) Token { 55 | mids.RLock() 56 | defer mids.RUnlock() 57 | if token, ok := mids.index[id]; ok { 58 | return token 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/oops.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * 9 | * Contributors: 10 | * Seth Hoenig 11 | * Allan Stockdill-Mander 12 | * Mike Robertson 13 | */ 14 | 15 | package mqtt 16 | 17 | func chkerr(e error) { 18 | if e != nil { 19 | panic(e) 20 | } 21 | } 22 | 23 | func chkcond(b bool) { 24 | if !b { 25 | panic("oops") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/connack.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "github.com/pborman/uuid" 7 | "io" 8 | ) 9 | 10 | //ConnackPacket is an internal representation of the fields of the 11 | //Connack MQTT packet 12 | type ConnackPacket struct { 13 | FixedHeader 14 | TopicNameCompression byte 15 | ReturnCode byte 16 | uuid uuid.UUID 17 | } 18 | 19 | func (ca *ConnackPacket) String() string { 20 | str := fmt.Sprintf("%s\n", ca.FixedHeader) 21 | str += fmt.Sprintf("returncode: %d", ca.ReturnCode) 22 | return str 23 | } 24 | 25 | func (ca *ConnackPacket) Write(w io.Writer) error { 26 | var body bytes.Buffer 27 | var err error 28 | 29 | body.WriteByte(ca.TopicNameCompression) 30 | body.WriteByte(ca.ReturnCode) 31 | ca.FixedHeader.RemainingLength = 2 32 | packet := ca.FixedHeader.pack() 33 | packet.Write(body.Bytes()) 34 | _, err = packet.WriteTo(w) 35 | 36 | return err 37 | } 38 | 39 | //Unpack decodes the details of a ControlPacket after the fixed 40 | //header has been read 41 | func (ca *ConnackPacket) Unpack(b io.Reader) { 42 | ca.TopicNameCompression = decodeByte(b) 43 | ca.ReturnCode = decodeByte(b) 44 | } 45 | 46 | //Details returns a Details struct containing the Qos and 47 | //MessageID of this ControlPacket 48 | func (ca *ConnackPacket) Details() Details { 49 | return Details{Qos: 0, MessageID: 0} 50 | } 51 | 52 | //UUID returns the unique ID assigned to the ControlPacket when 53 | //it was originally received. Note: this is not related to the 54 | //MessageID field for MQTT packets 55 | func (ca *ConnackPacket) UUID() uuid.UUID { 56 | return ca.uuid 57 | } 58 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/disconnect.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //DisconnectPacket is an internal representation of the fields of the 10 | //Disconnect MQTT packet 11 | type DisconnectPacket struct { 12 | FixedHeader 13 | uuid uuid.UUID 14 | } 15 | 16 | func (d *DisconnectPacket) String() string { 17 | str := fmt.Sprintf("%s\n", d.FixedHeader) 18 | return str 19 | } 20 | 21 | func (d *DisconnectPacket) Write(w io.Writer) error { 22 | packet := d.FixedHeader.pack() 23 | _, err := packet.WriteTo(w) 24 | 25 | return err 26 | } 27 | 28 | //Unpack decodes the details of a ControlPacket after the fixed 29 | //header has been read 30 | func (d *DisconnectPacket) Unpack(b io.Reader) { 31 | } 32 | 33 | //Details returns a Details struct containing the Qos and 34 | //MessageID of this ControlPacket 35 | func (d *DisconnectPacket) Details() Details { 36 | return Details{Qos: 0, MessageID: 0} 37 | } 38 | 39 | //UUID returns the unique ID assigned to the ControlPacket when 40 | //it was originally received. Note: this is not related to the 41 | //MessageID field for MQTT packets 42 | func (d *DisconnectPacket) UUID() uuid.UUID { 43 | return d.uuid 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingreq.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PingreqPacket is an internal representation of the fields of the 10 | //Pingreq MQTT packet 11 | type PingreqPacket struct { 12 | FixedHeader 13 | uuid uuid.UUID 14 | } 15 | 16 | func (pr *PingreqPacket) String() string { 17 | str := fmt.Sprintf("%s", pr.FixedHeader) 18 | return str 19 | } 20 | 21 | func (pr *PingreqPacket) Write(w io.Writer) error { 22 | packet := pr.FixedHeader.pack() 23 | _, err := packet.WriteTo(w) 24 | 25 | return err 26 | } 27 | 28 | //Unpack decodes the details of a ControlPacket after the fixed 29 | //header has been read 30 | func (pr *PingreqPacket) Unpack(b io.Reader) { 31 | } 32 | 33 | //Details returns a Details struct containing the Qos and 34 | //MessageID of this ControlPacket 35 | func (pr *PingreqPacket) Details() Details { 36 | return Details{Qos: 0, MessageID: 0} 37 | } 38 | 39 | //UUID returns the unique ID assigned to the ControlPacket when 40 | //it was originally received. Note: this is not related to the 41 | //MessageID field for MQTT packets 42 | func (pr *PingreqPacket) UUID() uuid.UUID { 43 | return pr.uuid 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingresp.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PingrespPacket is an internal representation of the fields of the 10 | //Pingresp MQTT packet 11 | type PingrespPacket struct { 12 | FixedHeader 13 | uuid uuid.UUID 14 | } 15 | 16 | func (pr *PingrespPacket) String() string { 17 | str := fmt.Sprintf("%s", pr.FixedHeader) 18 | return str 19 | } 20 | 21 | func (pr *PingrespPacket) Write(w io.Writer) error { 22 | packet := pr.FixedHeader.pack() 23 | _, err := packet.WriteTo(w) 24 | 25 | return err 26 | } 27 | 28 | //Unpack decodes the details of a ControlPacket after the fixed 29 | //header has been read 30 | func (pr *PingrespPacket) Unpack(b io.Reader) { 31 | } 32 | 33 | //Details returns a Details struct containing the Qos and 34 | //MessageID of this ControlPacket 35 | func (pr *PingrespPacket) Details() Details { 36 | return Details{Qos: 0, MessageID: 0} 37 | } 38 | 39 | //UUID returns the unique ID assigned to the ControlPacket when 40 | //it was originally received. Note: this is not related to the 41 | //MessageID field for MQTT packets 42 | func (pr *PingrespPacket) UUID() uuid.UUID { 43 | return pr.uuid 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/puback.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PubackPacket is an internal representation of the fields of the 10 | //Puback MQTT packet 11 | type PubackPacket struct { 12 | FixedHeader 13 | MessageID uint16 14 | uuid uuid.UUID 15 | } 16 | 17 | func (pa *PubackPacket) String() string { 18 | str := fmt.Sprintf("%s\n", pa.FixedHeader) 19 | str += fmt.Sprintf("messageID: %d", pa.MessageID) 20 | return str 21 | } 22 | 23 | func (pa *PubackPacket) Write(w io.Writer) error { 24 | var err error 25 | pa.FixedHeader.RemainingLength = 2 26 | packet := pa.FixedHeader.pack() 27 | packet.Write(encodeUint16(pa.MessageID)) 28 | _, err = packet.WriteTo(w) 29 | 30 | return err 31 | } 32 | 33 | //Unpack decodes the details of a ControlPacket after the fixed 34 | //header has been read 35 | func (pa *PubackPacket) Unpack(b io.Reader) { 36 | pa.MessageID = decodeUint16(b) 37 | } 38 | 39 | //Details returns a Details struct containing the Qos and 40 | //MessageID of this ControlPacket 41 | func (pa *PubackPacket) Details() Details { 42 | return Details{Qos: pa.Qos, MessageID: pa.MessageID} 43 | } 44 | 45 | //UUID returns the unique ID assigned to the ControlPacket when 46 | //it was originally received. Note: this is not related to the 47 | //MessageID field for MQTT packets 48 | func (pa *PubackPacket) UUID() uuid.UUID { 49 | return pa.uuid 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubcomp.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PubcompPacket is an internal representation of the fields of the 10 | //Pubcomp MQTT packet 11 | type PubcompPacket struct { 12 | FixedHeader 13 | MessageID uint16 14 | uuid uuid.UUID 15 | } 16 | 17 | func (pc *PubcompPacket) String() string { 18 | str := fmt.Sprintf("%s\n", pc.FixedHeader) 19 | str += fmt.Sprintf("MessageID: %d", pc.MessageID) 20 | return str 21 | } 22 | 23 | func (pc *PubcompPacket) Write(w io.Writer) error { 24 | var err error 25 | pc.FixedHeader.RemainingLength = 2 26 | packet := pc.FixedHeader.pack() 27 | packet.Write(encodeUint16(pc.MessageID)) 28 | _, err = packet.WriteTo(w) 29 | 30 | return err 31 | } 32 | 33 | //Unpack decodes the details of a ControlPacket after the fixed 34 | //header has been read 35 | func (pc *PubcompPacket) Unpack(b io.Reader) { 36 | pc.MessageID = decodeUint16(b) 37 | } 38 | 39 | //Details returns a Details struct containing the Qos and 40 | //MessageID of this ControlPacket 41 | func (pc *PubcompPacket) Details() Details { 42 | return Details{Qos: pc.Qos, MessageID: pc.MessageID} 43 | } 44 | 45 | //UUID returns the unique ID assigned to the ControlPacket when 46 | //it was originally received. Note: this is not related to the 47 | //MessageID field for MQTT packets 48 | func (pc *PubcompPacket) UUID() uuid.UUID { 49 | return pc.uuid 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrec.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PubrecPacket is an internal representation of the fields of the 10 | //Pubrec MQTT packet 11 | type PubrecPacket struct { 12 | FixedHeader 13 | MessageID uint16 14 | uuid uuid.UUID 15 | } 16 | 17 | func (pr *PubrecPacket) String() string { 18 | str := fmt.Sprintf("%s\n", pr.FixedHeader) 19 | str += fmt.Sprintf("MessageID: %d", pr.MessageID) 20 | return str 21 | } 22 | 23 | func (pr *PubrecPacket) Write(w io.Writer) error { 24 | var err error 25 | pr.FixedHeader.RemainingLength = 2 26 | packet := pr.FixedHeader.pack() 27 | packet.Write(encodeUint16(pr.MessageID)) 28 | _, err = packet.WriteTo(w) 29 | 30 | return err 31 | } 32 | 33 | //Unpack decodes the details of a ControlPacket after the fixed 34 | //header has been read 35 | func (pr *PubrecPacket) Unpack(b io.Reader) { 36 | pr.MessageID = decodeUint16(b) 37 | } 38 | 39 | //Details returns a Details struct containing the Qos and 40 | //MessageID of this ControlPacket 41 | func (pr *PubrecPacket) Details() Details { 42 | return Details{Qos: pr.Qos, MessageID: pr.MessageID} 43 | } 44 | 45 | //UUID returns the unique ID assigned to the ControlPacket when 46 | //it was originally received. Note: this is not related to the 47 | //MessageID field for MQTT packets 48 | func (pr *PubrecPacket) UUID() uuid.UUID { 49 | return pr.uuid 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrel.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //PubrelPacket is an internal representation of the fields of the 10 | //Pubrel MQTT packet 11 | type PubrelPacket struct { 12 | FixedHeader 13 | MessageID uint16 14 | uuid uuid.UUID 15 | } 16 | 17 | func (pr *PubrelPacket) String() string { 18 | str := fmt.Sprintf("%s\n", pr.FixedHeader) 19 | str += fmt.Sprintf("MessageID: %d", pr.MessageID) 20 | return str 21 | } 22 | 23 | func (pr *PubrelPacket) Write(w io.Writer) error { 24 | var err error 25 | pr.FixedHeader.RemainingLength = 2 26 | packet := pr.FixedHeader.pack() 27 | packet.Write(encodeUint16(pr.MessageID)) 28 | _, err = packet.WriteTo(w) 29 | 30 | return err 31 | } 32 | 33 | //Unpack decodes the details of a ControlPacket after the fixed 34 | //header has been read 35 | func (pr *PubrelPacket) Unpack(b io.Reader) { 36 | pr.MessageID = decodeUint16(b) 37 | } 38 | 39 | //Details returns a Details struct containing the Qos and 40 | //MessageID of this ControlPacket 41 | func (pr *PubrelPacket) Details() Details { 42 | return Details{Qos: pr.Qos, MessageID: pr.MessageID} 43 | } 44 | 45 | //UUID returns the unique ID assigned to the ControlPacket when 46 | //it was originally received. Note: this is not related to the 47 | //MessageID field for MQTT packets 48 | func (pr *PubrelPacket) UUID() uuid.UUID { 49 | return pr.uuid 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/suback.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "github.com/pborman/uuid" 7 | "io" 8 | ) 9 | 10 | //SubackPacket is an internal representation of the fields of the 11 | //Suback MQTT packet 12 | type SubackPacket struct { 13 | FixedHeader 14 | MessageID uint16 15 | GrantedQoss []byte 16 | uuid uuid.UUID 17 | } 18 | 19 | func (sa *SubackPacket) String() string { 20 | str := fmt.Sprintf("%s\n", sa.FixedHeader) 21 | str += fmt.Sprintf("MessageID: %d", sa.MessageID) 22 | return str 23 | } 24 | 25 | func (sa *SubackPacket) Write(w io.Writer) error { 26 | var body bytes.Buffer 27 | var err error 28 | body.Write(encodeUint16(sa.MessageID)) 29 | body.Write(sa.GrantedQoss) 30 | sa.FixedHeader.RemainingLength = body.Len() 31 | packet := sa.FixedHeader.pack() 32 | packet.Write(body.Bytes()) 33 | _, err = packet.WriteTo(w) 34 | 35 | return err 36 | } 37 | 38 | //Unpack decodes the details of a ControlPacket after the fixed 39 | //header has been read 40 | func (sa *SubackPacket) Unpack(b io.Reader) { 41 | var qosBuffer bytes.Buffer 42 | sa.MessageID = decodeUint16(b) 43 | qosBuffer.ReadFrom(b) 44 | sa.GrantedQoss = qosBuffer.Bytes() 45 | } 46 | 47 | //Details returns a Details struct containing the Qos and 48 | //MessageID of this ControlPacket 49 | func (sa *SubackPacket) Details() Details { 50 | return Details{Qos: 0, MessageID: sa.MessageID} 51 | } 52 | 53 | //UUID returns the unique ID assigned to the ControlPacket when 54 | //it was originally received. Note: this is not related to the 55 | //MessageID field for MQTT packets 56 | func (sa *SubackPacket) UUID() uuid.UUID { 57 | return sa.uuid 58 | } 59 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/unsuback.go: -------------------------------------------------------------------------------- 1 | package packets 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pborman/uuid" 6 | "io" 7 | ) 8 | 9 | //UnsubackPacket is an internal representation of the fields of the 10 | //Unsuback MQTT packet 11 | type UnsubackPacket struct { 12 | FixedHeader 13 | MessageID uint16 14 | uuid uuid.UUID 15 | } 16 | 17 | func (ua *UnsubackPacket) String() string { 18 | str := fmt.Sprintf("%s\n", ua.FixedHeader) 19 | str += fmt.Sprintf("MessageID: %d", ua.MessageID) 20 | return str 21 | } 22 | 23 | func (ua *UnsubackPacket) Write(w io.Writer) error { 24 | var err error 25 | ua.FixedHeader.RemainingLength = 2 26 | packet := ua.FixedHeader.pack() 27 | packet.Write(encodeUint16(ua.MessageID)) 28 | _, err = packet.WriteTo(w) 29 | 30 | return err 31 | } 32 | 33 | //Unpack decodes the details of a ControlPacket after the fixed 34 | //header has been read 35 | func (ua *UnsubackPacket) Unpack(b io.Reader) { 36 | ua.MessageID = decodeUint16(b) 37 | } 38 | 39 | //Details returns a Details struct containing the Qos and 40 | //MessageID of this ControlPacket 41 | func (ua *UnsubackPacket) Details() Details { 42 | return Details{Qos: 0, MessageID: ua.MessageID} 43 | } 44 | 45 | //UUID returns the unique ID assigned to the ControlPacket when 46 | //it was originally received. Note: this is not related to the 47 | //MessageID field for MQTT packets 48 | func (ua *UnsubackPacket) UUID() uuid.UUID { 49 | return ua.uuid 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | go clean 4 | 5 | for file in *.go 6 | do 7 | echo -n "Compiling $file ..." 8 | go build "$file" 9 | echo " done." 10 | done 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/README: -------------------------------------------------------------------------------- 1 | Certificate structure: 2 | 3 | Root CA 4 | | 5 | |-> Intermediate CA 6 | | 7 | |-> Server 8 | | 9 | |-> Client 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/client-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDRzCCAi8CAQIwDQYJKoZIhvcNAQEFBQAwbTELMAkGA1UEBhMCVVMxDjAMBgNV 3 | BAgMBUR1bW15MQ4wDAYDVQQHDAVEdW1teTEOMAwGA1UECgwFRHVtbXkxDjAMBgNV 4 | BAsMBUR1bW15MR4wHAYDVQQDDBVEdW1teSBJbnRlcm1lZGlhdGUgQ0EwHhcNMTMx 5 | MDIxMTkyNDIzWhcNMTgwOTI1MTkyNDIzWjBmMQswCQYDVQQGEwJVUzEOMAwGA1UE 6 | CAwFRHVtbXkxDjAMBgNVBAcMBUR1bW15MQ4wDAYDVQQKDAVEdW1teTEOMAwGA1UE 7 | CwwFRHVtbXkxFzAVBgNVBAMMDkR1bW15IChjbGllbnQpMIIBIjANBgkqhkiG9w0B 8 | AQEFAAOCAQ8AMIIBCgKCAQEA4J/+eKqsjK0QS+cSDa5Fh4XM4THy812JkWMySA5r 9 | bFxHZ5ye36/IuwyRQ0Yn2DvhhsDR5K7yz8K+Yfp9A6WRBkyHK/sy/8vurQHeDH3y 10 | lLtHCLi5nfyt2fDxWOYwFrS1giGn2IxJIHBAWu4cBODCkqwqAp92+Lqp3Sn+D+Fb 11 | maHEU3LHua8OIJiSeAIHo/jPqfHFqZxK1bXhGCSQKvUZCaTftsqDtn+LZSElqj1y 12 | 5/cnc7XGsTf8ml/+FDMX1aSAHf+pu+UAp9JqOXOM60A5JIpYu3Lsejp1RppyPJYP 13 | zC4nSN8R2LOdDChP2MB7f1/sXRGlLM/X3Vi4X+c6xQ85TQIDAQABMA0GCSqGSIb3 14 | DQEBBQUAA4IBAQAMWt9qMUOY5z1uyYcjUnconPHLM9MADCZI2sRbfdBOBHEnTVKv 15 | Y63SWnCt8TRJb01LKLIEys6pW1NUlxr6b+FwicNmycR0L8b63cmNXg2NmSZsnK9C 16 | fGT6BbbDdVPYjvmghpSd3soBGBLPsJvaFc6UL5tunm+hT7PxWjDxHZEiE18PTs05 17 | Vpp/ytILzhoXvJeFOWQHIdf4DLR5izGMNTKdQzgg1eBq2vKgjJIlEZ3j/AyHkJLE 18 | qFip1tyc0PRzgKYFLWttaZzakCLJOGuxtvYB+GrixVM7U23p5LQbLE0KX7fe2Gql 19 | xKMfSID5NUDNf1SuSrrGLD3gfnJEKVB8TVBk 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/intermediateCA-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDWDCCAkCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEO 3 | MAwGA1UECAwFRHVtbXkxDjAMBgNVBAcMBUR1bW15MQ4wDAYDVQQKDAVEdW1teTEO 4 | MAwGA1UECwwFRHVtbXkxETAPBgNVBAMMCER1bW15IENBMB4XDTEzMTAyMTE5MjQy 5 | M1oXDTE4MDkyNTE5MjQyM1owbTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBUR1bW15 6 | MQ4wDAYDVQQHDAVEdW1teTEOMAwGA1UECgwFRHVtbXkxDjAMBgNVBAsMBUR1bW15 7 | MR4wHAYDVQQDDBVEdW1teSBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEB 8 | AQUAA4IBDwAwggEKAoIBAQDPfZIHpVYbb0zzNMISwjRiO2mqpgzGcFuTvNxBmGGH 9 | YTa+jAjdMakzdtNmPndgHu2e4eXvvxeRrAxjBwGrMGe8FqYvefBhjHktPJhgdGHE 10 | X2BEhXGSncx7FDl0qkT5n672x43DAUdTJKx7ovbFfWU3QAsgyNQUzfj0V+ojcPTj 11 | mSscmmc37ZPHp3yGkPeu/G9LGNzV6/NoM9Z4FNHKpwZ9dTT2wNQVGyEreNl2JKXw 12 | xhPIHkrIync0Tvj6SV9s4WaoZfCMvEQgA6yvSmGlOUhRG8vYIilgJ0dC/L9qd2VY 13 | CSCCHNEWXloY6plhjpOUJzAg3UQDUEO07KMP7pFp17FbAgMBAAGjEDAOMAwGA1Ud 14 | EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADmgjS9oIh1PPtvxmykgdyP4ITQX 15 | hACIqD6hTYSUkJYC5mq0IFGgZiA4BRiqKj6aUGCv60pwrJtZMNUXFJy0kWobw0WK 16 | 3c0vxsWM/tB2IGOkl9vjKo7BPci2Bi1JetmK3hbqXV/7QXkNj9IjANm5b5NFu3QX 17 | 6mtyEwGG/o1+jydxdqk3bWyQWj/ZbU1spGR66oLJh+5q0G4wBX8ZHRkxqZrOIYTa 18 | R8egZhLofldpXZwk5UY8vzf2iMOxQt47ge31ruIjnsKJoedcHUkP7a5VYA5OTOmK 19 | ZOauxdGZp3BMfl1TrIgsDwshlBoy+aHMHmeYa7bpsblLRgKxZclJg4C9uXA= 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/mosquitto.org.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC8DCCAlmgAwIBAgIJAOD63PlXjJi8MA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD 3 | VQQGEwJHQjEXMBUGA1UECAwOVW5pdGVkIEtpbmdkb20xDjAMBgNVBAcMBURlcmJ5 4 | MRIwEAYDVQQKDAlNb3NxdWl0dG8xCzAJBgNVBAsMAkNBMRYwFAYDVQQDDA1tb3Nx 5 | dWl0dG8ub3JnMR8wHQYJKoZIhvcNAQkBFhByb2dlckBhdGNob28ub3JnMB4XDTEy 6 | MDYyOTIyMTE1OVoXDTIyMDYyNzIyMTE1OVowgZAxCzAJBgNVBAYTAkdCMRcwFQYD 7 | VQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwGA1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1v 8 | c3F1aXR0bzELMAkGA1UECwwCQ0ExFjAUBgNVBAMMDW1vc3F1aXR0by5vcmcxHzAd 9 | BgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hvby5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD 10 | gY0AMIGJAoGBAMYkLmX7SqOT/jJCZoQ1NWdCrr/pq47m3xxyXcI+FLEmwbE3R9vM 11 | rE6sRbP2S89pfrCt7iuITXPKycpUcIU0mtcT1OqxGBV2lb6RaOT2gC5pxyGaFJ+h 12 | A+GIbdYKO3JprPxSBoRponZJvDGEZuM3N7p3S/lRoi7G5wG5mvUmaE5RAgMBAAGj 13 | UDBOMB0GA1UdDgQWBBTad2QneVztIPQzRRGj6ZHKqJTv5jAfBgNVHSMEGDAWgBTa 14 | d2QneVztIPQzRRGj6ZHKqJTv5jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA 15 | A4GBAAqw1rK4NlRUCUBLhEFUQasjP7xfFqlVbE2cRy0Rs4o3KS0JwzQVBwG85xge 16 | REyPOFdGdhBY2P1FNRy0MDr6xr+D2ZOwxs63dG1nnAnWZg7qwoLgpZ4fESPD3PkA 17 | 1ZgKJc2zbSQ9fCPxt2W3mdVav66c6fsb7els2W2Iz7gERJSX 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/rootCA-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDizCCAnOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEO 3 | MAwGA1UECAwFRHVtbXkxDjAMBgNVBAcMBUR1bW15MQ4wDAYDVQQKDAVEdW1teTEO 4 | MAwGA1UECwwFRHVtbXkxETAPBgNVBAMMCER1bW15IENBMB4XDTEzMTAyMTE5MjQy 5 | M1oXDTE4MDkyNTE5MjQyM1owYDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBUR1bW15 6 | MQ4wDAYDVQQHDAVEdW1teTEOMAwGA1UECgwFRHVtbXkxDjAMBgNVBAsMBUR1bW15 7 | MREwDwYDVQQDDAhEdW1teSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 8 | ggEBAMLR0DHck8OtiA34k/7MqgQdharDu72HBPBCZxQ0SlaUK7/Qa3IwODk1IIzj 9 | fmWCsH4+HfEYgrfWGVlD7YG+61FE/HeeN63hoBi5S1l5kIGk5FIv/OL/mBBe1ROa 10 | FmIa4MurHa7a0UDUl7Hm4/GXLCpSc6vQohXzHpqwZ9BiZ0t0sLuP754yakwnToJ8 11 | FmbOBumj2TZP9D68gACTwcoxzwNo1OWLOEW2GzWwwOlKYnWDAaq5wQvA7pfAcyPN 12 | NOy7PJU1yC1p/4bYH8gEfhjeYsJLN8aqjgO/Kw2XICp1R+yYKTxkUu+Ri2MPavjC 13 | nQhqYWhvZJpWsgq8e1k9f/26EksCAwEAAaNQME4wHQYDVR0OBBYEFFu7Po4tkK2u 14 | WAf/UwAYmP9EhEy6MB8GA1UdIwQYMBaAFFu7Po4tkK2uWAf/UwAYmP9EhEy6MAwG 15 | A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADyJC71JEKYa9ipLXwI97vMZ 16 | T8kQeZwB74giPQNbGhRGtn+br6WZGtTUm9Zvwf6Wj5qeR0K07iFWasSSOGyBzY4x 17 | Q4Z8lxWQgNgh8Ea+Ki/ylgeFdKj6G3iPgMFevNkGwjOejvkI3UN7b1oiZ0Z4XftK 18 | TsLGKZQXU6bFqdZnBk8H79pbRSGDyzGy3NysExmYP5hfLLS02tRD16kabrbPvoWo 19 | gB+KwZWKg6Sv0iNKthiHTigxNgMsv+SetnX9xGjtTdWo+qWBExccQ2cCHNDmAG6L 20 | E+ZgH7pAeJMlyllaccxY1FJjHbM8zjfxiXj8E/qz6iKvF2iKoVlX9RpJbrn2X7M= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/samplecerts/server-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDYTCCAkmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBtMQswCQYDVQQGEwJVUzEO 3 | MAwGA1UECAwFRHVtbXkxDjAMBgNVBAcMBUR1bW15MQ4wDAYDVQQKDAVEdW1teTEO 4 | MAwGA1UECwwFRHVtbXkxHjAcBgNVBAMMFUR1bW15IEludGVybWVkaWF0ZSBDQTAe 5 | Fw0xMzEwMjExOTI0MjNaFw0xODA5MjUxOTI0MjNaMGYxCzAJBgNVBAYTAlVTMQ4w 6 | DAYDVQQIDAVEdW1teTEOMAwGA1UEBwwFRHVtbXkxDjAMBgNVBAoMBUR1bW15MQ4w 7 | DAYDVQQLDAVEdW1teTEXMBUGA1UEAwwORHVtbXkgKHNlcnZlcikwggEiMA0GCSqG 8 | SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0fQCRUWXt+i7JMR55Zuo6wBRxG7RnPutN 9 | 2L7J/18io52vxjm8AZDiC0JFkCHh72ZzvbgVA+e+WxAIYfioRis4JWw4jK8v5m8q 10 | cZzS0GJNTMROPiZQi7A81tAbrV00XN7d5PsmIJ2Bf4XbJWMy31CsmoFloeRMd7bR 11 | LxwDIb0qqRawhKsWdfZB/c9wGKmHlei50B7PXk+koKnVdsLwXxtCZDvc/3fNRHEK 12 | lZs4m0N05G38FdrnczPm/0pie87nK9rnklL7u1sYOukOznnOtW5h7+A4M+DxzME0 13 | HRU6k4d+6QvukxBlsE93gHhwRsejIuDGlqD+DRxk2PdmmgsmPH59AgMBAAGjEzAR 14 | MA8GA1UdEQQIMAaHBAoKBOQwDQYJKoZIhvcNAQEFBQADggEBAJ3bKs2b4cAJWTZj 15 | 69dMEfYZKcQIXs7euwtKlP7H8m5c+X5KmZPi1Puq4Z0gtvLu/z7J9UjZjG0CoylV 16 | q15Zp5svryJ7XzcsZs7rwyo1JtngW1z54wr9MezqIOF2w12dTwEAINFsW7TxAsH7 17 | bfqkzZjuCbbsww5q4eHuZp0yaMHc3hOGaUot27OTlxlIMhv7VBBqWAj0jmvAfTKf 18 | la0SiL/Mc8rD8D5C0SXGcCL6li/kqtinAxzhokuyyPf+hQX35kcZxEPu6WxtYVLv 19 | hMzrokOZP2FrGbCnhaNT8gw4Aa0RXV1JgonRWYSbkeaCzvr2bJ0OuJiDdwdRKvOo 20 | raKLlfY= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/samples/simple.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * 9 | * Contributors: 10 | * Seth Hoenig 11 | * Allan Stockdill-Mander 12 | * Mike Robertson 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | "time" 21 | 22 | MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" 23 | ) 24 | 25 | var f MQTT.MessageHandler = func(client *MQTT.Client, msg MQTT.Message) { 26 | fmt.Printf("TOPIC: %s\n", msg.Topic()) 27 | fmt.Printf("MSG: %s\n", msg.Payload()) 28 | } 29 | 30 | func main() { 31 | opts := MQTT.NewClientOptions().AddBroker("tcp://iot.eclipse.org:1883").SetClientID("gotrivial") 32 | opts.SetDefaultPublishHandler(f) 33 | 34 | c := MQTT.NewClient(opts) 35 | if token := c.Connect(); token.Wait() && token.Error() != nil { 36 | panic(token.Error()) 37 | } 38 | 39 | if token := c.Subscribe("/go-mqtt/sample", 0, nil); token.Wait() && token.Error() != nil { 40 | fmt.Println(token.Error()) 41 | os.Exit(1) 42 | } 43 | 44 | for i := 0; i < 5; i++ { 45 | text := fmt.Sprintf("this is msg #%d!", i) 46 | token := c.Publish("/go-mqtt/sample", 0, false, text) 47 | token.Wait() 48 | } 49 | 50 | time.Sleep(3 * time.Second) 51 | 52 | if token := c.Unsubscribe("/go-mqtt/sample"); token.Wait() && token.Error() != nil { 53 | fmt.Println(token.Error()) 54 | os.Exit(1) 55 | } 56 | 57 | c.Disconnect(250) 58 | } 59 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/trace.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * 9 | * Contributors: 10 | * Seth Hoenig 11 | * Allan Stockdill-Mander 12 | * Mike Robertson 13 | */ 14 | 15 | package mqtt 16 | 17 | import ( 18 | "io/ioutil" 19 | "log" 20 | ) 21 | 22 | // Internal levels of library output that are initialised to not print 23 | // anything but can be overridden by programmer 24 | var ( 25 | ERROR *log.Logger 26 | CRITICAL *log.Logger 27 | WARN *log.Logger 28 | DEBUG *log.Logger 29 | ) 30 | 31 | func init() { 32 | ERROR = log.New(ioutil.Discard, "", 0) 33 | CRITICAL = log.New(ioutil.Discard, "", 0) 34 | WARN = log.New(ioutil.Discard, "", 0) 35 | DEBUG = log.New(ioutil.Discard, "", 0) 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore: -------------------------------------------------------------------------------- 1 | logrus 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.3 4 | - 1.4 5 | - tip 6 | install: 7 | - go get -t ./... 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.9.0 (Unreleased) 2 | 3 | * logrus/text_formatter: don't emit empty msg 4 | * logrus/hooks/airbrake: move out of main repository 5 | * logrus/hooks/sentry: move out of main repository 6 | * logrus/hooks/papertrail: move out of main repository 7 | * logrus/hooks/bugsnag: move out of main repository 8 | 9 | # 0.8.7 10 | 11 | * logrus/core: fix possible race (#216) 12 | * logrus/doc: small typo fixes and doc improvements 13 | 14 | 15 | # 0.8.6 16 | 17 | * hooks/raven: allow passing an initialized client 18 | 19 | # 0.8.5 20 | 21 | * logrus/core: revert #208 22 | 23 | # 0.8.4 24 | 25 | * formatter/text: fix data race (#218) 26 | 27 | # 0.8.3 28 | 29 | * logrus/core: fix entry log level (#208) 30 | * logrus/core: improve performance of text formatter by 40% 31 | * logrus/core: expose `LevelHooks` type 32 | * logrus/core: add support for DragonflyBSD and NetBSD 33 | * formatter/text: print structs more verbosely 34 | 35 | # 0.8.2 36 | 37 | * logrus: fix more Fatal family functions 38 | 39 | # 0.8.1 40 | 41 | * logrus: fix not exiting on `Fatalf` and `Fatalln` 42 | 43 | # 0.8.0 44 | 45 | * logrus: defaults to stderr instead of stdout 46 | * hooks/sentry: add special field for `*http.Request` 47 | * formatter/text: ignore Windows for colors 48 | 49 | # 0.7.3 50 | 51 | * formatter/\*: allow configuration of timestamp layout 52 | 53 | # 0.7.2 54 | 55 | * formatter/text: Add configuration option for time format (#158) 56 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Simon Eskildsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus is a structured logger for Go, completely API compatible with the standard library logger. 3 | 4 | 5 | The simplest way to use Logrus is simply the package-level exported logger: 6 | 7 | package main 8 | 9 | import ( 10 | log "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | log.WithFields(log.Fields{ 15 | "animal": "walrus", 16 | "number": 1, 17 | "size": 10, 18 | }).Info("A walrus appears") 19 | } 20 | 21 | Output: 22 | time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 23 | 24 | For a full guide visit https://github.com/Sirupsen/logrus 25 | */ 26 | package logrus 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | ) 6 | 7 | var log = logrus.New() 8 | 9 | func init() { 10 | log.Formatter = new(logrus.JSONFormatter) 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Level = logrus.DebugLevel 13 | } 14 | 15 | func main() { 16 | defer func() { 17 | err := recover() 18 | if err != nil { 19 | log.WithFields(logrus.Fields{ 20 | "omg": true, 21 | "err": err, 22 | "number": 100, 23 | }).Fatal("The ice breaks!") 24 | } 25 | }() 26 | 27 | log.WithFields(logrus.Fields{ 28 | "animal": "walrus", 29 | "number": 8, 30 | }).Debug("Started observing beach") 31 | 32 | log.WithFields(logrus.Fields{ 33 | "animal": "walrus", 34 | "size": 10, 35 | }).Info("A group of walrus emerges from the ocean") 36 | 37 | log.WithFields(logrus.Fields{ 38 | "omg": true, 39 | "number": 122, 40 | }).Warn("The group's number increased tremendously!") 41 | 42 | log.WithFields(logrus.Fields{ 43 | "temperature": -4, 44 | }).Debug("Temperature changes") 45 | 46 | log.WithFields(logrus.Fields{ 47 | "animal": "orca", 48 | "size": 9009, 49 | }).Panic("It's over 9000!") 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | "gopkg.in/gemnasium/logrus-airbrake-hook.v2" 6 | ) 7 | 8 | var log = logrus.New() 9 | 10 | func init() { 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Hooks.Add(airbrake.NewHook(123, "xyz", "development")) 13 | } 14 | 15 | func main() { 16 | log.WithFields(logrus.Fields{ 17 | "animal": "walrus", 18 | "size": 10, 19 | }).Info("A group of walrus emerges from the ocean") 20 | 21 | log.WithFields(logrus.Fields{ 22 | "omg": true, 23 | "number": 122, 24 | }).Warn("The group's number increased tremendously!") 25 | 26 | log.WithFields(logrus.Fields{ 27 | "omg": true, 28 | "number": 100, 29 | }).Fatal("The ice breaks!") 30 | } 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import "time" 4 | 5 | const DefaultTimestampFormat = time.RFC3339 6 | 7 | // The Formatter interface is used to implement a custom Formatter. It takes an 8 | // `Entry`. It exposes all the fields, including the default ones: 9 | // 10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. 11 | // * `entry.Data["time"]`. The timestamp. 12 | // * `entry.Data["level"]. The level the entry was logged at. 13 | // 14 | // Any additional fields added with `WithField` or `WithFields` are also in 15 | // `entry.Data`. Format is expected to return an array of bytes which are then 16 | // logged to `logger.Out`. 17 | type Formatter interface { 18 | Format(*Entry) ([]byte, error) 19 | } 20 | 21 | // This is to not silently overwrite `time`, `msg` and `level` fields when 22 | // dumping it. If this code wasn't there doing: 23 | // 24 | // logrus.WithField("level", 1).Info("hello") 25 | // 26 | // Would just silently drop the user provided level. Instead with this code 27 | // it'll logged as: 28 | // 29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} 30 | // 31 | // It's not exported because it's still using Data in an opinionated way. It's to 32 | // avoid code duplication between the two default formatters. 33 | func prefixFieldClashes(data Fields) { 34 | _, ok := data["time"] 35 | if ok { 36 | data["fields.time"] = data["time"] 37 | } 38 | 39 | _, ok = data["msg"] 40 | if ok { 41 | data["fields.msg"] = data["msg"] 42 | } 43 | 44 | _, ok = data["level"] 45 | if ok { 46 | data["fields.level"] = data["level"] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/formatters/logstash/logstash.go: -------------------------------------------------------------------------------- 1 | package logstash 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/Sirupsen/logrus" 8 | ) 9 | 10 | // Formatter generates json in logstash format. 11 | // Logstash site: http://logstash.net/ 12 | type LogstashFormatter struct { 13 | Type string // if not empty use for logstash type field. 14 | 15 | // TimestampFormat sets the format used for timestamps. 16 | TimestampFormat string 17 | } 18 | 19 | func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { 20 | entry.Data["@version"] = 1 21 | 22 | if f.TimestampFormat == "" { 23 | f.TimestampFormat = logrus.DefaultTimestampFormat 24 | } 25 | 26 | entry.Data["@timestamp"] = entry.Time.Format(f.TimestampFormat) 27 | 28 | // set message field 29 | v, ok := entry.Data["message"] 30 | if ok { 31 | entry.Data["fields.message"] = v 32 | } 33 | entry.Data["message"] = entry.Message 34 | 35 | // set level field 36 | v, ok = entry.Data["level"] 37 | if ok { 38 | entry.Data["fields.level"] = v 39 | } 40 | entry.Data["level"] = entry.Level.String() 41 | 42 | // set type field 43 | if f.Type != "" { 44 | v, ok = entry.Data["type"] 45 | if ok { 46 | entry.Data["fields.type"] = v 47 | } 48 | entry.Data["type"] = f.Type 49 | } 50 | 51 | serialized, err := json.Marshal(entry.Data) 52 | if err != nil { 53 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 54 | } 55 | return append(serialized, '\n'), nil 56 | } 57 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // A hook to be fired when logging on the logging levels returned from 4 | // `Levels()` on your implementation of the interface. Note that this is not 5 | // fired in a goroutine or a channel with workers, you should handle such 6 | // functionality yourself if your call is non-blocking and you don't wish for 7 | // the logging calls for levels returned from `Levels()` to block. 8 | type Hook interface { 9 | Levels() []Level 10 | Fire(*Entry) error 11 | } 12 | 13 | // Internal type for storing the hooks on a logger instance. 14 | type LevelHooks map[Level][]Hook 15 | 16 | // Add a hook to an instance of logger. This is called with 17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. 18 | func (hooks LevelHooks) Add(hook Hook) { 19 | for _, level := range hook.Levels() { 20 | hooks[level] = append(hooks[level], hook) 21 | } 22 | } 23 | 24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire 25 | // appropriate hooks for a log entry. 26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error { 27 | for _, hook := range hooks[level] { 28 | if err := hook.Fire(entry); err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md: -------------------------------------------------------------------------------- 1 | # Syslog Hooks for Logrus :walrus: 2 | 3 | ## Usage 4 | 5 | ```go 6 | import ( 7 | "log/syslog" 8 | "github.com/Sirupsen/logrus" 9 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" 10 | ) 11 | 12 | func main() { 13 | log := logrus.New() 14 | hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") 15 | 16 | if err == nil { 17 | log.Hooks.Add(hook) 18 | } 19 | } 20 | ``` 21 | 22 | If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following. 23 | 24 | ```go 25 | import ( 26 | "log/syslog" 27 | "github.com/Sirupsen/logrus" 28 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" 29 | ) 30 | 31 | func main() { 32 | log := logrus.New() 33 | hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") 34 | 35 | if err == nil { 36 | log.Hooks.Add(hook) 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!nacl,!plan9 2 | 3 | package logrus_syslog 4 | 5 | import ( 6 | "fmt" 7 | "github.com/Sirupsen/logrus" 8 | "log/syslog" 9 | "os" 10 | ) 11 | 12 | // SyslogHook to send logs via syslog. 13 | type SyslogHook struct { 14 | Writer *syslog.Writer 15 | SyslogNetwork string 16 | SyslogRaddr string 17 | } 18 | 19 | // Creates a hook to be added to an instance of logger. This is called with 20 | // `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` 21 | // `if err == nil { log.Hooks.Add(hook) }` 22 | func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { 23 | w, err := syslog.Dial(network, raddr, priority, tag) 24 | return &SyslogHook{w, network, raddr}, err 25 | } 26 | 27 | func (hook *SyslogHook) Fire(entry *logrus.Entry) error { 28 | line, err := entry.String() 29 | if err != nil { 30 | fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) 31 | return err 32 | } 33 | 34 | switch entry.Level { 35 | case logrus.PanicLevel: 36 | return hook.Writer.Crit(line) 37 | case logrus.FatalLevel: 38 | return hook.Writer.Crit(line) 39 | case logrus.ErrorLevel: 40 | return hook.Writer.Err(line) 41 | case logrus.WarnLevel: 42 | return hook.Writer.Warning(line) 43 | case logrus.InfoLevel: 44 | return hook.Writer.Info(line) 45 | case logrus.DebugLevel: 46 | return hook.Writer.Debug(line) 47 | default: 48 | return nil 49 | } 50 | } 51 | 52 | func (hook *SyslogHook) Levels() []logrus.Level { 53 | return []logrus.Level{ 54 | logrus.PanicLevel, 55 | logrus.FatalLevel, 56 | logrus.ErrorLevel, 57 | logrus.WarnLevel, 58 | logrus.InfoLevel, 59 | logrus.DebugLevel, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type JSONFormatter struct { 9 | // TimestampFormat sets the format used for marshaling timestamps. 10 | TimestampFormat string 11 | } 12 | 13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { 14 | data := make(Fields, len(entry.Data)+3) 15 | for k, v := range entry.Data { 16 | switch v := v.(type) { 17 | case error: 18 | // Otherwise errors are ignored by `encoding/json` 19 | // https://github.com/Sirupsen/logrus/issues/137 20 | data[k] = v.Error() 21 | default: 22 | data[k] = v 23 | } 24 | } 25 | prefixFieldClashes(data) 26 | 27 | timestampFormat := f.TimestampFormat 28 | if timestampFormat == "" { 29 | timestampFormat = DefaultTimestampFormat 30 | } 31 | 32 | data["time"] = entry.Time.Format(timestampFormat) 33 | data["msg"] = entry.Message 34 | data["level"] = entry.Level.String() 35 | 36 | serialized, err := json.Marshal(data) 37 | if err != nil { 38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 39 | } 40 | return append(serialized, '\n'), nil 41 | } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | 3 | package logrus 4 | 5 | import "syscall" 6 | 7 | const ioctlReadTermios = syscall.TIOCGETA 8 | 9 | type Termios syscall.Termios 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2013 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package logrus 7 | 8 | import "syscall" 9 | 10 | const ioctlReadTermios = syscall.TCGETS 11 | 12 | type Termios syscall.Termios 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build linux darwin freebsd openbsd netbsd dragonfly 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | // IsTerminal returns true if stderr's file descriptor is a terminal. 16 | func IsTerminal() bool { 17 | fd := syscall.Stderr 18 | var termios Termios 19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 20 | return err == 0 21 | } 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris 2 | 3 | package logrus 4 | 5 | import ( 6 | "os" 7 | 8 | "golang.org/x/sys/unix" 9 | ) 10 | 11 | // IsTerminal returns true if the given file descriptor is a terminal. 12 | func IsTerminal() bool { 13 | _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) 14 | return err == nil 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | var ( 18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 19 | ) 20 | 21 | // IsTerminal returns true if stderr's file descriptor is a terminal. 22 | func IsTerminal() bool { 23 | fd := syscall.Stderr 24 | var st uint32 25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 26 | return r != 0 && e == 0 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/writer.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | func (logger *Logger) Writer() *io.PipeWriter { 10 | reader, writer := io.Pipe() 11 | 12 | go logger.writerScanner(reader) 13 | runtime.SetFinalizer(writer, writerFinalizer) 14 | 15 | return writer 16 | } 17 | 18 | func (logger *Logger) writerScanner(reader *io.PipeReader) { 19 | scanner := bufio.NewScanner(reader) 20 | for scanner.Scan() { 21 | logger.Print(scanner.Text()) 22 | } 23 | if err := scanner.Err(); err != nil { 24 | logger.Errorf("Error while reading from Writer: %s", err) 25 | } 26 | reader.Close() 27 | } 28 | 29 | func writerFinalizer(writer *io.PipeWriter) { 30 | writer.Close() 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/inject/.gitignore: -------------------------------------------------------------------------------- 1 | inject 2 | inject.test 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/inject/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/inject/update_readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | go get github.com/robertkrimen/godocdown/godocdown 3 | godocdown > README.md 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/client/cancelreq.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // borrowed from golang/net/context/ctxhttp/cancelreq.go 6 | 7 | package client 8 | 9 | import "net/http" 10 | 11 | func requestCanceler(tr CancelableTransport, req *http.Request) func() { 12 | ch := make(chan struct{}) 13 | req.Cancel = ch 14 | 15 | return func() { 16 | close(ch) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/client/cluster_error.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package client 16 | 17 | import "fmt" 18 | 19 | type ClusterError struct { 20 | Errors []error 21 | } 22 | 23 | func (ce *ClusterError) Error() string { 24 | return ErrClusterUnavailable.Error() 25 | } 26 | 27 | func (ce *ClusterError) Detail() string { 28 | s := "" 29 | for i, e := range ce.Errors { 30 | s += fmt.Sprintf("error #%d: %s\n", i, e) 31 | } 32 | return s 33 | } 34 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/client/discover.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package client 16 | 17 | // Discoverer is an interface that wraps the Discover method. 18 | type Discoverer interface { 19 | // Discover looks up the etcd servers for the domain. 20 | Discover(domain string) ([]string, error) 21 | } 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/client/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package client 16 | 17 | // IsKeyNotFound returns true if the error code is ErrorCodeKeyNotFound. 18 | func IsKeyNotFound(err error) bool { 19 | if cErr, ok := err.(Error); ok { 20 | return cErr.Code == ErrorCodeKeyNotFound 21 | } 22 | return false 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/pkg/pathutil/path.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package pathutil implements utility functions for handling slash-separated 6 | // paths. 7 | package pathutil 8 | 9 | import "path" 10 | 11 | // CanonicalURLPath returns the canonical url path for p, which follows the rules: 12 | // 1. the path always starts with "/" 13 | // 2. replace multiple slashes with a single slash 14 | // 3. replace each '.' '..' path name element with equivalent one 15 | // 4. keep the trailing slash 16 | // The function is borrowed from stdlib http.cleanPath in server.go. 17 | func CanonicalURLPath(p string) string { 18 | if p == "" { 19 | return "/" 20 | } 21 | if p[0] != '/' { 22 | p = "/" + p 23 | } 24 | np := path.Clean(p) 25 | // path.Clean removes trailing slash except for root, 26 | // put the trailing slash back if necessary. 27 | if p[len(p)-1] == '/' && np != "/" { 28 | np += "/" 29 | } 30 | return np 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/pkg/types/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package types declares various data types and implements type-checking 16 | // functions. 17 | package types 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/pkg/types/id.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package types 16 | 17 | import ( 18 | "strconv" 19 | ) 20 | 21 | // ID represents a generic identifier which is canonically 22 | // stored as a uint64 but is typically represented as a 23 | // base-16 string for input/output 24 | type ID uint64 25 | 26 | func (i ID) String() string { 27 | return strconv.FormatUint(uint64(i), 16) 28 | } 29 | 30 | // IDFromString attempts to create an ID from a base-16 string. 31 | func IDFromString(s string) (ID, error) { 32 | i, err := strconv.ParseUint(s, 16, 64) 33 | return ID(i), err 34 | } 35 | 36 | // IDSlice implements the sort interface 37 | type IDSlice []ID 38 | 39 | func (p IDSlice) Len() int { return len(p) } 40 | func (p IDSlice) Less(i, j int) bool { return uint64(p[i]) < uint64(p[j]) } 41 | func (p IDSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/etcd/pkg/types/slice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package types 16 | 17 | // Uint64Slice implements sort interface 18 | type Uint64Slice []uint64 19 | 20 | func (p Uint64Slice) Len() int { return len(p) } 21 | func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] } 22 | func (p Uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/garyburd/redigo/internal/commandinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package internal 16 | 17 | import ( 18 | "strings" 19 | ) 20 | 21 | const ( 22 | WatchState = 1 << iota 23 | MultiState 24 | SubscribeState 25 | MonitorState 26 | ) 27 | 28 | type CommandInfo struct { 29 | Set, Clear int 30 | } 31 | 32 | var commandInfos = map[string]CommandInfo{ 33 | "WATCH": {Set: WatchState}, 34 | "UNWATCH": {Clear: WatchState}, 35 | "MULTI": {Set: MultiState}, 36 | "EXEC": {Clear: WatchState | MultiState}, 37 | "DISCARD": {Clear: WatchState | MultiState}, 38 | "PSUBSCRIBE": {Set: SubscribeState}, 39 | "SUBSCRIBE": {Set: SubscribeState}, 40 | "MONITOR": {Set: MonitorState}, 41 | } 42 | 43 | func init() { 44 | for n, ci := range commandInfos { 45 | commandInfos[strings.ToLower(n)] = ci 46 | } 47 | } 48 | 49 | func LookupCommandInfo(commandName string) CommandInfo { 50 | if ci, ok := commandInfos[commandName]; ok { 51 | return ci 52 | } 53 | return commandInfos[strings.ToUpper(commandName)] 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/garyburd/redigo/redis/redis.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | // Error represents an error returned in a command reply. 18 | type Error string 19 | 20 | func (err Error) Error() string { return string(err) } 21 | 22 | // Conn represents a connection to a Redis server. 23 | type Conn interface { 24 | // Close closes the connection. 25 | Close() error 26 | 27 | // Err returns a non-nil value if the connection is broken. The returned 28 | // value is either the first non-nil value returned from the underlying 29 | // network connection or a protocol parsing error. Applications should 30 | // close broken connections. 31 | Err() error 32 | 33 | // Do sends a command to the server and returns the received reply. 34 | Do(commandName string, args ...interface{}) (reply interface{}, err error) 35 | 36 | // Send writes the command to the client's output buffer. 37 | Send(commandName string, args ...interface{}) error 38 | 39 | // Flush flushes the output buffer to the Redis server. 40 | Flush() error 41 | 42 | // Receive receives a single reply from the Redis server 43 | Receive() (reply interface{}, err error) 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | 25 | /.godeps 26 | /.envrc 27 | 28 | # Godeps 29 | Godeps/_workspace 30 | Godeps/Readme 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/go-martini/martini", 3 | "GoVersion": "go1.4.2", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/codegangsta/inject", 7 | "Comment": "v1.0-rc1-10-g33e0aa1", 8 | "Rev": "33e0aa1cb7c019ccc3fbe049a8262a6403d30504" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/env.go: -------------------------------------------------------------------------------- 1 | package martini 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | // Envs 8 | const ( 9 | Dev string = "development" 10 | Prod string = "production" 11 | Test string = "test" 12 | ) 13 | 14 | // Env is the environment that Martini is executing in. The MARTINI_ENV is read on initialization to set this variable. 15 | var Env = Dev 16 | var Root string 17 | 18 | func setENV(e string) { 19 | if len(e) > 0 { 20 | Env = e 21 | } 22 | } 23 | 24 | func init() { 25 | setENV(os.Getenv("MARTINI_ENV")) 26 | var err error 27 | Root, err = os.Getwd() 28 | if err != nil { 29 | panic(err) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/go_version.go: -------------------------------------------------------------------------------- 1 | // +build !go1.1 2 | 3 | package martini 4 | 5 | func MartiniDoesNotSupportGo1Point0() { 6 | "Martini requires Go 1.1 or greater." 7 | } 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/logger.go: -------------------------------------------------------------------------------- 1 | package martini 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | // Logger returns a middleware handler that logs the request as it goes in and the response as it goes out. 10 | func Logger() Handler { 11 | return func(res http.ResponseWriter, req *http.Request, c Context, log *log.Logger) { 12 | start := time.Now() 13 | 14 | addr := req.Header.Get("X-Real-IP") 15 | if addr == "" { 16 | addr = req.Header.Get("X-Forwarded-For") 17 | if addr == "" { 18 | addr = req.RemoteAddr 19 | } 20 | } 21 | 22 | log.Printf("Started %s %s for %s", req.Method, req.URL.Path, addr) 23 | 24 | rw := res.(ResponseWriter) 25 | c.Next() 26 | 27 | log.Printf("Completed %v %s in %v\n", rw.Status(), http.StatusText(rw.Status()), time.Since(start)) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/return_handler.go: -------------------------------------------------------------------------------- 1 | package martini 2 | 3 | import ( 4 | "github.com/codegangsta/inject" 5 | "net/http" 6 | "reflect" 7 | ) 8 | 9 | // ReturnHandler is a service that Martini provides that is called 10 | // when a route handler returns something. The ReturnHandler is 11 | // responsible for writing to the ResponseWriter based on the values 12 | // that are passed into this function. 13 | type ReturnHandler func(Context, []reflect.Value) 14 | 15 | func defaultReturnHandler() ReturnHandler { 16 | return func(ctx Context, vals []reflect.Value) { 17 | rv := ctx.Get(inject.InterfaceOf((*http.ResponseWriter)(nil))) 18 | res := rv.Interface().(http.ResponseWriter) 19 | var responseVal reflect.Value 20 | if len(vals) > 1 && vals[0].Kind() == reflect.Int { 21 | res.WriteHeader(int(vals[0].Int())) 22 | responseVal = vals[1] 23 | } else if len(vals) > 0 { 24 | responseVal = vals[0] 25 | } 26 | if canDeref(responseVal) { 27 | responseVal = responseVal.Elem() 28 | } 29 | if isByteSlice(responseVal) { 30 | res.Write(responseVal.Bytes()) 31 | } else { 32 | res.Write([]byte(responseVal.String())) 33 | } 34 | } 35 | } 36 | 37 | func isByteSlice(val reflect.Value) bool { 38 | return val.Kind() == reflect.Slice && val.Type().Elem().Kind() == reflect.Uint8 39 | } 40 | 41 | func canDeref(val reflect.Value) bool { 42 | return val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-martini/martini/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/golang@1.1.1 -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go: 4 | - 1.2 5 | - 1.3 6 | - 1.4 7 | - tip 8 | 9 | before_script: 10 | - mysql -e 'create database gotest;' 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Go-MySQL-Driver authors for copyright purposes. 2 | 3 | # If you are submitting a patch, please add your name or the name of the 4 | # organization which holds the copyright to this list in alphabetical order. 5 | 6 | # Names should be added to this file as 7 | # Name 8 | # The email address is not required for organizations. 9 | # Please keep the list sorted. 10 | 11 | 12 | # Individual Persons 13 | 14 | Aaron Hopkins 15 | Arne Hormann 16 | Carlos Nieto 17 | Chris Moos 18 | DisposaBoy 19 | Frederick Mayle 20 | Gustavo Kristic 21 | Hanno Braun 22 | Henri Yandell 23 | INADA Naoki 24 | James Harr 25 | Jian Zhen 26 | Joshua Prunier 27 | Julien Schmidt 28 | Kamil Dziedzic 29 | Leonardo YongUk Kim 30 | Lucas Liu 31 | Luke Scott 32 | Michael Woolnough 33 | Nicola Peduzzi 34 | Runrioter Wung 35 | Soroush Pour 36 | Stan Putrya 37 | Xiaobing Jiang 38 | Xiuming Chen 39 | 40 | # Organizations 41 | 42 | Barracuda Networks, Inc. 43 | Google Inc. 44 | Stripe Inc. 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/appengine.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | // +build appengine 10 | 11 | package mysql 12 | 13 | import ( 14 | "appengine/cloudsql" 15 | ) 16 | 17 | func init() { 18 | RegisterDial("cloudsql", cloudsql.Dial) 19 | } 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/result.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlResult struct { 12 | affectedRows int64 13 | insertId int64 14 | } 15 | 16 | func (res *mysqlResult) LastInsertId() (int64, error) { 17 | return res.insertId, nil 18 | } 19 | 20 | func (res *mysqlResult) RowsAffected() (int64, error) { 21 | return res.affectedRows, nil 22 | } 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/go-sql-driver/mysql/transaction.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlTx struct { 12 | mc *mysqlConn 13 | } 14 | 15 | func (tx *mysqlTx) Commit() (err error) { 16 | if tx.mc == nil || tx.mc.netConn == nil { 17 | return ErrInvalidConn 18 | } 19 | err = tx.mc.exec("COMMIT") 20 | tx.mc = nil 21 | return 22 | } 23 | 24 | func (tx *mysqlTx) Rollback() (err error) { 25 | if tx.mc == nil || tx.mc.netConn == nil { 26 | return ErrInvalidConn 27 | } 28 | err = tx.mc.exec("ROLLBACK") 29 | tx.mc = nil 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | gofmt: 4 | enabled: true 5 | govet: 6 | enabled: true 7 | golint: 8 | enabled: true 9 | ratings: 10 | paths: 11 | - "**.go" 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/.gitignore: -------------------------------------------------------------------------------- 1 | documents 2 | _book 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | ## Bug Report 4 | 5 | - Do a search on GitHub under Issues in case it has already been reported 6 | - Submit __executable script__ or failing test pull request that could demonstrates the issue is *MUST HAVE* 7 | 8 | ## Feature Request 9 | 10 | - Feature request with pull request is welcome 11 | - Or it won't be implemented until I (other developers) find it is helpful for my (their) daily work 12 | 13 | ## Pull Request 14 | 15 | - Prefer single commit pull request, that make the git history can be a bit easier to follow. 16 | - New features need to be covered with tests to make sure your code works as expected, and won't be broken by others in future 17 | 18 | ## Contributing to Documentation 19 | 20 | - You are welcome ;) 21 | - You can help improve the README by making them more coherent, consistent or readable, and add more godoc documents to make people easier to follow. 22 | - Blogs & Usage Guides & PPT also welcome, please add them to https://github.com/jinzhu/gorm/wiki/Guides 23 | 24 | ### Executable script template 25 | 26 | ```go 27 | package main 28 | 29 | import ( 30 | _ "github.com/mattn/go-sqlite3" 31 | _ "github.com/go-sql-driver/mysql" 32 | _ "github.com/lib/pq" 33 | "github.com/jinzhu/gorm" 34 | ) 35 | 36 | var db gorm.DB 37 | 38 | func init() { 39 | var err error 40 | db, err = gorm.Open("sqlite3", "test.db") 41 | // db, err := gorm.Open("postgres", "user=username dbname=password sslmode=disable") 42 | // db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True") 43 | if err != nil { 44 | panic(err) 45 | } 46 | db.LogMode(true) 47 | } 48 | 49 | func main() { 50 | // Your code 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-NOW Jinzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/README.md: -------------------------------------------------------------------------------- 1 | # GORM 2 | 3 | The fantastic ORM library for Golang, aims to be developer friendly. 4 | 5 | [![Join the chat at https://gitter.im/jinzhu/gorm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | [![wercker status](https://app.wercker.com/status/0cb7bb1039e21b74f8274941428e0921/s/master "wercker status")](https://app.wercker.com/project/bykey/0cb7bb1039e21b74f8274941428e0921) 7 | [![GoDoc](https://godoc.org/github.com/jinzhu/gorm?status.svg)](https://godoc.org/github.com/jinzhu/gorm) 8 | 9 | ## Overview 10 | 11 | * Full-Featured ORM (almost) 12 | * Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism) 13 | * Callbacks (Before/After Create/Save/Update/Delete/Find) 14 | * Preloading (eager loading) 15 | * Transactions 16 | * Composite Primary Key 17 | * SQL Builder 18 | * Auto Migrations 19 | * Logger 20 | * Extendable, write Plugins based on GORM callbacks 21 | * Every feature comes with tests 22 | * Developer Friendly 23 | 24 | ## Getting Started 25 | 26 | * GORM Guides [jinzhu.github.com/gorm](https://jinzhu.github.io/gorm) 27 | 28 | ## Upgrading To V1.0 29 | 30 | * [CHANGELOG](https://jinzhu.github.io/gorm/changelog.html) 31 | 32 | # Author 33 | 34 | **jinzhu** 35 | 36 | * 37 | * 38 | * 39 | 40 | # Contributors 41 | 42 | https://github.com/jinzhu/gorm/graphs/contributors 43 | 44 | ## License 45 | 46 | Released under the [MIT License](https://github.com/jinzhu/gorm/blob/master/License). 47 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/dialects/mysql/mysql.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import _ "github.com/go-sql-driver/mysql" 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/dialects/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "database/sql" 5 | "database/sql/driver" 6 | 7 | _ "github.com/lib/pq" 8 | "github.com/lib/pq/hstore" 9 | ) 10 | 11 | type Hstore map[string]*string 12 | 13 | // Value get value of Hstore 14 | func (h Hstore) Value() (driver.Value, error) { 15 | hstore := hstore.Hstore{Map: map[string]sql.NullString{}} 16 | if len(h) == 0 { 17 | return nil, nil 18 | } 19 | 20 | for key, value := range h { 21 | var s sql.NullString 22 | if value != nil { 23 | s.String = *value 24 | s.Valid = true 25 | } 26 | hstore.Map[key] = s 27 | } 28 | return hstore.Value() 29 | } 30 | 31 | // Scan scan value into Hstore 32 | func (h *Hstore) Scan(value interface{}) error { 33 | hstore := hstore.Hstore{} 34 | 35 | if err := hstore.Scan(value); err != nil { 36 | return err 37 | } 38 | 39 | if len(hstore.Map) == 0 { 40 | return nil 41 | } 42 | 43 | *h = Hstore{} 44 | for k := range hstore.Map { 45 | if hstore.Map[k].Valid { 46 | s := hstore.Map[k].String 47 | (*h)[k] = &s 48 | } else { 49 | (*h)[k] = nil 50 | } 51 | } 52 | 53 | return nil 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/dialects/sqlite/sqlite.go: -------------------------------------------------------------------------------- 1 | package sqlite 2 | 3 | import _ "github.com/mattn/go-sqlite3" 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/errors.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | ) 7 | 8 | var ( 9 | // ErrRecordNotFound record not found error, happens when haven't find any matched data when looking up with a struct 10 | ErrRecordNotFound = errors.New("record not found") 11 | // ErrInvalidSQL invalid SQL error, happens when you passed invalid SQL 12 | ErrInvalidSQL = errors.New("invalid SQL") 13 | // ErrInvalidTransaction invalid transaction when you are trying to `Commit` or `Rollback` 14 | ErrInvalidTransaction = errors.New("no valid transaction") 15 | // ErrCantStartTransaction can't start transaction when you are trying to start one with `Begin` 16 | ErrCantStartTransaction = errors.New("can't start transaction") 17 | // ErrUnaddressable unaddressable value 18 | ErrUnaddressable = errors.New("using unaddressable value") 19 | ) 20 | 21 | type errorsInterface interface { 22 | GetErrors() []error 23 | } 24 | 25 | // Errors contains all happened errors 26 | type Errors struct { 27 | errors []error 28 | } 29 | 30 | // GetErrors get all happened errors 31 | func (errs Errors) GetErrors() []error { 32 | return errs.errors 33 | } 34 | 35 | // Add add an error 36 | func (errs *Errors) Add(err error) { 37 | if errors, ok := err.(errorsInterface); ok { 38 | for _, err := range errors.GetErrors() { 39 | errs.Add(err) 40 | } 41 | } else { 42 | for _, e := range errs.errors { 43 | if err == e { 44 | return 45 | } 46 | } 47 | errs.errors = append(errs.errors, err) 48 | } 49 | } 50 | 51 | // Error format happened errors 52 | func (errs Errors) Error() string { 53 | var errors = []string{} 54 | for _, e := range errs.errors { 55 | errors = append(errors, e.Error()) 56 | } 57 | return strings.Join(errors, "; ") 58 | } 59 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/field.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "fmt" 7 | "reflect" 8 | ) 9 | 10 | // Field model field definition 11 | type Field struct { 12 | *StructField 13 | IsBlank bool 14 | Field reflect.Value 15 | } 16 | 17 | // Set set a value to the field 18 | func (field *Field) Set(value interface{}) (err error) { 19 | if !field.Field.IsValid() { 20 | return errors.New("field value not valid") 21 | } 22 | 23 | if !field.Field.CanAddr() { 24 | return ErrUnaddressable 25 | } 26 | 27 | reflectValue, ok := value.(reflect.Value) 28 | if !ok { 29 | reflectValue = reflect.ValueOf(value) 30 | } 31 | 32 | fieldValue := field.Field 33 | if reflectValue.IsValid() { 34 | if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { 35 | fieldValue.Set(reflectValue.Convert(fieldValue.Type())) 36 | } else { 37 | if fieldValue.Kind() == reflect.Ptr { 38 | if fieldValue.IsNil() { 39 | fieldValue.Set(reflect.New(field.Struct.Type.Elem())) 40 | } 41 | fieldValue = fieldValue.Elem() 42 | } 43 | 44 | if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { 45 | fieldValue.Set(reflectValue.Convert(fieldValue.Type())) 46 | } else if scanner, ok := fieldValue.Addr().Interface().(sql.Scanner); ok { 47 | err = scanner.Scan(reflectValue.Interface()) 48 | } else { 49 | err = fmt.Errorf("could not convert argument of field %s from %s to %s", field.Name, reflectValue.Type(), fieldValue.Type()) 50 | } 51 | } 52 | } else { 53 | field.Field.Set(reflect.Zero(field.Field.Type())) 54 | } 55 | 56 | field.IsBlank = isBlank(field.Field) 57 | return err 58 | } 59 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/interface.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import "database/sql" 4 | 5 | type sqlCommon interface { 6 | Exec(query string, args ...interface{}) (sql.Result, error) 7 | Prepare(query string) (*sql.Stmt, error) 8 | Query(query string, args ...interface{}) (*sql.Rows, error) 9 | QueryRow(query string, args ...interface{}) *sql.Row 10 | } 11 | 12 | type sqlDb interface { 13 | Begin() (*sql.Tx, error) 14 | } 15 | 16 | type sqlTx interface { 17 | Commit() error 18 | Rollback() error 19 | } 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/model.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import "time" 4 | 5 | // Model base model definition, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, which could be embedded in your models 6 | // type User struct { 7 | // gorm.Model 8 | // } 9 | type Model struct { 10 | ID uint `gorm:"primary_key"` 11 | CreatedAt time.Time 12 | UpdatedAt time.Time 13 | DeletedAt *time.Time `sql:"index"` 14 | } 15 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/gorm/test_all.sh: -------------------------------------------------------------------------------- 1 | dialects=("postgres" "mysql" "sqlite") 2 | 3 | for dialect in "${dialects[@]}" ; do 4 | GORM_DIALECT=${dialect} go test 5 | done 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/inflection/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 - Jinzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/inflection/README.md: -------------------------------------------------------------------------------- 1 | Inflection 2 | ========= 3 | 4 | Inflection pluralizes and singularizes English nouns 5 | 6 | ## Basic Usage 7 | 8 | ```go 9 | inflection.Plural("person") => "people" 10 | inflection.Plural("Person") => "People" 11 | inflection.Plural("PERSON") => "PEOPLE" 12 | inflection.Plural("bus") => "buses" 13 | inflection.Plural("BUS") => "BUSES" 14 | inflection.Plural("Bus") => "Buses" 15 | 16 | inflection.Singularize("people") => "person" 17 | inflection.Singularize("People") => "Person" 18 | inflection.Singularize("PEOPLE") => "PERSON" 19 | inflection.Singularize("buses") => "bus" 20 | inflection.Singularize("BUSES") => "BUS" 21 | inflection.Singularize("Buses") => "Bus" 22 | 23 | inflection.Plural("FancyPerson") => "FancyPeople" 24 | inflection.Singularize("FancyPeople") => "FancyPerson" 25 | ``` 26 | 27 | ## Register Rules 28 | 29 | Standard rules are from Rails's ActiveSupport (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflections.rb) 30 | 31 | If you want to register more rules, follow: 32 | 33 | ``` 34 | inflection.AddUncountable("fish") 35 | inflection.AddIrregular("person", "people") 36 | inflection.AddPlural("(bu)s$", "${1}ses") # "bus" => "buses" / "BUS" => "BUSES" / "Bus" => "Buses" 37 | inflection.AddSingular("(bus)(es)?$", "${1}") # "buses" => "bus" / "Buses" => "Bus" / "BUSES" => "BUS" 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/binding/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/binding/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/golang@1.1.1 -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/admin/index.tmpl: -------------------------------------------------------------------------------- 1 |

Admin {{.}}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/another_layout.tmpl: -------------------------------------------------------------------------------- 1 | another head 2 | {{ yield }} 3 | another foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/content.tmpl: -------------------------------------------------------------------------------- 1 |

{{ . }}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/current_layout.tmpl: -------------------------------------------------------------------------------- 1 | {{ current }} head 2 | {{ yield }} 3 | {{ current }} foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/delims.tmpl: -------------------------------------------------------------------------------- 1 |

Hello {[{.}]}

-------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/hello.tmpl: -------------------------------------------------------------------------------- 1 |

Hello {{.}}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/hypertext.html: -------------------------------------------------------------------------------- 1 | Hypertext! 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/basic/layout.tmpl: -------------------------------------------------------------------------------- 1 | head 2 | {{ yield }} 3 | foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/fixtures/custom_funcs/index.tmpl: -------------------------------------------------------------------------------- 1 | {{ myCustomFunc }} 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/martini-contrib/render/wercker.yml: -------------------------------------------------------------------------------- 1 | box: wercker/golang@1.1.1 -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oxtoacart/bpool/bpool.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bpool implements leaky pools of byte arrays and Buffers as bounded 3 | channels. It is based on the leaky buffer example from the Effective Go 4 | documentation: http://golang.org/doc/effective_go.html#leaky_buffer 5 | */ 6 | package bpool 7 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oxtoacart/bpool/bufferpool.go: -------------------------------------------------------------------------------- 1 | package bpool 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | // BufferPool implements a pool of bytes.Buffers in the form of a bounded 8 | // channel. 9 | type BufferPool struct { 10 | c chan *bytes.Buffer 11 | } 12 | 13 | // NewBufferPool creates a new BufferPool bounded to the given size. 14 | func NewBufferPool(size int) (bp *BufferPool) { 15 | return &BufferPool{ 16 | c: make(chan *bytes.Buffer, size), 17 | } 18 | } 19 | 20 | // Get gets a Buffer from the BufferPool, or creates a new one if none are 21 | // available in the pool. 22 | func (bp *BufferPool) Get() (b *bytes.Buffer) { 23 | select { 24 | case b = <-bp.c: 25 | // reuse existing buffer 26 | default: 27 | // create new buffer 28 | b = bytes.NewBuffer([]byte{}) 29 | } 30 | return 31 | } 32 | 33 | // Put returns the given Buffer to the BufferPool. 34 | func (bp *BufferPool) Put(b *bytes.Buffer) { 35 | b.Reset() 36 | select { 37 | case bp.c <- b: 38 | default: // Discard the buffer if the pool is full. 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oxtoacart/bpool/bytepool.go: -------------------------------------------------------------------------------- 1 | package bpool 2 | 3 | // BytePool implements a leaky pool of []byte in the form of a bounded 4 | // channel. 5 | type BytePool struct { 6 | c chan []byte 7 | w int 8 | } 9 | 10 | // NewBytePool creates a new BytePool bounded to the given maxSize, with new 11 | // byte arrays sized based on width. 12 | func NewBytePool(maxSize int, width int) (bp *BytePool) { 13 | return &BytePool{ 14 | c: make(chan []byte, maxSize), 15 | w: width, 16 | } 17 | } 18 | 19 | // Get gets a []byte from the BytePool, or creates a new one if none are 20 | // available in the pool. 21 | func (bp *BytePool) Get() (b []byte) { 22 | select { 23 | case b = <-bp.c: 24 | // reuse existing buffer 25 | default: 26 | // create new buffer 27 | b = make([]byte, bp.w) 28 | } 29 | return 30 | } 31 | 32 | // Put returns the given Buffer to the BytePool. 33 | func (bp *BytePool) Put(b []byte) { 34 | select { 35 | case bp.c <- b: 36 | // buffer went back into pool 37 | default: 38 | // buffer didn't go back into pool, just discard 39 | } 40 | } 41 | 42 | // Width returns the width of the byte arrays in this pool. 43 | func (bp *BytePool) Width() (n int) { 44 | return bp.w 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Paul Borman 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009,2014 Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // The uuid package generates and inspects UUIDs. 6 | // 7 | // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. 8 | package uuid 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import "errors" 8 | 9 | func (u UUID) MarshalJSON() ([]byte, error) { 10 | if len(u) == 0 { 11 | return []byte(`""`), nil 12 | } 13 | return []byte(`"` + u.String() + `"`), nil 14 | } 15 | 16 | func (u *UUID) UnmarshalJSON(data []byte) error { 17 | if len(data) == 0 || string(data) == `""` { 18 | return nil 19 | } 20 | if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' { 21 | return errors.New("invalid UUID format") 22 | } 23 | data = data[1 : len(data)-1] 24 | uu := Parse(string(data)) 25 | if uu == nil { 26 | return errors.New("invalid UUID format") 27 | } 28 | *u = uu 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/sql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | ) 11 | 12 | // Scan implements sql.Scanner so UUIDs can be read from databases transparently 13 | // Currently, database types that map to string and []byte are supported. Please 14 | // consult database-specific driver documentation for matching types. 15 | func (uuid *UUID) Scan(src interface{}) error { 16 | switch src.(type) { 17 | case string: 18 | // see uuid.Parse for required string format 19 | parsed := Parse(src.(string)) 20 | 21 | if parsed == nil { 22 | return errors.New("Scan: invalid UUID format") 23 | } 24 | 25 | *uuid = parsed 26 | case []byte: 27 | // assumes a simple slice of bytes, just check validity and store 28 | u := UUID(src.([]byte)) 29 | 30 | if u.Variant() == Invalid { 31 | return errors.New("Scan: invalid UUID format") 32 | } 33 | 34 | *uuid = u 35 | default: 36 | return fmt.Errorf("Scan: unable to scan type %T into UUID", src) 37 | } 38 | 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/version1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | ) 10 | 11 | // NewUUID returns a Version 1 UUID based on the current NodeID and clock 12 | // sequence, and the current time. If the NodeID has not been set by SetNodeID 13 | // or SetNodeInterface then it will be set automatically. If the NodeID cannot 14 | // be set NewUUID returns nil. If clock sequence has not been set by 15 | // SetClockSequence then it will be set automatically. If GetTime fails to 16 | // return the current NewUUID returns nil. 17 | func NewUUID() UUID { 18 | if nodeID == nil { 19 | SetNodeInterface("") 20 | } 21 | 22 | now, seq, err := GetTime() 23 | if err != nil { 24 | return nil 25 | } 26 | 27 | uuid := make([]byte, 16) 28 | 29 | time_low := uint32(now & 0xffffffff) 30 | time_mid := uint16((now >> 32) & 0xffff) 31 | time_hi := uint16((now >> 48) & 0x0fff) 32 | time_hi |= 0x1000 // Version 1 33 | 34 | binary.BigEndian.PutUint32(uuid[0:], time_low) 35 | binary.BigEndian.PutUint16(uuid[4:], time_mid) 36 | binary.BigEndian.PutUint16(uuid[6:], time_hi) 37 | binary.BigEndian.PutUint16(uuid[8:], seq) 38 | copy(uuid[10:], nodeID) 39 | 40 | return uuid 41 | } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/pborman/uuid/version4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | // Random returns a Random (Version 4) UUID or panics. 8 | // 9 | // The strength of the UUIDs is based on the strength of the crypto/rand 10 | // package. 11 | // 12 | // A note about uniqueness derived from from the UUID Wikipedia entry: 13 | // 14 | // Randomly generated UUIDs have 122 random bits. One's annual risk of being 15 | // hit by a meteorite is estimated to be one chance in 17 billion, that 16 | // means the probability is about 0.00000000006 (6 × 10−11), 17 | // equivalent to the odds of creating a few tens of trillions of UUIDs in a 18 | // year and having one duplicate. 19 | func NewRandom() UUID { 20 | uuid := make([]byte, 16) 21 | randomBits([]byte(uuid)) 22 | uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 23 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 24 | return uuid 25 | } 26 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/robfig/cron/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/robfig/cron/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/robfig/cron/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Rob Figueiredo 2 | All Rights Reserved. 3 | 4 | MIT LICENSE 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/robfig/cron/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](http://godoc.org/github.com/robfig/cron?status.png)](http://godoc.org/github.com/robfig/cron) 2 | [![Build Status](https://travis-ci.org/robfig/cron.svg?branch=master)](https://travis-ci.org/robfig/cron) 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/robfig/cron/constantdelay.go: -------------------------------------------------------------------------------- 1 | package cron 2 | 3 | import "time" 4 | 5 | // ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes". 6 | // It does not support jobs more frequent than once a second. 7 | type ConstantDelaySchedule struct { 8 | Delay time.Duration 9 | } 10 | 11 | // Every returns a crontab Schedule that activates once every duration. 12 | // Delays of less than a second are not supported (will round up to 1 second). 13 | // Any fields less than a Second are truncated. 14 | func Every(duration time.Duration) ConstantDelaySchedule { 15 | if duration < time.Second { 16 | duration = time.Second 17 | } 18 | return ConstantDelaySchedule{ 19 | Delay: duration - time.Duration(duration.Nanoseconds())%time.Second, 20 | } 21 | } 22 | 23 | // Next returns the next time this should be run. 24 | // This rounds so that the next activation time will be on the second. 25 | func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time { 26 | return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond) 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/.gitignore: -------------------------------------------------------------------------------- 1 | spec/spec 2 | examples/simple-consumer/simple-consumer 3 | examples/simple-producer/simple-producer 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.4 6 | - 1.5 7 | 8 | services: 9 | - rabbitmq 10 | 11 | env: 12 | - AMQP_URL=amqp://guest:guest@127.0.0.1:5672/ GOMAXPROCS=2 13 | 14 | script: go test -v -tags integration ./... 15 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/auth.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // Source code and contact info at http://github.com/streadway/amqp 5 | 6 | package amqp 7 | 8 | import ( 9 | "fmt" 10 | ) 11 | 12 | // Authentication interface provides a means for different SASL authentication 13 | // mechanisms to be used during connection tuning. 14 | type Authentication interface { 15 | Mechanism() string 16 | Response() string 17 | } 18 | 19 | // PlainAuth is a similar to Basic Auth in HTTP. 20 | type PlainAuth struct { 21 | Username string 22 | Password string 23 | } 24 | 25 | func (me *PlainAuth) Mechanism() string { 26 | return "PLAIN" 27 | } 28 | 29 | func (me *PlainAuth) Response() string { 30 | return fmt.Sprintf("\000%s\000%s", me.Username, me.Password) 31 | } 32 | 33 | // Finds the first mechanism preferred by the client that the server supports. 34 | func pickSASLMechanism(client []Authentication, serverMechanisms []string) (auth Authentication, ok bool) { 35 | for _, auth = range client { 36 | for _, mech := range serverMechanisms { 37 | if auth.Mechanism() == mech { 38 | return auth, true 39 | } 40 | } 41 | } 42 | 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | package amqp 3 | 4 | import "bytes" 5 | 6 | func Fuzz(data []byte) int { 7 | r := reader{bytes.NewReader(data)} 8 | frame, err := r.ReadFrame() 9 | if err != nil { 10 | if frame != nil { 11 | panic("frame is not nil") 12 | } 13 | return 0 14 | } 15 | return 1 16 | } 17 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/streadway/amqp/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | go run spec/gen.go < spec/amqp0-9-1.stripped.extended.xml | gofmt > spec091.go 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/README.md: -------------------------------------------------------------------------------- 1 | # codecgen tool 2 | 3 | Generate is given a list of *.go files to parse, and an output file (fout), 4 | codecgen will create an output file __file.go__ which 5 | contains `codec.Selfer` implementations for the named types found 6 | in the files parsed. 7 | 8 | Using codecgen is very straightforward. 9 | 10 | **Download and install the tool** 11 | 12 | `go get -u github.com/ugorji/go/codec/codecgen` 13 | 14 | **Run the tool on your files** 15 | 16 | The command line format is: 17 | 18 | `codecgen [options] (-o outfile) (infile ...)` 19 | 20 | ```sh 21 | % codecgen -? 22 | Usage of codecgen: 23 | -c="github.com/ugorji/go/codec": codec path 24 | -o="": out file 25 | -r=".*": regex for type name to match 26 | -rt="": tags for go run 27 | -t="": build tag to put in file 28 | -u=false: Use unsafe, e.g. to avoid unnecessary allocation on []byte->string 29 | -x=false: keep temp file 30 | 31 | % codecgen -o values_codecgen.go values.go values2.go moretypedefs.go 32 | ``` 33 | 34 | Please see the [blog article](http://ugorji.net/blog/go-codecgen) 35 | for more information on how to use the tool. 36 | 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/z.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const genCodecPath = "github.com/ugorji/go/codec" 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/fast-path.not.go: -------------------------------------------------------------------------------- 1 | // +build notfastpath 2 | 3 | package codec 4 | 5 | import "reflect" 6 | 7 | // The generated fast-path code is very large, and adds a few seconds to the build time. 8 | // This causes test execution, execution of small tools which use codec, etc 9 | // to take a long time. 10 | // 11 | // To mitigate, we now support the notfastpath tag. 12 | // This tag disables fastpath during build, allowing for faster build, test execution, 13 | // short-program runs, etc. 14 | 15 | func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false } 16 | func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false } 17 | func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false } 18 | func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false } 19 | 20 | type fastpathT struct{} 21 | type fastpathE struct { 22 | rtid uintptr 23 | rt reflect.Type 24 | encfn func(*encFnInfo, reflect.Value) 25 | decfn func(*decFnInfo, reflect.Value) 26 | } 27 | type fastpathA [0]fastpathE 28 | 29 | func (x fastpathA) index(rtid uintptr) int { return -1 } 30 | 31 | var fastpathAV fastpathA 32 | var fastpathTV fastpathT 33 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/helper_not_unsafe.go: -------------------------------------------------------------------------------- 1 | //+build !unsafe 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a MIT license found in the LICENSE file. 5 | 6 | package codec 7 | 8 | // stringView returns a view of the []byte as a string. 9 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 10 | // In regular safe mode, it is an allocation and copy. 11 | func stringView(v []byte) string { 12 | return string(v) 13 | } 14 | 15 | // bytesView returns a view of the string as a []byte. 16 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 17 | // In regular safe mode, it is an allocation and copy. 18 | func bytesView(v string) []byte { 19 | return []byte(v) 20 | } 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/helper_unsafe.go: -------------------------------------------------------------------------------- 1 | //+build unsafe 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a MIT license found in the LICENSE file. 5 | 6 | package codec 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // This file has unsafe variants of some helper methods. 13 | 14 | type unsafeString struct { 15 | Data uintptr 16 | Len int 17 | } 18 | 19 | type unsafeBytes struct { 20 | Data uintptr 21 | Len int 22 | Cap int 23 | } 24 | 25 | // stringView returns a view of the []byte as a string. 26 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 27 | // In regular safe mode, it is an allocation and copy. 28 | func stringView(v []byte) string { 29 | if len(v) == 0 { 30 | return "" 31 | } 32 | x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)} 33 | return *(*string)(unsafe.Pointer(&x)) 34 | } 35 | 36 | // bytesView returns a view of the string as a []byte. 37 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 38 | // In regular safe mode, it is an allocation and copy. 39 | func bytesView(v string) []byte { 40 | if len(v) == 0 { 41 | return zeroByteSlice 42 | } 43 | x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)} 44 | return *(*[]byte)(unsafe.Pointer(&x)) 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/prebuild.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | //go:generate bash prebuild.sh 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.5 6 | 7 | package ctxhttp 8 | 9 | import "net/http" 10 | 11 | func canceler(client *http.Client, req *http.Request) func() { 12 | ch := make(chan struct{}) 13 | req.Cancel = ch 14 | 15 | return func() { 16 | close(ch) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.5 6 | 7 | package ctxhttp 8 | 9 | import "net/http" 10 | 11 | type requestCanceler interface { 12 | CancelRequest(*http.Request) 13 | } 14 | 15 | func canceler(client *http.Client, req *http.Request) func() { 16 | rc, ok := client.Transport.(requestCanceler) 17 | if !ok { 18 | return func() {} 19 | } 20 | return func() { 21 | rc.CancelRequest(req) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/.bzrignore: -------------------------------------------------------------------------------- 1 | _* 2 | [856].out 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/LICENSE: -------------------------------------------------------------------------------- 1 | mgo - MongoDB driver for Go 2 | 3 | Copyright (c) 2010-2013 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/Makefile: -------------------------------------------------------------------------------- 1 | startdb: 2 | @testdb/setup.sh start 3 | 4 | stopdb: 5 | @testdb/setup.sh stop 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/bson/LICENSE: -------------------------------------------------------------------------------- 1 | BSON library for Go 2 | 3 | Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/doc.go: -------------------------------------------------------------------------------- 1 | // Package mgo offers a rich MongoDB driver for Go. 2 | // 3 | // Details about the mgo project (pronounced as "mango") are found 4 | // in its web page: 5 | // 6 | // http://labix.org/mgo 7 | // 8 | // Usage of the driver revolves around the concept of sessions. To 9 | // get started, obtain a session using the Dial function: 10 | // 11 | // session, err := mgo.Dial(url) 12 | // 13 | // This will establish one or more connections with the cluster of 14 | // servers defined by the url parameter. From then on, the cluster 15 | // may be queried with multiple consistency rules (see SetMode) and 16 | // documents retrieved with statements such as: 17 | // 18 | // c := session.DB(database).C(collection) 19 | // err := c.Find(query).One(&result) 20 | // 21 | // New sessions are typically created by calling session.Copy on the 22 | // initial session obtained at dial time. These new sessions will share 23 | // the same cluster information and connection cache, and may be easily 24 | // handed into other methods and functions for organizing logic. 25 | // Every session created must have its Close method called at the end 26 | // of its life time, so its resources may be put back in the pool or 27 | // collected, depending on the case. 28 | // 29 | // For more details, see the documentation for the types and methods. 30 | // 31 | package mgo 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/saslimpl.go: -------------------------------------------------------------------------------- 1 | //+build sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "labix.org/v2/mgo/sasl" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return sasl.New(cred.Username, cred.Password, cred.Mechanism, cred.Service, host) 11 | } 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/saslstub.go: -------------------------------------------------------------------------------- 1 | //+build !sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return nil, fmt.Errorf("SASL support not enabled during build (-tags sasl)") 11 | } 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/testdb/dropall.js: -------------------------------------------------------------------------------- 1 | 2 | var ports = [40001, 40002, 40011, 40012, 40013, 40021, 40022, 40023, 40041, 40101, 40102, 40103, 40201, 40202, 40203] 3 | var auth = [40002, 40103, 40203, 40031] 4 | 5 | for (var i in ports) { 6 | var port = ports[i] 7 | var server = "localhost:" + port 8 | var mongo = new Mongo("localhost:" + port) 9 | var admin = mongo.getDB("admin") 10 | 11 | for (var j in auth) { 12 | if (auth[j] == port) { 13 | admin.auth("root", "rapadura") 14 | break 15 | } 16 | } 17 | var result = admin.runCommand({"listDatabases": 1}) 18 | // Why is the command returning undefined!? 19 | while (typeof result.databases == "undefined") { 20 | print("dropall.js: listing databases of :" + port + " got:", result) 21 | result = admin.runCommand({"listDatabases": 1}) 22 | } 23 | var dbs = result.databases 24 | for (var j = 0; j != dbs.length; j++) { 25 | var db = dbs[j] 26 | switch (db.name) { 27 | case "admin": 28 | case "local": 29 | case "config": 30 | break 31 | default: 32 | mongo.getDB(db.name).dropDatabase() 33 | } 34 | } 35 | } 36 | 37 | // vim:ts=4:sw=4:et 38 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/testdb/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | start() { 4 | mkdir _testdb 5 | cd _testdb 6 | mkdir db1 db2 rs1a rs1b rs1c rs2a rs2b rs2c rs3a rs3b rs3c rs4a cfg1 cfg2 cfg3 7 | ln -s ../testdb/supervisord.conf supervisord.conf 8 | echo keyfile > keyfile 9 | chmod 600 keyfile 10 | echo "Running supervisord..." 11 | supervisord || ( echo "Supervisord failed executing ($?)" && exit 1 ) 12 | COUNT=$(grep '^\[program' supervisord.conf | wc -l) 13 | echo "Supervisord is up, starting $COUNT processes..." 14 | for i in $(seq 10); do 15 | RUNNING=$(supervisorctl status | grep RUNNING | wc -l) 16 | echo "$RUNNING processes running..." 17 | if [ x$COUNT = x$RUNNING ]; then 18 | echo "Running setup.js with mongo..." 19 | mongo --nodb ../testdb/init.js 20 | exit 0 21 | fi 22 | sleep 1 23 | done 24 | echo "Failed to start all processes. Check out what's up at $PWD now!" 25 | exit 1 26 | } 27 | 28 | stop() { 29 | if [ -d _testdb ]; then 30 | echo "Shutting down test cluster..." 31 | (cd _testdb && supervisorctl shutdown) 32 | rm -rf _testdb 33 | fi 34 | } 35 | 36 | 37 | if [ ! -f suite_test.go ]; then 38 | echo "This script must be run from within the source directory." 39 | exit 1 40 | fi 41 | 42 | case "$1" in 43 | 44 | start) 45 | start 46 | ;; 47 | 48 | stop) 49 | stop 50 | ;; 51 | 52 | esac 53 | 54 | # vim:ts=4:sw=4:et 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/labix.org/v2/mgo/txn/chaos.go: -------------------------------------------------------------------------------- 1 | package txn 2 | 3 | import ( 4 | mrand "math/rand" 5 | "time" 6 | ) 7 | 8 | var chaosEnabled = false 9 | var chaosSetting Chaos 10 | 11 | // Chaos holds parameters for the failure injection mechanism. 12 | type Chaos struct { 13 | // KillChance is the 0.0 to 1.0 chance that a given checkpoint 14 | // within the algorithm will raise an interruption that will 15 | // stop the procedure. 16 | KillChance float64 17 | 18 | // SlowdownChance is the 0.0 to 1.0 chance that a given checkpoint 19 | // within the algorithm will be delayed by Slowdown before 20 | // continuing. 21 | SlowdownChance float64 22 | Slowdown time.Duration 23 | 24 | // If Breakpoint is set, the above settings will only affect the 25 | // named breakpoint. 26 | Breakpoint string 27 | } 28 | 29 | // SetChaos sets the failure injection parameters to c. 30 | func SetChaos(c Chaos) { 31 | chaosSetting = c 32 | chaosEnabled = c.KillChance > 0 || c.SlowdownChance > 0 33 | } 34 | 35 | func chaos(bpname string) { 36 | if !chaosEnabled { 37 | return 38 | } 39 | switch chaosSetting.Breakpoint { 40 | case "", bpname: 41 | kc := chaosSetting.KillChance 42 | if kc > 0 && mrand.Intn(1000) < int(kc*1000) { 43 | panic(chaosError{}) 44 | } 45 | if bpname == "insert" { 46 | return 47 | } 48 | sc := chaosSetting.SlowdownChance 49 | if sc > 0 && mrand.Intn(1000) < int(kc*1000) { 50 | time.Sleep(chaosSetting.Slowdown) 51 | } 52 | } 53 | } 54 | 55 | type chaosError struct{} 56 | 57 | func (f *flusher) handleChaos(err *error) { 58 | v := recover() 59 | if v == nil { 60 | return 61 | } 62 | if _, ok := v.(chaosError); ok { 63 | f.debugf("Killed by chaos!") 64 | *err = ErrChaos 65 | return 66 | } 67 | panic(v) 68 | } 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 PandoCloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /build/local/docker/base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SERVICES='etcd mysql redis mongo' 4 | 5 | echo "stopping all services..." 6 | docker stop `echo $SERVICES` 7 | docker rm `echo $SERVICES` 8 | 9 | echo "starting etcd..." 10 | docker run -d --name etcd elcolio/etcd 11 | 12 | echo "starting mysql..." 13 | docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql 14 | 15 | echo "starting redis..." 16 | docker run -d --name redis redis 17 | 18 | echo "starting mongo..." 19 | docker run -d --name mongo mongo 20 | -------------------------------------------------------------------------------- /build/local/linux/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # restore dependency packages. 4 | cd $GOPATH/src/github.com/PandoCloud/pando-cloud 5 | cp -r Godeps/_workspace/src/* $GOPATH/src 6 | 7 | # install binaries 8 | go install -v github.com/PandoCloud/pando-cloud/services/... 9 | -------------------------------------------------------------------------------- /build/local/linux/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | killall -9 httpaccess registry apiprovider devicemanager controller mqttaccess 4 | 5 | # start services 6 | $GOPATH/bin/httpaccess -etcd http://localhost:2379 -httphost internal:443 -loglevel debug -usehttps -keyfile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/key.pem -cafile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/cert.pem & 7 | $GOPATH/bin/registry -etcd http://localhost:2379 -rpchost localhost:20034 -aeskey ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP -dbhost localhost -dbname PandoCloud -dbport 3306 -dbuser root -loglevel debug & 8 | $GOPATH/bin/apiprovider -etcd http://localhost:2379 -loglevel debug -httphost :8888 & 9 | $GOPATH/bin/devicemanager -etcd http://localhost:2379 -loglevel debug -rpchost localhost:20033 & 10 | $GOPATH/bin/controller -etcd http://localhost:2379 -loglevel debug -rpchost localhost:20032 & 11 | $GOPATH/bin/mqttaccess -etcd http://localhost:2379 -loglevel debug -rpchost localhost:20030 -tcphost internal:1883 -usetls -keyfile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/key.pem -cafile $GOPATH/src/github.com/PandoCloud/pando-cloud/pkg/server/testdata/cert.pem & 12 | 13 | exit 0 14 | -------------------------------------------------------------------------------- /docs/img/architecture.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruizeng/pando-cloud/004f9ac1c98aeca5e8d8de5f410702e9c9eaf483/docs/img/architecture.jpeg -------------------------------------------------------------------------------- /docs/zh-cn/api-doc/device.md: -------------------------------------------------------------------------------- 1 | # 设备接入API 2 | 3 | ## 概述 4 | 需要接入pando云平台的设备,都需要遵循pando物联网平台的接入流程和接入协议。设备相关api由设备代理(网关)向服务器发起,设备在第一次成功联网后第一时间向服务器注册自己的信息,设备通过设备登陆接口获取设备token。 5 | 6 | ## API列表 7 | ### 设备注册 8 | *请求方式* 9 | ``` 10 | POST 11 | ``` 12 | *请求URL* 13 | ``` 14 | /v1/devices/registration 15 | ``` 16 | *参数* 17 | ``` 18 | 无 19 | ``` 20 | *请求头* 21 | ``` 22 | 无 23 | ``` 24 | *请求内容* 25 | ``` 26 | { 27 | // 产品key,平台分配给产品 28 | "product_key": "3d6few3ac31w7a6d3f...", 29 | // 设备序列号,设备唯一硬件标识,如mac地址 30 | "device_code": "4d3e2a5d3fff", 31 | // 网关版本 32 | "产品版本": "0.1.0" 33 | } 34 | ``` 35 | *返回内容* 36 | ``` 37 | { 38 | // 返回码 39 | "code": 0, 40 | // 正确或错误信息 41 | "message": "", 42 | // 如果成功,将返回设备id及设备密码 43 | "data": { 44 | // 设备id 45 | "device_id": 12324, 46 | // 设备密码 47 | "device_secret": "3d6few3ac31w7a6d3f", 48 | // 设备激活码,用来绑定设备 49 | "device_key": "34ffffffff", 50 | // 设备标识符 51 | "device_identifier": "64-64-fe4efe" 52 | } 53 | } 54 | ``` 55 | 56 | ### 设备登录 57 | *请求方式* 58 | ``` 59 | POST 60 | ``` 61 | *请求URL* 62 | ``` 63 | /v1/devices/authentication 64 | ``` 65 | *参数* 66 | ``` 67 | 无 68 | ``` 69 | *请求头* 70 | ``` 71 | 无 72 | ``` 73 | *请求内容* 74 | ``` 75 | { 76 | // 设备id 77 | "device_id": 123, 78 | // 设备密码 79 | "device_secret": "fsfwefewf23r2r32r23rfs", 80 | // 协议类型,不填写表示默认协议(mqtt) 81 | "protocol": "mqtt" 82 | } 83 | ``` 84 | *返回内容* 85 | ``` 86 | { 87 | //返回码 88 | "code": 0, 89 | //正确或错误信息 90 | "message": "", 91 | "data": { 92 | // 设备token,16个字节,经过hex编码 93 | "access_token": "3sffefefefefsf...", 94 | // 接入服务器地址+端口 95 | "access_addr": "ip:port" 96 | } 97 | } 98 | ``` -------------------------------------------------------------------------------- /docs/zh-cn/config/product-json-config.md: -------------------------------------------------------------------------------- 1 | # 产品配置 2 | 平台采用JSON格式的字符串来描述产品支持的功能。提供JSON配置文件时请严格按照JSON的格式规范和本文档的格式规范,否则可能造成产品无法使用。 3 | 4 | ## 概要说明 5 | ### status 6 | 我们用`status`作为信息的描述参数。一个产品的功能,由`object`、`command`、`event`三组信息描述。 7 | 8 | ### object 9 | 对象。产品由若干个可复用的功能组件组成,这些组件称之为对象。一个对象描述了其包含的**状态**(`status`)的描述参数,如支持的数据类型和标签。 10 | 11 | ### command 12 | 命令。外界对产品本地信息处理提出的要求。可能含有一个或多个参数,并有优先级。 13 | 14 | ### event 15 | 事件。产品需要通知外界关注的、处理后的、有效信息。可能含有一个或多个参数,并有优先级。 16 | 17 | ## JSON格式说明 18 | 下面是一个完整的产品配置,注释中对相应字段的意义进行了说明。(**注意**:标准的json格式规范是不允许有注释的,如果你参考这份配置编辑配置文件,请删除所有`//`及其后的注释!) 19 | 20 | ```javascript 21 | { 22 | // objects是一个数组,包含至少一个object对象 23 | "objects": [{ 24 | "no": 1, // 对象编号,需保证产品内唯一,设备端固件实现需对应 25 | "label": "atmosphere", // 对象标签,根据自己喜好给产品中的该对象取得别名 26 | "part": 1, // 部件编号,对象所述的子设备 27 | // status是一个数组,包含了该对象支持的信息的数据类型 28 | "status": [{ 29 | "value_type": 8, // 值类型 30 | "name": "red" // 给该属性命的别名,方便区分,此例为三色灯的红色值,以下类似 31 | }, { 32 | "value_type": 8, 33 | "name": "humidity" 34 | }, { 35 | "value_type": 8, 36 | "name": "air-quality" 37 | }] 38 | }], 39 | // commands是一个数组,包含产品支持的命令列表,数组可以为空([]) 40 | "commands": [{ 41 | "no": 1, // 命令编号,产品内唯一,设备端固件实现需对应 42 | "name": "upgrade", // 命令名称 43 | "part": 1, // 部件编号 44 | "priority": 0, // 优先级,0-99,值越高,优先级越高 45 | // params是一个参数列表,描述参数的值类型和名称 46 | "params": [{ 47 | "value_type": 12, 48 | "name": "url" 49 | }, { 50 | "value_type": 11, 51 | "name": "md5" 52 | }] 53 | }], 54 | // events是一个数组,包含产品支持的事件列表,可为空([]) 55 | "events": [{ 56 | "no": 1, // 事件编号,产品内唯一,设备端固件实现需对应 57 | "name": "alert", // 事件名称 58 | "part": 1, // 部件编号,所述的子设备 59 | "priority": 0, // 优先级,0-99,值越高,优先级越高 60 | "params": [] 61 | }] 62 | } 63 | ``` -------------------------------------------------------------------------------- /docs/zh-cn/contribution/work-flow.md: -------------------------------------------------------------------------------- 1 | # 贡献流程 2 | 3 | 欢迎参与Pando物联网平台的代码贡献!我们的代码全部托管在github并通过github进行协作开发。 4 | 5 | ## 流程 6 | 1. 从官方项目github地址Fork项目,并进行修改 7 | * 请Fork master分支而不是其他分支,因为其他分支经常变动 8 | * 请为分支起一个好理解的名字来描述你做的修改,分支名采用横线分割,如some-buf-fix 9 | * 你的分支应该只做某一个功能,如果需要实现多个功能,请拉取不同分支并分别提交 10 | * 确保代码符合我们的[Go语言编码规范](coding-standard.md) 11 | 2. 请尽量全面地测试你的代码,硬性要求如下: 12 | * 必须通过travis-ci的测试(目前为编译和单元测试) 13 | * 如果新功能或者代码,请添加完备的单元测试 14 | * 必须保证测试覆盖率不会明显下降(我们通过coverall进行测试覆盖率扫描) 15 | 3. 合并你的提交 16 | * 请通过rebase将多个提交合并为一个 17 | 4. 通过GitHub发起一个pull request 18 | * 请详细地描述此分支的修改 19 | * 项目keeper会对你的修改进行审核,并提出意见 20 | * 如果审核不通过,请重新按照要求修改后重新提交 21 | 5. 项目keeper将分支合入主干 -------------------------------------------------------------------------------- /docs/zh-cn/environment/golang.md: -------------------------------------------------------------------------------- 1 | # GoLang 2 | 本文档介绍如何安装Go语言环境。 3 | 4 | ## Ubuntu 5 | 6 | ### 1.下载Go二进制包: 7 | 8 | * [64位](http://www.golangtc.com/static/go/go1.5.1/go1.5.1.linux-amd64.tar.gz) 9 | * [32位](http://www.golangtc.com/static/go/go1.5.1/go1.5.1.linux-386.tar.gz) 10 | 11 | 在Ubuntu下,可以通过wget命令进行下载,如(64位): 12 | 13 | ```sh 14 | wget http://www.golangtc.com/static/go/go1.5.1/go1.5.1.linux-amd64.tar.gz 15 | ``` 16 | 17 | > 注意,不要使用apt-get命令安装Go环境,否则安装的Go版本过低。 18 | 19 | ### 2. 解压 20 | 21 | 将下载的二进制包解压到任何喜欢的目录下,如`/usr/local`: 22 | 23 | ```sh 24 | sudo tar -C /usr/local -xzf go1.5.1.linux-amd64.tar.gz 25 | ``` 26 | 27 | ### 3. 创建Go工程目录 28 | 29 | 创建一个目录作为Go工作目录,如: 30 | 31 | ```sh 32 | mkdir ~/golang 33 | ``` 34 | 35 | ### 4. 配置环境变量 36 | 37 | 打开home下的bashrc,增加Go环境变量: 38 | 39 | ```sh 40 | vi ~/.bashrc 41 | ``` 42 | 43 | 在最末尾添加: 44 | 45 | ```sh 46 | export GOROOT=/usr/local/go 47 | export GOPATH=~/golang 48 | export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin 49 | ``` 50 | 51 | ### 5. 加载环境变量 52 | 53 | ```sh 54 | source ~/.bashrc 55 | ``` 56 | 57 | ### 6. 验证 58 | 59 | ```sh 60 | go version 61 | ``` 62 | 如果能正常显示go版本号,则证明安装成功。 -------------------------------------------------------------------------------- /docs/zh-cn/quick-start/README.md: -------------------------------------------------------------------------------- 1 | # 快速开始 2 | 这里将介绍如何编译pando cloud,以及如何在自己的服务器或pc机上单机部署pando物联网云。 3 | 4 | * [Ubuntu](ubuntu.md):介绍如何在安装Ubuntu Linux操作系统的服务器或PC机上编译及部署服务。 5 | * [Docker](docker.md):介绍如何通过制作好的docker镜像部署服务。 -------------------------------------------------------------------------------- /docs/zh-cn/services/README.md: -------------------------------------------------------------------------------- 1 | # 服务部署指南 2 | 3 | Pando物联网云平台采用微服务架构。除了系统依赖的MySQL,MongoDB等开源服务,平台自身目前有以下几个服务组成: 4 | 5 | - **[registry](registry.md)**:维护平台全局配置和信息的服务。 6 | - **[devicemanager](devicemanager.md)**: 设备信息和设备状态维护。 7 | - **[controller](controller.md)**: 和设备进行信息交互的路由服务。 8 | - **[apiprovider](apiprovider.md)**: 为应用提供REST接口。 9 | - **[httpaccess](httpaccess.md)**: 设备API服务,提供设备登陆、注册等逻辑。 10 | - **[mqttaccess](mqttaccess.md)**:MQTT接入服务。 -------------------------------------------------------------------------------- /docs/zh-cn/services/apiprovider.md: -------------------------------------------------------------------------------- 1 | # apiprovider 2 | 3 | `apiprovider`服务为应用提供HTTP REST接口。 4 | 5 | ## 工作原理 6 | [应用接口文档](../api-doc/application.md) 7 | 8 | ## 启动参数 9 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 10 | * `-rpchost` rpc服务访问地址,必需参数。该参数定义该服务对其他服务提供的rpc服务的监听地址。如`http://localhost:20034`。 11 | * `-httphost` HTTP服务地址,必须参数。格式为`ip:port`如`localhost:443`,为了安全考虑,建议最好只绑定内网ip和端口。如果需要外网访问,强烈建议开启https选项。 12 | * `-usehttps` 是否启动https服务,默认不启用。如果启用,则必须提供以下`cafile`和`keyfile`两个参数。 13 | * `-cafile` ssl加密证书的证书文件路径(pem格式)。 14 | * `-keyfile` ssl加密证书的密钥文件路径(pem格式)。 15 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 16 | 17 | > 说明:ssl证书和密钥的pem文件生成方法可以参考[这里](http://killeraction.iteye.com/blog/858325) 18 | -------------------------------------------------------------------------------- /docs/zh-cn/services/controller.md: -------------------------------------------------------------------------------- 1 | # controller 2 | 3 | `controller`服务作为和设备进行信息交互时的控制节点,为访问设备提供路由服务,并接收设备上报的信息。 4 | 5 | ## 工作原理 6 | `controller`主要负责设备信息交互,具体分两种场景: 7 | 8 | * 当应用需要向设备发送信息时,`controller`会向`devicemanager` 查询当前设备的在线信息,并根据反馈的接入点,向接入服务器发送信息转发请求。 9 | * 当设备向平台发送数据时,`controller`会将数据存入MongoDB,如需通知应用则放入消息队列。 10 | 11 | ## 启动参数 12 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 13 | * `-rpchost` rpc服务访问地址,必需参数。该参数定义该服务对其他服务提供的rpc服务的监听地址。如`http://localhost:20034`。 14 | * `-mongohost` MongoDB地址,可选参数。如果没有提供则为`localhost`,如果需要指定,格式为`ip:port`如`192.168.0.3:27017`。 15 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 -------------------------------------------------------------------------------- /docs/zh-cn/services/devicemanager.md: -------------------------------------------------------------------------------- 1 | # devicemanager 2 | 3 | `devicemanager`维护了设备的状态,如设备当前在哪台接入服务器接入,设备是否在线等。 4 | 5 | ## 工作原理 6 | `devicemanager`是无状态的,采用redis存储了设备的实时状态信息,并对外提供了rpc接口供其他服务查询设备的当前信息。 7 | 8 | ## 启动参数 9 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 10 | * `-rpchost` rpc服务访问地址,必需参数。该参数定义该服务对其他服务提供的rpc服务的监听地址。如`http://localhost:20034`。 11 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 -------------------------------------------------------------------------------- /docs/zh-cn/services/httpaccess.md: -------------------------------------------------------------------------------- 1 | # httpaccess 2 | 3 | `httpaccess`服务提供了供设备注册、登录的HTTP[接口](../api-doc/device.md)。 4 | 5 | ## 启动参数 6 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 7 | * `-httphost` HTTP服务地址,必须参数。格式为`ip:port`如`localhost:443`,强烈建议开启https选项。一般情况下绑定到外网的443端口(https默认端口)。 8 | * `-usehttps` 是否启动https服务,默认不启用。如果启用,则必须提供以下`cafile`和`keyfile`两个参数。如果需要pando设备连接,则必须启用,否则无法连接。 9 | * `-cafile` ssl加密证书的证书文件路径(pem格式)。 10 | * `-keyfile` ssl加密证书的密钥文件路径(pem格式)。 11 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 12 | 13 | > 说明:ssl证书和密钥的pem文件生成方法可以参考[这里](http://killeraction.iteye.com/blog/858325) -------------------------------------------------------------------------------- /docs/zh-cn/services/mqttaccess.md: -------------------------------------------------------------------------------- 1 | # mqttaccess 2 | 3 | mqttaccess是支持mqtt协议的接入服务器,平台目前默认采用该协议。提供了tcp长连接连接设备,并对设备交互数据进行转发服务。 4 | 5 | ## 启动参数 6 | 7 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 8 | * `-rpchost` rpc服务访问地址,必需参数。该参数定义该服务对其他服务提供的rpc服务的监听地址。如`http://localhost:20034`。 9 | * `-tcphost` tcp服务地址,必须参数。格式为`ip:port`如`localhost:1883`,一般绑定为外网ip加1883端口(mqtt默认端口)。 10 | * `-usetls` 是否启动ssl加密服务,默认不启用。如果启用,则必须提供以下`cafile`和`keyfile`两个参数。如果pando设备需接入,必须开启tls加密选项,否则无法接入。 11 | * `-cafile` ssl加密证书的证书文件路径(pem格式)。 12 | * `-keyfile` ssl加密证书的密钥文件路径(pem格式)。 13 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 14 | 15 | > 说明:ssl证书和密钥的pem文件生成方法可以参考[这里](http://killeraction.iteye.com/blog/858325) -------------------------------------------------------------------------------- /docs/zh-cn/services/registry.md: -------------------------------------------------------------------------------- 1 | # registry 2 | 3 | `registry`服务负责维护平台的全局配置。 4 | 5 | ## 工作原理 6 | 该服务采用MySQL存储平台的配置和设备注册信息。 7 | 8 | `registry`服务是无状态的,在名为`PandoCloud`的库中维护了`application`, `vendor`, `product`以及`device`表,并为了加快访问速度提供了缓存机制。 9 | 10 | ## 启动参数列表 11 | * `-etcd` etcd服务的访问地址,必需参数。如`http://localhost:2379`,如果etcd是多副本部署,可以用分号隔开访问地址,如`http://192.168.0.2:2379;http://192.168.0.3:2379`。 12 | * `-rpchost` rpc服务访问地址,必需参数。该参数定义该服务对其他服务提供的rpc服务的监听地址。如`http://localhost:20034`。 13 | * `-aeskey` 用来生成KEY的aes加密密钥串,必须参数。该参数为32位的任意字符串,如`ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP`。该参数越随机越好。 14 | * `-dbhost` MySQL数据库的访问地址,选填,如果没有填写默认为`localhost`。 15 | * `-dbport` MySQL数据库的访问端口,选填,如果没有填写默认为`3306`。 16 | * `-dbuser` MySQL数据库的访问用户名,选填,如果没有填写默认为`root`。 17 | * `-dbpass` MySQL数据库的访问用户密码,选填,如果没有填写默认为空。 18 | * `-loglevel` 服务打印日志的级别,选填,如果没有指定则默认为`info`级别。 19 | -------------------------------------------------------------------------------- /make_deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf ./Godeps 4 | $GOPATH/bin/godep save ./... 5 | -------------------------------------------------------------------------------- /pkg/README.md: -------------------------------------------------------------------------------- 1 | common libs and frameworks 2 | -------------------------------------------------------------------------------- /pkg/cache/cache.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | 4 | 5 | //return status of chache 6 | type CacheStatus struct { 7 | Gets int64 8 | Hits int64 9 | MaxItemSize int 10 | CurrentSize int 11 | } 12 | 13 | //this is a interface which defines some common functions 14 | type Cache interface{ 15 | Set(key string, value interface{}) 16 | Get(key string) (interface{}, bool) 17 | Delete(key string) 18 | Status()(*CacheStatus) 19 | } -------------------------------------------------------------------------------- /pkg/generator/key_gen_test.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKeyGen(t *testing.T) { 8 | generator, err := NewKeyGenerator("INVALIDKEY") 9 | if err == nil { 10 | t.Error("should return error when key length is invalid") 11 | } 12 | testid := int64(10000) 13 | generator, err = NewKeyGenerator("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | key, err := generator.GenRandomKey(testid) 18 | if err != nil { 19 | t.Error(err) 20 | } 21 | t.Log(key) 22 | id, err := generator.DecodeIdFromRandomKey(key) 23 | if err != nil { 24 | t.Error(err) 25 | } 26 | if id != testid { 27 | t.Errorf("wrong id %d, want %d", id, testid) 28 | } 29 | 30 | id, err = generator.DecodeIdFromRandomKey("") 31 | if err == nil { 32 | t.Error("decode id from random key should return error for empty key.") 33 | } 34 | 35 | id, err = generator.DecodeIdFromRandomKey("1111111111111111111111111111111111111111") 36 | if err == nil { 37 | t.Errorf("decode id from random key should return error for bad key : %s", "1111111111111111111111111111111111111111") 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /pkg/generator/password_gen.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/base64" 6 | ) 7 | 8 | const ( 9 | ranPasswordByteLength = 24 10 | ) 11 | 12 | // gen random base64 encoded password 13 | func GenRandomPassword() (string, error) { 14 | ranbuf := make([]byte, ranPasswordByteLength) 15 | _, err := rand.Read(ranbuf) 16 | if err != nil { 17 | return "", err 18 | } 19 | 20 | return base64.StdEncoding.EncodeToString(ranbuf), nil 21 | } 22 | -------------------------------------------------------------------------------- /pkg/generator/password_gen_test.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPasswordGen(t *testing.T) { 8 | pass, err := GenRandomPassword() 9 | if err != nil { 10 | t.Error(err) 11 | } 12 | t.Log(pass) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/generator/token_gen.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "crypto/rand" 5 | ) 6 | 7 | const ( 8 | ranTokendByteLength = 16 9 | ) 10 | 11 | // gen random token bytes 12 | func GenRandomToken() ([]byte, error) { 13 | ranbuf := make([]byte, ranTokendByteLength) 14 | _, err := rand.Read(ranbuf) 15 | if err != nil { 16 | return nil, err 17 | } 18 | 19 | return ranbuf, nil 20 | } 21 | -------------------------------------------------------------------------------- /pkg/generator/token_gen_test.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTokenGen(t *testing.T) { 8 | pass, err := GenRandomToken() 9 | if err != nil { 10 | t.Error(err) 11 | } 12 | t.Log(pass) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/models/application.go: -------------------------------------------------------------------------------- 1 | // application is app who will use the cloud api 2 | package models 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | type Application struct { 9 | // inner id 10 | ID int32 11 | // App-Key for api 12 | AppKey string `sql:"type:varchar(200);not null;"` 13 | // App-Token for web hook 14 | AppToken string `sql:"type:varchar(200);not null;"` 15 | // Report Url for web hook 16 | ReportUrl string `sql:"type:varchar(200);not null;"` 17 | // name 18 | AppName string `sql:"type:varchar(200);"` 19 | // desc 20 | AppDescription string `sql:"type:text;"` 21 | // app domain which allows wildcard string like "*", "vendor/12", "product/10" 22 | AppDomain string `sql:"type:varchar(200);not null;"` 23 | 24 | CreatedAt time.Time 25 | UpdatedAt time.Time 26 | } 27 | -------------------------------------------------------------------------------- /pkg/models/device.go: -------------------------------------------------------------------------------- 1 | // device is a product instance, which is managed by our platform 2 | package models 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | type Device struct { 9 | // inner id 10 | ID int64 11 | // which product the device belongs to 12 | ProductID int32 13 | // universal device identifier, generated from vendorid-productid-deviceserial 14 | DeviceIdentifier string `sql:"type:varchar(200);not null;unique;key"` 15 | // device secret which is auto generated by the platform 16 | DeviceSecret string `sql:"type:varchar(200);not null;"` 17 | // device key is used to auth a device 18 | DeviceKey string `sql:"type:varchar(200);not null;key;"` 19 | // device name 20 | DeviceName string `sql:"type:varchar(200);not null;"` 21 | // device desc 22 | DeviceDescription string `sql:"type:text;not null;"` 23 | // device version(the agent version) 24 | DeviceVersion string `sql:"type:text;not null;"` 25 | // change history 26 | CreatedAt time.Time 27 | UpdatedAt time.Time 28 | } 29 | -------------------------------------------------------------------------------- /pkg/models/product.go: -------------------------------------------------------------------------------- 1 | // product is a abstract define of same devices made by some vendor 2 | package models 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | type Product struct { 9 | // inner id 10 | ID int32 11 | // which vendor 12 | VendorID int32 13 | // name 14 | ProductName string `sql:"type:varchar(200);not null;"` 15 | // desc 16 | ProductDescription string `sql:"type:text;not null;"` 17 | // product key to auth a product 18 | ProductKey string `sql:"type:varchar(200);not null;unique;key;"` 19 | // product config string (JSON) 20 | ProductConfig string `sql:"type:text"; not null;` 21 | // change history 22 | CreatedAt time.Time 23 | UpdatedAt time.Time 24 | 25 | Devices []Device 26 | } 27 | -------------------------------------------------------------------------------- /pkg/models/rule.go: -------------------------------------------------------------------------------- 1 | // rule is used for automated works such as timers, ifttts. 2 | package models 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | type Rule struct { 9 | // inner id 10 | ID int64 11 | // which device the rule belongs to 12 | DeviceID int64 13 | // rule type, timmer | ifttt 14 | RuleType string `sql:"type:varchar(20);not null;"` 15 | // which action triggers the rule 16 | Trigger string `sql:"type:varchar(200);not null;"` 17 | // where to send 18 | Target string `sql:"type:varchar(200);not null;"` 19 | // what action to take. 20 | Action string `sql:"type:varchar(200);not null;"` 21 | // if trigger once 22 | Once bool `sql:"default(false)"` 23 | // change history 24 | CreatedAt time.Time 25 | UpdatedAt time.Time 26 | } 27 | -------------------------------------------------------------------------------- /pkg/models/vendor.go: -------------------------------------------------------------------------------- 1 | // vendor is those who make products 2 | package models 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | type Vendor struct { 9 | // inner id 10 | ID int32 11 | // vendor name 12 | VendorName string `sql:"type:varchar(200);not null;"` 13 | // vendor key 14 | VendorKey string `sql:"type:varchar(200);not null;key;"` 15 | // vendor description 16 | VendorDescription string `sql:"type:text;not null;"` 17 | // change history 18 | CreatedAt time.Time 19 | UpdatedAt time.Time 20 | 21 | Products []Product 22 | } 23 | -------------------------------------------------------------------------------- /pkg/mongo/recorder.go: -------------------------------------------------------------------------------- 1 | package mongo 2 | 3 | import ( 4 | "labix.org/v2/mgo" 5 | "labix.org/v2/mgo/bson" 6 | ) 7 | 8 | type Recorder struct { 9 | session *mgo.Session 10 | set string 11 | collection string 12 | } 13 | 14 | func NewRecorder(host string, set string, collection string) (*Recorder, error) { 15 | sess, err := mgo.Dial(host) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | sess.DB(set).C(collection).EnsureIndexKey("deviceid", "timestamp") 21 | 22 | return &Recorder{ 23 | session: sess, 24 | set: set, 25 | collection: collection, 26 | }, nil 27 | } 28 | 29 | func (r *Recorder) Insert(args interface{}) error { 30 | dbHandler := r.session.DB(r.set).C(r.collection) 31 | 32 | err := dbHandler.Insert(args) 33 | if err != nil { 34 | return err 35 | } 36 | 37 | return nil 38 | } 39 | 40 | func (r *Recorder) FindLatest(deviceid uint64, record interface{}) error { 41 | dbHandler := r.session.DB(r.set).C(r.collection) 42 | err := dbHandler.Find(bson.M{ 43 | "$query": bson.M{"deviceid": deviceid}, 44 | "$orderby": bson.M{"timestamp": -1}, 45 | }).Limit(1).One(record) 46 | 47 | return err 48 | } 49 | 50 | func (r *Recorder) FindByTimestamp(deviceid uint64, start uint64, end uint64, records interface{}) error { 51 | dbHandler := r.session.DB(r.set).C(r.collection) 52 | err := dbHandler.Find(bson.M{ 53 | "deviceid": deviceid, 54 | "timestamp": bson.M{"$gte": start, "$lte": end}, 55 | }).All(records) 56 | 57 | return err 58 | } 59 | -------------------------------------------------------------------------------- /pkg/mongo/recorder_test.go: -------------------------------------------------------------------------------- 1 | package mongo 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/protocol" 5 | "github.com/PandoCloud/pando-cloud/pkg/rpcs" 6 | "github.com/PandoCloud/pando-cloud/pkg/tlv" 7 | "reflect" 8 | "testing" 9 | "time" 10 | ) 11 | 12 | func TestRecorder(t *testing.T) { 13 | r, err := NewRecorder("localhost", "pandocloud", "commands") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | 18 | tlvs, err := tlv.MakeTLVs([]interface{}{float64(0.1), int64(100), uint64(200)}) 19 | if err != nil { 20 | t.Error(err) 21 | } 22 | 23 | deviceid := uint64(12345) 24 | timestamp := uint64(time.Now().Unix() * 1000) 25 | 26 | subdata := protocol.SubData{ 27 | Head: protocol.SubDataHead{1, 2, 3}, 28 | Params: tlvs, 29 | } 30 | 31 | subdatas := []protocol.SubData{} 32 | 33 | subdatas = append(subdatas, subdata) 34 | 35 | data := rpcs.ArgsOnStatus{ 36 | DeviceId: deviceid, 37 | Timestamp: timestamp, 38 | Subdata: subdatas, 39 | } 40 | 41 | err = r.Insert(data) 42 | if err != nil { 43 | t.Error(err) 44 | } 45 | 46 | readData := rpcs.ArgsOnStatus{} 47 | err = r.FindLatest(deviceid, &readData) 48 | 49 | if err != nil { 50 | t.Error(err) 51 | } 52 | 53 | if !reflect.DeepEqual(data, readData) { 54 | t.Errorf("read data want %v, but got %v", data, readData) 55 | } 56 | 57 | readDatas := []rpcs.ArgsOnStatus{} 58 | err = r.FindByTimestamp(deviceid, timestamp, timestamp, &readDatas) 59 | t.Log(readDatas) 60 | if !reflect.DeepEqual(data, readDatas[0]) { 61 | t.Errorf("read data by timestamp want %v, but got %v", data, readDatas[0]) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pkg/mqtt/broker.go: -------------------------------------------------------------------------------- 1 | package mqtt 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | type Broker struct { 9 | mgr *Manager 10 | } 11 | 12 | func NewBroker(p Provider) *Broker { 13 | // manager 14 | mgr := NewManager(p) 15 | 16 | handler := &Broker{mgr: mgr} 17 | 18 | return handler 19 | } 20 | 21 | func (b *Broker) Handle(conn net.Conn) { 22 | b.mgr.NewConn(conn) 23 | } 24 | 25 | func (b *Broker) SendMessageToDevice(deviceid uint64, msgtype string, message []byte, timeout time.Duration) error { 26 | msg := &Publish{} 27 | msg.Header.QosLevel = QosAtLeastOnce 28 | msg.TopicName = msgtype 29 | msg.Payload = BytesPayload(message) 30 | return b.mgr.PublishMessage2Device(deviceid, msg, timeout) 31 | } 32 | 33 | func (b *Broker) GetToken(deviceid uint64) ([]byte, error) { 34 | return b.mgr.GetToken(deviceid) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/mqtt/payload.go: -------------------------------------------------------------------------------- 1 | package mqtt 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | // Payload is the interface for Publish payloads. Typically the BytesPayload 9 | // implementation will be sufficient for small payloads whose full contents 10 | // will exist in memory. However, other implementations can read or write 11 | // payloads requiring them holding their complete contents in memory. 12 | type Payload interface { 13 | // Size returns the number of bytes that WritePayload will write. 14 | Size() int 15 | 16 | // WritePayload writes the payload data to w. Implementations must write 17 | // Size() bytes of data, but it is *not* required to do so prior to 18 | // returning. Size() bytes must have been written to w prior to another 19 | // message being encoded to the underlying connection. 20 | WritePayload(b *bytes.Buffer) error 21 | 22 | // ReadPayload reads the payload data from r (r will EOF at the end of the 23 | // payload). It is *not* required for r to have been consumed prior to this 24 | // returning. r must have been consumed completely prior to another message 25 | // being decoded from the underlying connection. 26 | ReadPayload(r io.Reader, n int) error 27 | } 28 | 29 | type BytesPayload []byte 30 | 31 | func (p BytesPayload) Size() int { 32 | return len(p) 33 | } 34 | 35 | func (p BytesPayload) WritePayload(b *bytes.Buffer) error { 36 | _, err := b.Write(p) 37 | return err 38 | } 39 | 40 | func (p BytesPayload) ReadPayload(r io.Reader, n int) error { 41 | _, err := io.ReadFull(r, p) 42 | return err 43 | } 44 | -------------------------------------------------------------------------------- /pkg/mqtt/provider.go: -------------------------------------------------------------------------------- 1 | package mqtt 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/rpcs" 5 | ) 6 | 7 | type Provider interface { 8 | ValidateDeviceToken(deviceid uint64, token []byte) error 9 | OnDeviceOnline(args rpcs.ArgsGetOnline) error 10 | OnDeviceOffline(deviceid uint64) error 11 | OnDeviceHeartBeat(deviceid uint64) error 12 | OnDeviceMessage(deviceid uint64, msgtype string, message []byte) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/mysql/client.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | "database/sql" 5 | _ "github.com/go-sql-driver/mysql" 6 | "time" 7 | ) 8 | 9 | var mapClients map[string]*sql.DB 10 | 11 | func GetClient(dbhost, dbport, dbname, dbuser, dbpass string) (*sql.DB, error) { 12 | 13 | pattern := dbuser + ":" + dbpass + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname 14 | _, exist := mapClients[pattern] 15 | if !exist { 16 | var err error 17 | mapClients[pattern], err = sql.Open("mysql", pattern+"?charset=utf8&parseTime=True") 18 | if err != nil { 19 | return nil, err 20 | } 21 | err = mapClients[pattern].Ping() 22 | if err != nil { 23 | return nil, err 24 | } 25 | } 26 | 27 | return mapClients[pattern], nil 28 | } 29 | 30 | func init() { 31 | mapClients = make(map[string]*sql.DB) 32 | 33 | timer := time.NewTicker(30 * time.Second) 34 | go func() { 35 | for { 36 | <-timer.C 37 | for _, db := range mapClients { 38 | db.Ping() 39 | } 40 | } 41 | }() 42 | } 43 | -------------------------------------------------------------------------------- /pkg/mysql/migrate.go: -------------------------------------------------------------------------------- 1 | // database initial and migrate 2 | package mysql 3 | 4 | import ( 5 | "github.com/PandoCloud/pando-cloud/pkg/models" 6 | _ "github.com/go-sql-driver/mysql" 7 | "github.com/jinzhu/gorm" 8 | ) 9 | 10 | func MigrateDatabase(dbhost, dbport, dbname, dbuser, dbpass string) error { 11 | mysqldb, err := GetClient(dbhost, dbport, dbname, dbuser, dbpass) 12 | if err != nil { 13 | return err 14 | } 15 | db, err := gorm.Open("mysql", mysqldb) 16 | if err != nil { 17 | return err 18 | } 19 | 20 | // Then you could invoke `*sql.DB`'s functions with it 21 | err = db.DB().Ping() 22 | if err != nil { 23 | return err 24 | } 25 | 26 | // Disable table name's pluralization 27 | db.SingularTable(true) 28 | db.LogMode(false) 29 | 30 | db.DB().Query("CREATE DATABASE PandoCloud; ") 31 | db.DB().Query("USE PandoCloud;") 32 | // Automating Migration 33 | db.Set("gorm:table_options", "ENGINE=MyISAM").AutoMigrate( 34 | &models.Device{}, 35 | &models.Product{}, 36 | &models.Vendor{}, 37 | &models.Application{}, 38 | &models.Rule{}, 39 | ) 40 | 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /pkg/mysql/migrate_test.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMigrate(t *testing.T) { 8 | err := MigrateDatabase("localhost", "3306", "", "root", "") 9 | if err != nil { 10 | t.Error(err) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pkg/online/online_test.go: -------------------------------------------------------------------------------- 1 | package online 2 | 3 | import ( 4 | "github.com/garyburd/redigo/redis" 5 | "reflect" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | var testid = uint64(100) 11 | 12 | func checkOnlineStatus(t *testing.T, mgr *Manager, status Status) { 13 | readstatus, err := mgr.GetStatus(testid) 14 | if err != nil && err != redis.ErrNil { 15 | t.Error(err) 16 | } 17 | 18 | if readstatus == nil { 19 | t.Errorf("device should be online, but is offline.") 20 | } 21 | 22 | if !reflect.DeepEqual(status, *readstatus) { 23 | t.Errorf("get status test error, want %v, got %v", status, *readstatus) 24 | } 25 | } 26 | 27 | func checkOfflineStatus(t *testing.T, mgr *Manager) { 28 | readstatus, err := mgr.GetStatus(testid) 29 | if err != nil && err != redis.ErrNil { 30 | t.Error(err) 31 | } 32 | 33 | if readstatus != nil { 34 | t.Errorf("device should be offline, but got status: %v", readstatus) 35 | } 36 | 37 | } 38 | 39 | func TestManager(t *testing.T) { 40 | mgr := NewManager("localhost:6379") 41 | 42 | status := Status{ 43 | ClientIP: "3.3.3.3", 44 | AccessRPCHost: "192.168.9.1:20030", 45 | HeartbeatInterval: 2, 46 | } 47 | 48 | err := mgr.GetOnline(testid, status) 49 | if err != nil { 50 | t.Error(err) 51 | } 52 | 53 | checkOnlineStatus(t, mgr, status) 54 | 55 | cnt := 0 56 | for { 57 | time.Sleep(time.Second * 2) 58 | if cnt > 2 { 59 | break 60 | } 61 | err := mgr.SetHeartbeat(testid) 62 | if err != nil { 63 | t.Error(err) 64 | } 65 | cnt++ 66 | } 67 | 68 | checkOnlineStatus(t, mgr, status) 69 | 70 | err = mgr.GetOffline(testid) 71 | if err != nil { 72 | t.Error(err) 73 | } 74 | 75 | checkOfflineStatus(t, mgr) 76 | 77 | } 78 | -------------------------------------------------------------------------------- /pkg/protocol/structure.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/tlv" 5 | ) 6 | 7 | type CommandEventHead struct { 8 | Flag uint8 9 | Timestamp uint64 10 | Token [16]byte 11 | SubDeviceid uint16 12 | No uint16 13 | Priority uint16 14 | ParamsCount uint16 15 | } 16 | 17 | type Command struct { 18 | Head CommandEventHead 19 | Params []tlv.TLV 20 | } 21 | 22 | type Event struct { 23 | Head CommandEventHead 24 | Params []tlv.TLV 25 | } 26 | 27 | type DataHead struct { 28 | Flag uint8 29 | Timestamp uint64 30 | Token [16]byte 31 | } 32 | 33 | type Data struct { 34 | Head DataHead 35 | SubData []SubData 36 | } 37 | 38 | type SubDataHead struct { 39 | SubDeviceid uint16 40 | PropertyNum uint16 41 | ParamsCount uint16 42 | } 43 | 44 | type SubData struct { 45 | Head SubDataHead 46 | Params []tlv.TLV 47 | } 48 | -------------------------------------------------------------------------------- /pkg/queue/queque_test.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | type test struct { 10 | Cmd int 11 | Msg string 12 | } 13 | 14 | const testQueueName = "test/queue/somename" 15 | 16 | var testChan chan test = make(chan test) 17 | 18 | func recv(t *testing.T) { 19 | q, err := New("amqp://guest:guest@localhost:5672/", testQueueName) 20 | if err != nil { 21 | t.Error(err) 22 | } 23 | msg := test{} 24 | err = q.Receive(&msg) 25 | if err != nil { 26 | t.Error(err) 27 | } 28 | testChan <- msg 29 | } 30 | 31 | func TestQueue(t *testing.T) { 32 | testMessage := test{123, "hello"} 33 | 34 | q, err := New("amqp://guest:guest@localhost:5672/", testQueueName) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | go recv(t) 40 | 41 | time.Sleep(time.Second) 42 | 43 | err = q.Send(testMessage) 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | 48 | recvMessage := <-testChan 49 | 50 | if !reflect.DeepEqual(testMessage, recvMessage) { 51 | t.Errorf("receive message not match, want: %v, got : %v", testMessage, recvMessage) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/redispool/redispool.go: -------------------------------------------------------------------------------- 1 | package redispool 2 | 3 | import ( 4 | "github.com/garyburd/redigo/redis" 5 | "time" 6 | ) 7 | 8 | var mapRedisPool map[string]*redis.Pool 9 | 10 | // GetClient get a redis connection by host 11 | func GetClient(host string) (redis.Conn, error) { 12 | 13 | pool, exist := mapRedisPool[host] 14 | if !exist { 15 | pool = &redis.Pool{ 16 | MaxIdle: 10, 17 | Dial: func() (redis.Conn, error) { 18 | c, err := redis.Dial("tcp", host) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return c, err 23 | }, 24 | TestOnBorrow: func(c redis.Conn, t time.Time) error { 25 | _, err := c.Do("PING") 26 | return err 27 | }, 28 | } 29 | mapRedisPool[host] = pool 30 | } 31 | return pool.Get(), nil 32 | } 33 | 34 | func init() { 35 | mapRedisPool = make(map[string]*redis.Pool) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/redispool/redispool_test.go: -------------------------------------------------------------------------------- 1 | package redispool 2 | 3 | import ( 4 | "github.com/garyburd/redigo/redis" 5 | "testing" 6 | ) 7 | 8 | func TestRedisCli(t *testing.T) { 9 | cli, err := GetClient("localhost:6379") 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | 14 | _, err = redis.String(cli.Do("GET", "testkey")) 15 | if err != nil && err != redis.ErrNil { 16 | t.Error(err) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pkg/rpcs/access.go: -------------------------------------------------------------------------------- 1 | package rpcs 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/protocol" 5 | "github.com/PandoCloud/pando-cloud/pkg/tlv" 6 | ) 7 | 8 | type ArgsSetStatus struct { 9 | DeviceId uint64 10 | Status []protocol.SubData 11 | } 12 | type ReplySetStatus ReplyEmptyResult 13 | 14 | type ArgsGetStatus ArgsDeviceId 15 | type ReplyGetStatus struct { 16 | Status []protocol.SubData 17 | } 18 | 19 | type ArgsSendCommand struct { 20 | DeviceId uint64 21 | SubDevice uint16 22 | No uint16 23 | Priority uint16 24 | WaitTime uint32 25 | Params []tlv.TLV 26 | } 27 | type ReplySendCommand ReplyEmptyResult 28 | -------------------------------------------------------------------------------- /pkg/rpcs/common.go: -------------------------------------------------------------------------------- 1 | package rpcs 2 | 3 | type ArgsDeviceId struct { 4 | Id uint64 5 | } 6 | 7 | type ReplyEmptyResult struct{} 8 | -------------------------------------------------------------------------------- /pkg/rpcs/controller.go: -------------------------------------------------------------------------------- 1 | package rpcs 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/protocol" 5 | "github.com/PandoCloud/pando-cloud/pkg/tlv" 6 | ) 7 | 8 | type ArgsOnStatus struct { 9 | DeviceId uint64 10 | Timestamp uint64 11 | Subdata []protocol.SubData 12 | } 13 | type ReplyOnStatus ReplyEmptyResult 14 | 15 | type ArgsOnEvent struct { 16 | DeviceId uint64 17 | TimeStamp uint64 18 | SubDevice uint16 19 | No uint16 20 | Priority uint16 21 | Params []tlv.TLV 22 | } 23 | type ReplyOnEvent ReplyEmptyResult 24 | -------------------------------------------------------------------------------- /pkg/rpcs/devicemanager.go: -------------------------------------------------------------------------------- 1 | package rpcs 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/online" 5 | ) 6 | 7 | type ArgsGenerateDeviceAccessToken ArgsDeviceId 8 | type ReplyGenerateDeviceAccessToken struct { 9 | AccessToken []byte 10 | } 11 | 12 | type ArgsValidateDeviceAccessToken struct { 13 | Id uint64 14 | AccessToken []byte 15 | } 16 | type ReplyValidateDeviceAccessToken ReplyEmptyResult 17 | 18 | type ArgsGetOnline struct { 19 | Id uint64 20 | ClientIP string 21 | AccessRPCHost string 22 | HeartbeatInterval uint32 23 | } 24 | type ReplyGetOnline ReplyEmptyResult 25 | 26 | type ArgsGetOffline ArgsDeviceId 27 | type ReplyGetOffline ReplyEmptyResult 28 | 29 | type ArgsHeartBeat struct { 30 | Id uint64 31 | } 32 | type ReplyHeartBeat ReplyEmptyResult 33 | 34 | type ArgsGetDeviceOnlineStatus ArgsDeviceId 35 | type ReplyGetDeviceOnlineStatus online.Status 36 | -------------------------------------------------------------------------------- /pkg/rpcs/registry.go: -------------------------------------------------------------------------------- 1 | package rpcs 2 | 3 | // device register args 4 | type ArgsDeviceRegister struct { 5 | ProductKey string 6 | DeviceCode string 7 | DeviceVersion string 8 | } 9 | 10 | // device update args 11 | type ArgsDeviceUpdate struct { 12 | DeviceIdentifier string 13 | DeviceName string 14 | DeviceDescription string 15 | } 16 | -------------------------------------------------------------------------------- /pkg/rule/timer.go: -------------------------------------------------------------------------------- 1 | // suport cron like schedule tasks. 2 | package rule 3 | 4 | import ( 5 | "fmt" 6 | "github.com/PandoCloud/pando-cloud/pkg/models" 7 | "github.com/PandoCloud/pando-cloud/pkg/server" 8 | "github.com/robfig/cron" 9 | "time" 10 | ) 11 | 12 | type Timer struct { 13 | c *cron.Cron 14 | } 15 | 16 | func NewTimer() *Timer { 17 | t := &Timer{} 18 | 19 | return t 20 | } 21 | 22 | func (t *Timer) createTimerFunc(target string, action string) func() { 23 | return func() { 24 | err := performRuleAction(target, action) 25 | if err != nil { 26 | server.Log.Warnf("timer action failed: %v", err) 27 | } 28 | } 29 | } 30 | 31 | func (t *Timer) refresh() { 32 | if t.c != nil { 33 | t.c.Stop() 34 | } 35 | t.c = cron.New() 36 | timers := &[]models.Rule{} 37 | query := &models.Rule{ 38 | RuleType: "timer", 39 | } 40 | err := server.RPCCallByName("registry", "Registry.QueryRules", query, timers) 41 | if err != nil { 42 | server.Log.Warnf("refresh timer rules error : %v", err) 43 | return 44 | } 45 | 46 | sec := fmt.Sprintf("%d ", (time.Now().Second()+30)%60) 47 | 48 | for _, one := range *timers { 49 | t.c.AddFunc(sec+one.Trigger, t.createTimerFunc(one.Target, one.Action)) 50 | } 51 | 52 | t.c.Start() 53 | } 54 | 55 | func (t *Timer) Run() { 56 | go func() { 57 | for { 58 | t.refresh() 59 | time.Sleep(time.Minute) 60 | } 61 | }() 62 | } 63 | -------------------------------------------------------------------------------- /pkg/serializer/serializer.go: -------------------------------------------------------------------------------- 1 | package serializer 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | ) 7 | 8 | // convert string to any kind of struct 9 | func String2Struct(str string, target interface{}) error { 10 | bytes_buffer := bytes.NewBufferString(str) 11 | dec := gob.NewDecoder(bytes_buffer) 12 | err := dec.Decode(target) 13 | return err 14 | } 15 | 16 | // convert any kind of struct to string 17 | func Struct2String(stru interface{}) (string, error) { 18 | var bytes_buffer bytes.Buffer 19 | enc := gob.NewEncoder(&bytes_buffer) 20 | err := enc.Encode(stru) 21 | return bytes_buffer.String(), err 22 | } 23 | -------------------------------------------------------------------------------- /pkg/serializer/serializer_test.go: -------------------------------------------------------------------------------- 1 | package serializer 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | type testStruct struct { 9 | Int1 int 10 | Str1 string 11 | Int2 int32 12 | Arr []byte 13 | } 14 | 15 | func TestStringStructConvert(t *testing.T) { 16 | test := testStruct{0, "hello", 12, []byte{1, 0, 12}} 17 | str, err := Struct2String(test) 18 | if err != nil { 19 | t.Error(err) 20 | } 21 | stru := testStruct{} 22 | err = String2Struct(str, &stru) 23 | if err != nil { 24 | t.Error(err) 25 | } 26 | if !reflect.DeepEqual(test, stru) { 27 | t.Errorf("wrong result %v, want %v", stru, test) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pkg/server/README.md: -------------------------------------------------------------------------------- 1 | # the server framework. 2 | includes: 3 | 4 | - tcp/http service framework 5 | - rpc helper 6 | - stats api 7 | - timer task interface 8 | -------------------------------------------------------------------------------- /pkg/server/config.go: -------------------------------------------------------------------------------- 1 | // config flags from command line or ini conf file. 2 | 3 | package server 4 | 5 | import ( 6 | "flag" 7 | ) 8 | 9 | const ( 10 | FlagTCPHost = "tcphost" 11 | FlagUseTls = "usetls" 12 | FlagHTTPHost = "httphost" 13 | FlagUseHttps = "usehttps" 14 | FlagCAFile = "cafile" 15 | FlagKeyFile = "keyfile" 16 | FlagRPCHost = "rpchost" 17 | FlagEtcd = "etcd" 18 | FlagLogLevel = "loglevel" 19 | ) 20 | 21 | var ( 22 | confTCPHost = flag.String(FlagTCPHost, "", "tcp server listen address, format ip:port") 23 | confUseTls = flag.Bool(FlagUseTls, false, "if tcp server uses tls, default false") 24 | 25 | confHTTPHost = flag.String(FlagHTTPHost, "", "http server listen address, format ip:port") 26 | confUseHttps = flag.Bool(FlagUseHttps, false, "if http server uses tls, default false") 27 | 28 | confCAFile = flag.String(FlagCAFile, "cacert.pem", "public ca pem file path") 29 | confKeyFile = flag.String(FlagKeyFile, "privkey.pem", "private key pem file path") 30 | 31 | confRPCHost = flag.String(FlagRPCHost, "", "rpc server listen address, format ip:port") 32 | 33 | confEtcd = flag.String(FlagEtcd, "", "etcd service addr, format ip:port;ip:port") 34 | 35 | confLogLevel = flag.String(FlagLogLevel, "info", "default log level, options are panic|fatal|error|warn|info|debug") 36 | ) 37 | -------------------------------------------------------------------------------- /pkg/server/errors.go: -------------------------------------------------------------------------------- 1 | // error messages 2 | 3 | package server 4 | 5 | const ( 6 | errServerNotInit = "Server has not been initialized...You must call server.Init(name) first !" 7 | errTCPHandlerNotRegistered = "Start TCP Server error : tcp handler not registered !" 8 | errMissingFlag = "Missing flag: %s !" 9 | errLoadSecureKey = "Load secret key file failed - %s" 10 | errListenFailed = "FATAL: tcp listen (%s) failed - %s" 11 | errNewConnection = "receive new connection error (%s)" 12 | errWrongHostAddr = "wrong address : %s" 13 | errWrongEtcdPath = "wrong path in etcd: %s" 14 | errServerManagerNotInit = "sever manager not init!" 15 | ) 16 | -------------------------------------------------------------------------------- /pkg/server/http_server.go: -------------------------------------------------------------------------------- 1 | // http server library. 2 | package server 3 | 4 | import ( 5 | "net/http" 6 | ) 7 | 8 | type HTTPServer struct { 9 | addr string 10 | handler http.Handler 11 | useHttps bool 12 | } 13 | 14 | func (hs *HTTPServer) Start() error { 15 | // field check 16 | if hs.handler == nil { 17 | return errorf("Start HTTP Server error : http handler not registered!") 18 | } 19 | 20 | if hs.useHttps { 21 | // secure files 22 | if *confCAFile == "" { 23 | return errorf(errMissingFlag, FlagCAFile) 24 | } 25 | if *confKeyFile == "" { 26 | return errorf(errMissingFlag, FlagKeyFile) 27 | } 28 | } 29 | 30 | Log.Infof("HTTP Server Listen on %s, use https: %v", hs.addr, hs.useHttps) 31 | go func() { 32 | var err error 33 | if hs.useHttps == false { 34 | err = http.ListenAndServe(hs.addr, hs.handler) 35 | } else { 36 | err = http.ListenAndServeTLS(hs.addr, *confCAFile, *confKeyFile, hs.handler) 37 | } 38 | 39 | if err != nil { 40 | Log.Fatal(err.Error()) 41 | } 42 | }() 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /pkg/server/log.go: -------------------------------------------------------------------------------- 1 | // log provides log api. 2 | // thanks to the helpful log tool logrus(https://github.com/Sirupsen/logrus) 3 | package server 4 | 5 | import ( 6 | "github.com/Sirupsen/logrus" 7 | ) 8 | 9 | var Log *logrus.Entry 10 | 11 | func initLog(name string, level string) error { 12 | if Log == nil { 13 | // Log as JSON instead of the default ASCII formatter. 14 | logrus.SetFormatter(&logrus.JSONFormatter{}) 15 | 16 | // Output to stderr instead of stdout, could also be a file. 17 | // logrus.SetOutput(os.Stderr) 18 | 19 | // logging level 20 | lvl, err := logrus.ParseLevel(level) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | logrus.SetLevel(lvl) 26 | 27 | // default fields 28 | Log = logrus.WithFields(logrus.Fields{ 29 | "service": name, 30 | "ip": InternalIP, 31 | }) 32 | } 33 | 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /pkg/server/log_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLog(t *testing.T) { 8 | Log = nil 9 | err := initLog("wrongtest", "wronglevel") 10 | if err == nil { 11 | t.Errorf("init log should return error when level is wrong.") 12 | } 13 | 14 | err = initLog("test", "error") 15 | if err != nil { 16 | t.Error(err) 17 | } 18 | 19 | Log.Error("test log.") 20 | } 21 | -------------------------------------------------------------------------------- /pkg/server/netif_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNetIf(t *testing.T) { 8 | readNetInterfaces() 9 | t.Logf("internal ip: %s", InternalIP) 10 | t.Logf("external ip: %s", ExternalIP) 11 | } 12 | 13 | func TestIsInternalIP(t *testing.T) { 14 | testIPs := []string{"127.0.0.1", "192.168.5.234", "10.23.45.56", "172.17.2.4"} 15 | for _, ip := range testIPs { 16 | if isInternalIP(ip) == false { 17 | t.Errorf("test internal ip failed: %s", ip) 18 | } 19 | } 20 | } 21 | 22 | func TestFixHostIP(t *testing.T) { 23 | InternalIP = "10.1.1.1" 24 | ExternalIP = "5.1.1.1" 25 | fixedIP, err := fixHostIp("internal:40") 26 | if err != nil || fixedIP != "10.1.1.1:40" { 27 | t.Errorf("test fix host ip failed: %s, %s", fixedIP, err) 28 | } 29 | fixedIP, err = fixHostIp("external:40") 30 | if err != nil || fixedIP != "5.1.1.1:40" { 31 | t.Errorf("test fix host ip failed: %s, %s", fixedIP, err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pkg/server/rpc_client_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func validateRPCClient(t *testing.T) { 8 | rpccli, err := NewRPCClient() 9 | if err != nil { 10 | t.Fatal(err) 11 | } 12 | 13 | args := &Args{100, 200} 14 | var reply int 15 | 16 | err = rpccli.Call("test", "Arith.Multiply", args, &reply) 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | if reply != testRPCArgs.A*testRPCArgs.B { 22 | t.Fatalf("rpc client test faild, want %d, got %d", testRPCArgs.A*testRPCArgs.B, reply) 23 | } 24 | 25 | err = RPCCallByName("test", "Arith.Multiply", args, &reply) 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | err = RPCCallByHost(*confRPCHost, "Arith.Multiply", args, &reply) 31 | if err != nil { 32 | t.Fatal(err) 33 | } 34 | 35 | if reply != testRPCArgs.A*testRPCArgs.B { 36 | t.Fatalf("rpc client test faild, want %d, got %d", testRPCArgs.A*testRPCArgs.B, reply) 37 | } 38 | 39 | err = rpccli.Call("wrongtest", "Arith.Multiply", args, &reply) 40 | t.Log(err) 41 | if err == nil { 42 | t.Fatalf("rpc client should return error when no server found!") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pkg/server/rpc_server.go: -------------------------------------------------------------------------------- 1 | // rpc server 2 | package server 3 | 4 | import ( 5 | "net" 6 | "net/rpc" 7 | ) 8 | 9 | type RPCServer struct { 10 | TCPServer 11 | } 12 | 13 | type rpcHandler struct{} 14 | 15 | func (handler *rpcHandler) Handle(conn net.Conn) { 16 | rpc.ServeConn(conn) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/server/rpc_server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "net/rpc" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | const ( 10 | testRPCHost = "localhost:12346" 11 | ) 12 | 13 | var testRPCArgs = &Args{100, 200} 14 | 15 | type Args struct { 16 | A, B int 17 | } 18 | 19 | type Arith int 20 | 21 | func (t *Arith) Multiply(args *Args, reply *int) error { 22 | *reply = args.A * args.B 23 | return nil 24 | } 25 | 26 | func validateRPCServer(t *testing.T, addr string, method string) { 27 | rpccli, err := rpc.Dial("tcp", addr) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | var reply int 33 | 34 | err = rpccli.Call(method, testRPCArgs, &reply) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | if reply != testRPCArgs.A*testRPCArgs.B { 40 | t.Fatalf("rpc test faild, want %d, got %d", testRPCArgs.A*testRPCArgs.B, reply) 41 | } 42 | } 43 | 44 | func TestRPCServer(t *testing.T) { 45 | initLog("test", "debug") 46 | 47 | testRPC := new(Arith) 48 | 49 | err := rpc.Register(testRPC) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | 54 | handler := rpcHandler{} 55 | 56 | svr := &RPCServer{ 57 | TCPServer{ 58 | addr: testRPCHost, 59 | handler: &handler, 60 | useTls: false, 61 | }, 62 | } 63 | 64 | err = svr.Start() 65 | if err != nil { 66 | t.Fatal(err) 67 | } 68 | 69 | time.Sleep(time.Millisecond * 300) 70 | 71 | validateRPCServer(t, testRPCHost, "Arith.Multiply") 72 | } 73 | -------------------------------------------------------------------------------- /pkg/server/testdata/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC+TCCAeGgAwIBAgIQJfY0073hjBlu0vY/xbvYHzANBgkqhkiG9w0BAQsFADAS 3 | MRAwDgYDVQQKEwdBY21lIENvMB4XDTE1MTAyMjA3MzkwOFoXDTE2MTAyMTA3Mzkw 4 | OFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC 5 | AQoCggEBAMbJZYRbvbevHkFzkVrP8Zg54QAfiaCMx36W9YWVaTf793Y90dqmUAdr 6 | A7DhB5TO6Dz0L1Zao+7HAqwEHxNSkOjGDxI3zo3/N5Q5dStHmmTRz49+lUR1L1NA 7 | kX9QlvPPgkAGb9Z40CmtckZStH9QXujxuYqH18HJnbuVxntogbNMfCX98Ix3N6oI 8 | ktuRE/GtysmJ7YyrPP1JUv358jA3Y44WLFFcJ3+X4MsZEthEqRsb/fqd5WUfRarK 9 | HgC5AuX226out8QRfd0WWjiuWaXWmV7y9lw2Buzakh4Wu+P0tkbc+iLwtTlhEgx9 10 | dXMIZfVrO6OcAkNxunbojuCR/wl0REkCAwEAAaNLMEkwDgYDVR0PAQH/BAQDAgWg 11 | MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFAYDVR0RBA0wC4IJ 12 | bG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQB1fqZEISFArzR5oIiy1tdJu4wO 13 | YcZxKvemJo7PaZluNE4eAw1ITbVZKEGpSzi5dYC5A13Q5pP8ue7FvOQonm5elEY4 14 | fLDZhzpfnRj+oDhc+NPBhczCh640gcdxe6BtAcmsOJJEenLEPsGj3NrQZbPl9anL 15 | 94v9NPdvFuy1ZpLMRb8WEZO4f/iGTAj7Hg7tzxvWMIg0mbrZg9spR2wgRqyzXPEK 16 | A0awbuFuVDmg1+x1SVq6BjY+XL9+B4KiCAOQFA5dX+v1+ruSxsliUzcM8840V8i6 17 | uRBTV982FZWhbuiFJJY4/c46tjJ0DRvXdkUiEAeLeTaIb1Lkk2Q+XtfvV+2c 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /pkg/server/testdata/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAxsllhFu9t68eQXORWs/xmDnhAB+JoIzHfpb1hZVpN/v3dj3R 3 | 2qZQB2sDsOEHlM7oPPQvVlqj7scCrAQfE1KQ6MYPEjfOjf83lDl1K0eaZNHPj36V 4 | RHUvU0CRf1CW88+CQAZv1njQKa1yRlK0f1Be6PG5iofXwcmdu5XGe2iBs0x8Jf3w 5 | jHc3qgiS25ET8a3KyYntjKs8/UlS/fnyMDdjjhYsUVwnf5fgyxkS2ESpGxv9+p3l 6 | ZR9FqsoeALkC5fbbqi63xBF93RZaOK5ZpdaZXvL2XDYG7NqSHha74/S2Rtz6IvC1 7 | OWESDH11cwhl9Ws7o5wCQ3G6duiO4JH/CXRESQIDAQABAoIBAHTduBn9WWbgxBfU 8 | mpLaB33oIRhScjX6LdqFY2iac1Zfgpd4NqSl/AywZGYblbptfek/4YiSFyhsxWxd 9 | q+tPMjQ3JGsgdgXTEljJAtJj8SfulWkWESlC/4ShRCimN2i1CS0c26kqM68c8j7X 10 | ppfmpzWpztvbiwO5xUqf/iVVRlMizdDXXPssGJlDI/DtiyVx1tMt0YkUrsrZKW2P 11 | cTrYWA638GnQ6IDYPp9rQYwkaAeWbvm1aI5CqB7fJdIsyp9XslUGdUiRe1yIoT/G 12 | q/BMP38NfyxfbZQzVPrniZl67wwVRLvp3Te2PKjOts89/yBN5FaqgdIpbzJ06aOc 13 | 9Mqci9ECgYEA2/GUVMnjmct0Wd1/PaPVWfjyMknVIMP2pLZLN07DEu6x+5i2DOtd 14 | B6bp23yDyX2okNho0GTmq+l7qRaMNb/pFcOiFuduaJ4H5NM445pw9EWwn9keah6R 15 | SFE7pq2qoBRi2ogiqJGnMOrWNmBvxBVYDqavWLLEZuvjAaJWJWKb6qUCgYEA51/r 16 | JCG3bLE4Q3anmaXer0Bpqwr7iDRM1qw+3gAzWN/ePUtEefC4iUPnxRKxRy/ovDGZ 17 | iUCmYD6p3yR0g9+4pdmgoeekQm81Rrr6jk9T3bMpg15x1h9VqKqnZliXMo4dH67o 18 | HUTUIPag8YUnFavDi63zZzQgUwTU7YJw0PUIldUCgYEAldz6s/dIRO+zXNQmsepj 19 | IkYVSRyzwvqjoUGw6IObOdg4n/VC/nSU0/TwXaRu66jaZa9/Y5eM8VBK+UCq0qjr 20 | +e9uD2sr+M7NFCa0GamPE3I00gYPykD/vyXSnlSw8RhS7xJZg0CTiipJQY3eOd5N 21 | PNZonehZGMPbzq49QoX5NR0CgYEAyIA+bFkrcm1ArHWuV1990bCn4SjrP+TSkVVC 22 | RW83D9Uv6T3IYUNRJuJJfmXsahwCOtNgkagMhWrIGi6lKYI9qLsmkCcEGO315Q0z 23 | Aw+LRZt0Zfr5+uu8dyUrW2152L1+T25qhrKWgNo4LhONAyKNmgVr4Asz171gJ1Ha 24 | Ibm1buECgYEAmNBNkfgm4OcGOABcR/8TU1uBE7aplN8XUOv3rTslD9gs4SCMmK1x 25 | 87MofB4aX6gQ2KNfvIlOQ8vhxc5XgTTYIZt+TL/UlQXQKPeKgX8ok9I3U7YEmhJ+ 26 | 98q5D+qpyQOqVO/mcgwN3+YWG8fq9OrEcB/anFYJb7KtQbXWm3p7iX0= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /pkg/server/timer_task.go: -------------------------------------------------------------------------------- 1 | // the timer task interface. 2 | 3 | package server 4 | 5 | type TimerTask interface { 6 | DoTask() 7 | } 8 | -------------------------------------------------------------------------------- /pkg/server/utils.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // will print a log and return error 8 | func errorf(format string, a ...interface{}) error { 9 | err := fmt.Errorf(format, a...) 10 | Log.Error(err) 11 | return err 12 | } 13 | -------------------------------------------------------------------------------- /pkg/server/utils_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | ) 7 | 8 | func TestErrorf(t *testing.T) { 9 | err := errorf("err %s %d", "1", 2) 10 | if err.Error() != "err 1 2" { 11 | t.Errorf("err is %v ,want %v", err, errors.New("err 1 2")) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pkg/token/token_test.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTokenHelper(t *testing.T) { 8 | helper := NewHelper("localhost:6379") 9 | 10 | testid := uint64(123) 11 | 12 | token, err := helper.GenerateToken(testid) 13 | if err != nil { 14 | t.Error(err) 15 | } 16 | 17 | err = helper.ValidateToken(testid, token) 18 | if err != nil { 19 | t.Error(err) 20 | } 21 | 22 | err = helper.ClearToken(testid) 23 | if err != nil { 24 | t.Error(err) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /pkg/utils/http.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | /** 11 | Params: 12 | argUrl: reqeust url 13 | argReq: reqeust contents 14 | argType: reqeust type 15 | argHead: reqeust head 16 | Retrun: reqesut result body 17 | */ 18 | func SendHttpRequest(argUrl string, argReq string, argType string, argHead map[string]string) ([]byte, error) { 19 | bReq := []byte(argReq) 20 | req, err := http.NewRequest(argType, argUrl, bytes.NewBuffer(bReq)) 21 | if err != nil { 22 | return []byte{}, err 23 | } 24 | req.Header.Set("Content-Type", "application/json") 25 | if argHead != nil { 26 | for key, vaule := range argHead { 27 | req.Header.Set(key, vaule) 28 | } 29 | } 30 | tr := &http.Transport{ 31 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 32 | } 33 | client := &http.Client{Transport: tr} 34 | resp, err := client.Do(req) 35 | if err != nil { 36 | return []byte{}, err 37 | } 38 | defer resp.Body.Close() 39 | body, _ := ioutil.ReadAll(resp.Body) 40 | return body, nil 41 | } 42 | -------------------------------------------------------------------------------- /pkg/utils/http_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSendHttpRequest(t *testing.T) { 8 | headers := make(map[string]string) 9 | headers["test"] = "test" 10 | 11 | res, err := SendHttpRequest("http://www.baidu.com", "", "GET", headers) 12 | 13 | if err != nil { 14 | t.Error(err) 15 | } 16 | 17 | t.Log(len(res)) 18 | } 19 | -------------------------------------------------------------------------------- /services/README.md: -------------------------------------------------------------------------------- 1 | # core services to serve iot devices. 2 | 3 | - **mqttaccess**: mqtt access service which accepts device mqtt connections. 4 | - **httpaccess**: device api service which offers device http apis like authentication, registration, etc. 5 | - **devicemanager**: device info and status management. 6 | - **controller**: logic and route service. 7 | - **apiprovidor**: http apis for applications, and notify device status changes to applications. 8 | - **registry**: service that keep global configuration and info. 9 | -------------------------------------------------------------------------------- /services/apiprovider/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | ) 6 | 7 | const ( 8 | flagRabbitHost = "rabbithost" 9 | defaultRabbitHost = "amqp://guest:guest@localhost:5672/" 10 | ) 11 | 12 | var ( 13 | confRabbitHost = flag.String(flagRabbitHost, defaultRabbitHost, "rabbitmq host address, amqp://user:password@ip:port/") 14 | ) 15 | -------------------------------------------------------------------------------- /services/apiprovider/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/server" 5 | "github.com/go-martini/martini" 6 | "github.com/martini-contrib/render" 7 | ) 8 | 9 | func main() { 10 | // init server 11 | err := server.Init("apiprovidor") 12 | if err != nil { 13 | server.Log.Fatal(err) 14 | return 15 | } 16 | 17 | // martini setup 18 | martini.Env = martini.Prod 19 | handler := martini.Classic() 20 | handler.Use(render.Renderer()) 21 | route(handler) 22 | 23 | // register a http handler 24 | err = server.RegisterHTTPHandler(handler) 25 | if err != nil { 26 | server.Log.Errorf("RegisterHTTPHandler Error: %s", err) 27 | return 28 | } 29 | 30 | // run notifier 31 | err = RunNotifier() 32 | if err != nil { 33 | server.Log.Fatalf("Run Notifier Error: %s", err) 34 | } 35 | 36 | // go 37 | err = server.Run() 38 | if err != nil { 39 | server.Log.Fatal(err) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /services/apiprovider/middleware_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func checkPair(t *testing.T, domain string, identifier string, shoudpass bool) { 8 | err := checkAppDomain(domain, identifier) 9 | if shoudpass { 10 | if err != nil { 11 | t.Errorf("check domain should pass, but failed: domain: %v, identifier: %v, err: %v", domain, identifier, err) 12 | } 13 | } else { 14 | if err == nil { 15 | t.Errorf("check domain should fail, but passed: domain: %v, identifier: %v, err: %v", domain, identifier, err) 16 | } 17 | } 18 | } 19 | 20 | func TestCheckAppDomain(t *testing.T) { 21 | checkPair(t, "", "", false) 22 | checkPair(t, "*", "1-2-3333", true) 23 | checkPair(t, "vendor/1", "1-2-3333", true) 24 | checkPair(t, "product/2", "1-2-3333", true) 25 | checkPair(t, "product/2", "1-a-3333", false) 26 | checkPair(t, "product/10", "1-a-3333", true) 27 | checkPair(t, "vendor/11", "b-a-3333", true) 28 | checkPair(t, "fff/product/2", "1-a-3333", false) 29 | checkPair(t, "product/10", "1-a-3333-11111", false) 30 | } 31 | -------------------------------------------------------------------------------- /services/apiprovider/request.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type CreateRuleRequest struct { 4 | Type string `json:"type"` 5 | Trigger string `json:"trigger"` 6 | Target string `json:"target"` 7 | Action string `json:"action"` 8 | } 9 | -------------------------------------------------------------------------------- /services/apiprovider/response.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // common response fields 4 | type Common struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | } 8 | 9 | type DeviceInfoData struct { 10 | Identifier string `json:"identifier"` 11 | Name string `json:"name"` 12 | Description string `json:"description"` 13 | Version string `json:"version"` 14 | } 15 | 16 | type DeviceInfoResponse struct { 17 | Common 18 | Data DeviceInfoData `json:"data"` 19 | } 20 | 21 | type DeviceStatusData map[string][]interface{} 22 | 23 | type DeviceStatusResponse struct { 24 | Common 25 | Data DeviceStatusData `json:"data"` 26 | } 27 | -------------------------------------------------------------------------------- /services/apiprovider/router.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/go-martini/martini" 5 | // "github.com/martini-contrib/binding" 6 | ) 7 | 8 | // martini router 9 | func route(m *martini.ClassicMartini) { 10 | // find a device by key 11 | m.Get("/application/v1/device/info", GetDeviceInfoByKey) 12 | 13 | // find a device by identifier 14 | m.Get("/application/v1/devices/:identifier/info", ApplicationAuthOnDeviceIdentifer, GetDeviceInfoByIdentifier) 15 | 16 | // get devie current status 17 | m.Get("/application/v1/devices/:identifier/status/current", 18 | ApplicationAuthOnDeviceIdentifer, CheckDeviceOnline, CheckProductConfig, 19 | GetDeviceCurrentStatus) 20 | 21 | // get devie latest status 22 | m.Get("/application/v1/devices/:identifier/status/latest", 23 | ApplicationAuthOnDeviceIdentifer, CheckDeviceOnline, CheckProductConfig, 24 | GetDeviceLatestStatus) 25 | 26 | // set device status 27 | m.Put("/application/v1/devices/:identifier/status", 28 | ApplicationAuthOnDeviceIdentifer, CheckDeviceOnline, CheckProductConfig, 29 | SetDeviceStatus) 30 | 31 | // send a command to device 32 | m.Post("/application/v1/devices/:identifier/commands", 33 | ApplicationAuthOnDeviceIdentifer, CheckDeviceOnline, CheckProductConfig, 34 | SendCommandToDevice) 35 | 36 | // and a rule to device 37 | m.Post("/application/v1/devices/:identifier/rules", 38 | ApplicationAuthOnDeviceIdentifer, CheckDeviceIdentifier, 39 | AddRule) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /services/controller/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | ) 6 | 7 | const ( 8 | flagMongoHost = "mongohost" 9 | defaultMongoHost = "localhost" 10 | 11 | flagRabbitHost = "rabbithost" 12 | defaultRabbitHost = "amqp://guest:guest@localhost:5672/" 13 | ) 14 | 15 | var ( 16 | confMongoHost = flag.String(flagMongoHost, defaultMongoHost, "mongo host address, ip:port") 17 | confRabbitHost = flag.String(flagRabbitHost, defaultRabbitHost, "rabbitmq host address, amqp://user:password@ip:port/") 18 | ) 19 | -------------------------------------------------------------------------------- /services/controller/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/server" 5 | ) 6 | 7 | func main() { 8 | // init server 9 | err := server.Init("controller") 10 | if err != nil { 11 | server.Log.Fatal(err) 12 | return 13 | } 14 | 15 | // register a rpc service 16 | controller, err := NewController(*confMongoHost, *confRabbitHost) 17 | if err != nil { 18 | server.Log.Errorf("NewController Error: %s", err) 19 | return 20 | } 21 | 22 | err = server.RegisterRPCHandler(controller) 23 | if err != nil { 24 | server.Log.Errorf("Register RPC service Error: %s", err) 25 | return 26 | } 27 | 28 | // start to run 29 | err = server.Run() 30 | if err != nil { 31 | server.Log.Fatal(err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /services/devicemanager/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | ) 6 | 7 | const ( 8 | flagRedisHost = "redishost" 9 | 10 | defaultRedisHost = "localhost:6379" 11 | ) 12 | 13 | var ( 14 | confRedisHost = flag.String(flagRedisHost, defaultRedisHost, "redis host address, ip:port") 15 | ) 16 | -------------------------------------------------------------------------------- /services/devicemanager/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/server" 5 | ) 6 | 7 | func main() { 8 | // init server 9 | err := server.Init("devicemanager") 10 | if err != nil { 11 | server.Log.Fatal(err) 12 | return 13 | } 14 | 15 | // register a rpc service 16 | dm := NewDeviceManager(*confRedisHost) 17 | err = server.RegisterRPCHandler(dm) 18 | if err != nil { 19 | server.Log.Errorf("Register RPC service Error: %s", err) 20 | return 21 | } 22 | 23 | // start to run 24 | err = server.Run() 25 | if err != nil { 26 | server.Log.Fatal(err) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /services/devicemanager/manager_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/rpcs" 5 | "testing" 6 | ) 7 | 8 | func TestDeviceManager(t *testing.T) { 9 | mgr := NewDeviceManager("localhost:6379") 10 | 11 | deviceid := uint64(123456) 12 | 13 | args1 := rpcs.ArgsGenerateDeviceAccessToken{ 14 | Id: deviceid, 15 | } 16 | reply1 := rpcs.ReplyGenerateDeviceAccessToken{} 17 | err := mgr.GenerateDeviceAccessToken(args1, &reply1) 18 | if err != nil { 19 | t.Fatal(err) 20 | } 21 | 22 | token := reply1.AccessToken 23 | 24 | args2 := rpcs.ArgsValidateDeviceAccessToken{ 25 | Id: deviceid, 26 | AccessToken: token, 27 | } 28 | reply2 := rpcs.ReplyValidateDeviceAccessToken{} 29 | err = mgr.ValidateDeviceAccessToken(args2, &reply2) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | 34 | args3 := rpcs.ArgsGetOnline{ 35 | Id: deviceid, 36 | ClientIP: "", 37 | AccessRPCHost: "", 38 | HeartbeatInterval: 10, 39 | } 40 | reply3 := rpcs.ReplyGetOnline{} 41 | err = mgr.GetOnline(args3, &reply3) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | 46 | args4 := rpcs.ArgsHeartBeat{ 47 | Id: deviceid, 48 | } 49 | reply4 := rpcs.ReplyHeartBeat{} 50 | err = mgr.HeartBeat(args4, &reply4) 51 | if err != nil { 52 | t.Fatal(err) 53 | } 54 | 55 | args5 := rpcs.ArgsGetDeviceStatus{ 56 | Id: deviceid, 57 | } 58 | reply5 := rpcs.ReplyGetDeviceStatus{} 59 | err = mgr.GetDeviceStatus(args5, &reply5) 60 | if err != nil { 61 | t.Fatal(err) 62 | } 63 | t.Log(reply5) 64 | 65 | args6 := rpcs.ArgsGetOffline{ 66 | Id: deviceid, 67 | } 68 | reply6 := rpcs.ReplyGetOffline{} 69 | err = mgr.GetOffline(args6, &reply6) 70 | if err != nil { 71 | t.Fatal(err) 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /services/httpaccess/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | ) 6 | 7 | const ( 8 | flagRedisHost = "redishost" 9 | 10 | defaultRedisHost = "localhost:6379" 11 | ) 12 | 13 | var ( 14 | confRedisHost = flag.String(flagRedisHost, defaultRedisHost, "redis host address, ip:port") 15 | ) 16 | -------------------------------------------------------------------------------- /services/httpaccess/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/server" 5 | "github.com/go-martini/martini" 6 | "github.com/martini-contrib/render" 7 | ) 8 | 9 | func main() { 10 | // init server 11 | err := server.Init("httpaccess") 12 | if err != nil { 13 | server.Log.Fatal(err) 14 | return 15 | } 16 | 17 | // martini setup 18 | martini.Env = martini.Prod 19 | handler := martini.Classic() 20 | handler.Use(render.Renderer()) 21 | route(handler) 22 | 23 | // register a http handler 24 | err = server.RegisterHTTPHandler(handler) 25 | if err != nil { 26 | server.Log.Errorf("RegisterHTTPHandler Error: %s", err) 27 | return 28 | } 29 | 30 | // go 31 | err = server.Run() 32 | if err != nil { 33 | server.Log.Fatal(err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /services/httpaccess/response.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // common response fields 4 | type Common struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | } 8 | 9 | // device register response data field 10 | type DeviceRegisterData struct { 11 | DeviceId int64 `json:"device_id"` 12 | DeviceSecret string `json:"device_secret"` 13 | DeviceKey string `json:"device_key"` 14 | DeviceIdentifier string `json:"device_identifier"` 15 | } 16 | 17 | // device register response 18 | type DeviceRegisterResponse struct { 19 | Common 20 | Data DeviceRegisterData `json:"data"` 21 | } 22 | 23 | // device auth response data field 24 | type DeviceAuthData struct { 25 | AccessToken string `json:"access_token"` 26 | AccessAddr string `json:"access_addr"` 27 | } 28 | 29 | // device auth response 30 | type DeviceAuthResponse struct { 31 | Common 32 | Data DeviceAuthData `json:"data"` 33 | } 34 | -------------------------------------------------------------------------------- /services/httpaccess/router.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/go-martini/martini" 5 | "github.com/martini-contrib/binding" 6 | ) 7 | 8 | // martini router 9 | func route(m *martini.ClassicMartini) { 10 | // regist a device 11 | m.Post("/v1/devices/registration", binding.Json(DeviceRegisterArgs{}), RegisterDevice) 12 | 13 | // auth device 14 | m.Post("/v1/devices/authentication", binding.Json(DeviceAuthArgs{}), AuthDevice) 15 | 16 | } 17 | -------------------------------------------------------------------------------- /services/mqttaccess/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/server" 5 | ) 6 | 7 | func main() { 8 | // init server 9 | err := server.Init("mqttaccess") 10 | if err != nil { 11 | server.Log.Fatal(err) 12 | return 13 | } 14 | 15 | a, err := NewAccess() 16 | if err != nil { 17 | server.Log.Fatal(err) 18 | return 19 | } 20 | 21 | // register a rpc service 22 | err = server.RegisterRPCHandler(a) 23 | if err != nil { 24 | server.Log.Errorf("Register RPC service Error: %s", err) 25 | return 26 | } 27 | 28 | // register a tcp service for mqtt 29 | err = server.RegisterTCPHandler(a.MqttBroker) 30 | if err != nil { 31 | server.Log.Errorf("Register TCP service Error: %s", err) 32 | return 33 | } 34 | 35 | // start to run 36 | err = server.Run() 37 | if err != nil { 38 | server.Log.Fatal(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /services/mqttaccess/status.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/protocol" 5 | ) 6 | 7 | var StatusChan map[uint64]chan *protocol.Data 8 | 9 | func init() { 10 | StatusChan = make(map[uint64]chan *protocol.Data) 11 | } 12 | -------------------------------------------------------------------------------- /services/registry/cache.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "github.com/PandoCloud/pando-cloud/pkg/cache" 6 | ) 7 | 8 | const ( 9 | flagCacheSize = "cacheSize" 10 | defaultCacheSize = 102400 11 | ) 12 | 13 | var ( 14 | confCacheSize = flag.Int(flagCacheSize, defaultCacheSize, "maximum size of cache") 15 | ) 16 | 17 | var MemCache cache.Cache 18 | 19 | func getCache() cache.Cache { 20 | if MemCache == nil { 21 | MemCache = cache.NewMemCache(*confCacheSize) 22 | } 23 | return MemCache 24 | } 25 | -------------------------------------------------------------------------------- /services/registry/db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "github.com/PandoCloud/pando-cloud/pkg/mysql" 6 | "github.com/jinzhu/gorm" 7 | ) 8 | 9 | const ( 10 | flagDBHost = "dbhost" 11 | flagDBPort = "dbport" 12 | flagDBName = "dbname" 13 | flagDBUser = "dbuser" 14 | flagDBPass = "dbpass" 15 | 16 | defaultDBHost = "localhost" 17 | defaultDBPort = "3306" 18 | defaultDBName = "PandoCloud" 19 | defaultDBUser = "root" 20 | ) 21 | 22 | var ( 23 | confDBHost = flag.String(flagDBHost, defaultDBHost, "database host address.") 24 | confDBPort = flag.String(flagDBPort, defaultDBPort, "database host port.") 25 | confDBName = flag.String(flagDBName, defaultDBName, "database name.") 26 | confDBUser = flag.String(flagDBUser, defaultDBUser, "database user.") 27 | confDBPass = flag.String(flagDBPass, "", "databse password.") 28 | ) 29 | 30 | var DB *gorm.DB 31 | 32 | func getDB() (*gorm.DB, error) { 33 | db, err := mysql.GetClient(*confDBHost, *confDBPort, *confDBName, *confDBUser, *confDBPass) 34 | if err != nil { 35 | return nil, err 36 | } 37 | gormdb, err := gorm.Open("mysql", db) 38 | if err != nil { 39 | return nil, err 40 | } 41 | gormdb.SingularTable(true) 42 | gormdb.LogMode(true) 43 | return gormdb, nil 44 | } 45 | -------------------------------------------------------------------------------- /services/registry/db_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestWrongDB(t *testing.T) { 8 | *confDBPass = "wrongpassword" 9 | 10 | _, err := getDB() 11 | if err == nil { 12 | t.Errorf("get db should fail with wrong db config") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /services/registry/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/PandoCloud/pando-cloud/pkg/mysql" 5 | "github.com/PandoCloud/pando-cloud/pkg/server" 6 | ) 7 | 8 | func main() { 9 | // init server 10 | err := server.Init("registry") 11 | if err != nil { 12 | server.Log.Fatal(err) 13 | return 14 | } 15 | 16 | err = mysql.MigrateDatabase(*confDBHost, *confDBPort, *confDBName, *confDBUser, *confDBPass) 17 | if err != nil { 18 | server.Log.Fatal(err) 19 | return 20 | } 21 | 22 | // register a rpc service 23 | r, err := NewRegistry() 24 | if err != nil { 25 | server.Log.Fatal(err) 26 | return 27 | } 28 | err = server.RegisterRPCHandler(r) 29 | if err != nil { 30 | server.Log.Errorf("Register RPC service Error: %s", err) 31 | return 32 | } 33 | 34 | // start to run 35 | err = server.Run() 36 | if err != nil { 37 | server.Log.Fatal(err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /services/registry/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | func genDeviceIdentifier(vendor int32, product int32, device string) string { 8 | return strconv.FormatInt(int64(vendor), 16) + "-" + strconv.FormatInt(int64(product), 16) + "-" + device 9 | } 10 | -------------------------------------------------------------------------------- /services/registry/utils_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenDeviceIdentifier(t *testing.T) { 8 | vendorid, productid, devicecode := int32(100), int32(100), "ffaf4fffeeaa" 9 | identifier := genDeviceIdentifier(vendorid, productid, devicecode) 10 | if identifier != "64-64-ffaf4fffeeaa" { 11 | t.Errorf("gen identifier error, need %s, got %s ", "64-64-ffaf4fffeeaa", identifier) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/device/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | var ( 9 | TestUrl = flag.String("url", "https://localhost", "login url") 10 | TestProductKey = flag.String("productkey", "", "product key") 11 | ) 12 | 13 | func main() { 14 | flag.Parse() 15 | 16 | if *TestProductKey == "" { 17 | fmt.Println("product key not provided. use -productkey flag") 18 | return 19 | } 20 | 21 | dev := NewDevice(*TestUrl, *TestProductKey, "ffe34e", "version") 22 | 23 | err := dev.DoRegister() 24 | if err != nil { 25 | fmt.Errorf("device register error %s", err) 26 | return 27 | } 28 | 29 | err = dev.DoLogin() 30 | if err != nil { 31 | fmt.Errorf("device login error %s", err) 32 | return 33 | } 34 | 35 | err = dev.DoAccess() 36 | if err != nil { 37 | fmt.Errorf("device access error %s", err) 38 | return 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tools/pdcfg/README.md: -------------------------------------------------------------------------------- 1 | # pdcfg 2 | a interactive command line config tool for pando cloud. 3 | -------------------------------------------------------------------------------- /tools/pdcfg/command_handlers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type CommandHandler struct { 8 | cmdHandler map[string]func(args []string) error 9 | } 10 | 11 | func NewCommandHander() *CommandHandler { 12 | return &CommandHandler{ 13 | cmdHandler: make(map[string](func(args []string) error)), 14 | } 15 | } 16 | 17 | func (ch *CommandHandler) SetHandler(cmd string, handler func(args []string) error) { 18 | ch.cmdHandler[cmd] = handler 19 | } 20 | 21 | func (ch *CommandHandler) GetHandler(cmd string) (func(args []string) error, error) { 22 | handler, exist := ch.cmdHandler[cmd] 23 | if !exist { 24 | return nil, errors.New("command not found: " + cmd) 25 | } 26 | return handler, nil 27 | } 28 | -------------------------------------------------------------------------------- /tools/pdcfg/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "github.com/PandoCloud/pando-cloud/pkg/server" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | func main() { 12 | // init server 13 | err := server.Init("pdcfg") 14 | if err != nil { 15 | fmt.Printf("pdcfg init error : %s\n", err) 16 | return 17 | } 18 | 19 | cmdHandler := NewCommandHander() 20 | cmdHandler.SetHandler("vendor", DoVendorCommand) 21 | cmdHandler.SetHandler("product", DoProductCommand) 22 | cmdHandler.SetHandler("application", DoApplicationCommand) 23 | 24 | reader := bufio.NewReader(os.Stdin) 25 | 26 | for { 27 | fmt.Printf("> ") 28 | line, err := reader.ReadString('\n') 29 | if err != nil { 30 | fmt.Println(err) 31 | continue 32 | } 33 | 34 | fragments := strings.Split(line, " ") 35 | if len(fragments) < 1 { 36 | fmt.Println("wrong command.") 37 | continue 38 | } 39 | cmd := fragments[0] 40 | handler, err := cmdHandler.GetHandler(cmd) 41 | if err != nil { 42 | fmt.Printf("Error: %v \n", err) 43 | continue 44 | } 45 | 46 | args := fragments[1:] 47 | err = handler(args) 48 | if err != nil { 49 | fmt.Println(err) 50 | continue 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tools/pdcfg/utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func printStruct(stru interface{}) { 9 | value := reflect.ValueOf(stru) 10 | elem := value.Elem() 11 | for i := 0; i < elem.NumField(); i++ { 12 | switch elem.Field(i).Kind() { 13 | case reflect.String, reflect.Int32, reflect.Int64: 14 | fmt.Printf("%v: %v\n", elem.Type().Field(i).Name, elem.Field(i)) 15 | default: 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tools/pdcfg/utils_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type testStruct struct { 8 | aa int 9 | bb string 10 | cc float32 11 | } 12 | 13 | func TestPrintStruct(t *testing.T) { 14 | args := &testStruct{1, "2222", 1.23} 15 | printStruct(args) 16 | } 17 | -------------------------------------------------------------------------------- /tools/pdcfg/vendor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "fmt" 7 | "github.com/PandoCloud/pando-cloud/pkg/models" 8 | "github.com/PandoCloud/pando-cloud/pkg/server" 9 | "os" 10 | "strings" 11 | ) 12 | 13 | func addVendor() error { 14 | args := models.Vendor{} 15 | 16 | reader := bufio.NewReader(os.Stdin) 17 | 18 | fmt.Printf("vendor name: ") 19 | name, err := reader.ReadString('\n') 20 | if err != nil { 21 | return err 22 | } 23 | args.VendorName = strings.Replace(name, "\n", "", -1) 24 | 25 | fmt.Printf("vendor description: ") 26 | desc, err := reader.ReadString('\n') 27 | if err != nil { 28 | return err 29 | } 30 | args.VendorDescription = strings.Replace(desc, "\n", "", -1) 31 | 32 | reply := &models.Vendor{} 33 | 34 | err = server.RPCCallByName("registry", "Registry.SaveVendor", &args, reply) 35 | if err != nil { 36 | return err 37 | } 38 | 39 | fmt.Println("=======> vendor created successfully:") 40 | printStruct(reply) 41 | fmt.Println("=======") 42 | 43 | return nil 44 | } 45 | 46 | func DoVendorCommand(args []string) error { 47 | if len(args) < 1 { 48 | return errors.New("command arguments not enough!") 49 | } 50 | 51 | op := strings.Replace(args[0], "\n", "", -1) 52 | 53 | switch op { 54 | case "add": 55 | if len(args) > 1 { 56 | return errors.New("unnecessary command arguments. just type 'vendor add'") 57 | } 58 | err := addVendor() 59 | if err != nil { 60 | return err 61 | } 62 | default: 63 | return errors.New("operation not suported:" + op) 64 | } 65 | 66 | return nil 67 | } 68 | -------------------------------------------------------------------------------- /unit_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script runs the cover tool on all packages with test files. If you set a 4 | # WEB environment variable, it will additionally open the web-based coverage 5 | # visualizer for each package. 6 | 7 | set -e 8 | 9 | echo 'Please make sure all the core services(redis, mongodb, mysql, etcd) is started before run unit test!!!' 10 | 11 | function go_files { find ./pkg -name '*_test.go' ; } 12 | function filter { grep -v '/_' ; } 13 | function remove_relative_prefix { sed -e 's/^\.\///g' ; } 14 | 15 | function directories { 16 | go_files | filter | remove_relative_prefix | while read f 17 | do 18 | dirname $f 19 | done 20 | } 21 | 22 | function unique_directories { directories | sort | uniq ; } 23 | 24 | PATHS=${1:-$(unique_directories)} 25 | 26 | function report { 27 | for path in $PATHS 28 | do 29 | go test -v -coverprofile=$path/cover.coverprofile ./$path 30 | done 31 | } 32 | 33 | function combine { 34 | gover 35 | } 36 | 37 | function clean { 38 | find . -name cover.coverprofile | xargs rm 39 | } 40 | 41 | report 42 | combine 43 | clean 44 | 45 | if [ -n "${WEB+x}" ] 46 | then 47 | go tool cover -html=gover.coverprofile 48 | fi --------------------------------------------------------------------------------