Full Code of superkkt/cherry for AI

master ea98d7c26dbc cached
698 files
6.1 MB
1.6M tokens
55883 symbols
1 requests
Download .txt
Showing preview only (6,491K chars total). Download the full file or copy to clipboard to get everything.
Repository: superkkt/cherry
Branch: master
Commit: ea98d7c26dbc
Files: 698
Total size: 6.1 MB

Directory structure:
gitextract_s279x8yc/

├── .gitlab-ci.yml
├── Changelog
├── Dockerfile
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── Gopkg.toml
├── LICENSE
├── README.md
├── api/
│   ├── core/
│   │   └── api.go
│   ├── response.go
│   ├── server.go
│   └── ui/
│       ├── api.go
│       ├── category.go
│       ├── component.go
│       ├── group.go
│       ├── host.go
│       ├── ip.go
│       ├── log.go
│       ├── network.go
│       ├── session.go
│       ├── switch.go
│       ├── user.go
│       └── vip.go
├── cmd/
│   ├── cherry/
│   │   ├── cherry.yaml
│   │   └── main.go
│   └── walnut/
│       ├── main.go
│       ├── sdk.go
│       └── walnut.yaml
├── database/
│   ├── mysql.go
│   ├── mysql_schema.sql
│   └── random.go
├── election/
│   └── election.go
├── graph/
│   ├── graph.go
│   └── graph_test.go
├── ldap/
│   ├── client.go
│   └── conn.go
├── log/
│   └── syslog.go
├── network/
│   ├── controller.go
│   ├── device.go
│   ├── error.go
│   ├── flow_cache.go
│   ├── link.go
│   ├── node.go
│   ├── of10_session.go
│   ├── of13_session.go
│   ├── port.go
│   ├── reserve.go
│   ├── reserve_test.go
│   ├── session.go
│   └── topology.go
├── northbound/
│   ├── app/
│   │   ├── announcer/
│   │   │   ├── announcer.go
│   │   │   └── backoff.go
│   │   ├── dhcp/
│   │   │   └── dhcp.go
│   │   ├── discovery/
│   │   │   └── discovery.go
│   │   ├── l2switch/
│   │   │   ├── storm_controller.go
│   │   │   ├── storm_controller_test.go
│   │   │   └── switch.go
│   │   ├── monitor/
│   │   │   ├── monitor.go
│   │   │   └── sendmail.go
│   │   ├── processor.go
│   │   ├── proxyarp/
│   │   │   ├── arp.go
│   │   │   └── error.go
│   │   └── virtualip/
│   │       └── virtualip.go
│   └── manager.go
├── openflow/
│   ├── action.go
│   ├── barrier.go
│   ├── config.go
│   ├── const.go
│   ├── description.go
│   ├── echo.go
│   ├── error.go
│   ├── factory.go
│   ├── features.go
│   ├── flow_mod.go
│   ├── flow_removed.go
│   ├── flow_stats.go
│   ├── hello.go
│   ├── instruction.go
│   ├── match.go
│   ├── message.go
│   ├── of10/
│   │   ├── action.go
│   │   ├── barrier.go
│   │   ├── config.go
│   │   ├── const.go
│   │   ├── description.go
│   │   ├── echo.go
│   │   ├── factory.go
│   │   ├── features.go
│   │   ├── flow_mod.go
│   │   ├── flow_removed.go
│   │   ├── flow_stats.go
│   │   ├── hello.go
│   │   ├── instruction.go
│   │   ├── match.go
│   │   ├── packet_in.go
│   │   ├── packet_out.go
│   │   ├── port.go
│   │   ├── port_status.go
│   │   └── queue.go
│   ├── of13/
│   │   ├── action.go
│   │   ├── barrier.go
│   │   ├── config.go
│   │   ├── const.go
│   │   ├── echo.go
│   │   ├── factory.go
│   │   ├── features.go
│   │   ├── flow_mod.go
│   │   ├── flow_removed.go
│   │   ├── hello.go
│   │   ├── instruction.go
│   │   ├── match.go
│   │   ├── multipart_description.go
│   │   ├── multipart_flow_stats.go
│   │   ├── multipart_port_description.go
│   │   ├── multipart_table_features.go
│   │   ├── packet_in.go
│   │   ├── packet_out.go
│   │   ├── port.go
│   │   ├── port_status.go
│   │   └── queue.go
│   ├── packet_in.go
│   ├── packet_out.go
│   ├── port.go
│   ├── port_description.go
│   ├── port_status.go
│   ├── queue.go
│   ├── table_features.go
│   └── transceiver/
│       ├── stream.go
│       └── transceiver.go
├── protocol/
│   ├── arp.go
│   ├── checksum.go
│   ├── dhcp.go
│   ├── dhcp_test.go
│   ├── ethernet.go
│   ├── icmp.go
│   ├── ipv4.go
│   ├── lldp.go
│   ├── tcp.go
│   └── udp.go
├── vendor/
│   ├── github.com/
│   │   ├── ant0ine/
│   │   │   └── go-json-rest/
│   │   │       ├── LICENSE
│   │   │       └── rest/
│   │   │           ├── access_log_apache.go
│   │   │           ├── access_log_json.go
│   │   │           ├── api.go
│   │   │           ├── auth_basic.go
│   │   │           ├── content_type_checker.go
│   │   │           ├── cors.go
│   │   │           ├── doc.go
│   │   │           ├── gzip.go
│   │   │           ├── if.go
│   │   │           ├── json_indent.go
│   │   │           ├── jsonp.go
│   │   │           ├── middleware.go
│   │   │           ├── powered_by.go
│   │   │           ├── recorder.go
│   │   │           ├── recover.go
│   │   │           ├── request.go
│   │   │           ├── response.go
│   │   │           ├── route.go
│   │   │           ├── router.go
│   │   │           ├── status.go
│   │   │           ├── timer.go
│   │   │           └── trie/
│   │   │               └── impl.go
│   │   ├── boombuler/
│   │   │   └── barcode/
│   │   │       ├── .gitignore
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── barcode.go
│   │   │       ├── qr/
│   │   │       │   ├── alphanumeric.go
│   │   │       │   ├── automatic.go
│   │   │       │   ├── blocks.go
│   │   │       │   ├── encoder.go
│   │   │       │   ├── errorcorrection.go
│   │   │       │   ├── numeric.go
│   │   │       │   ├── qrcode.go
│   │   │       │   ├── unicode.go
│   │   │       │   └── versioninfo.go
│   │   │       ├── scaledbarcode.go
│   │   │       └── utils/
│   │   │           ├── base1dcode.go
│   │   │           ├── bitlist.go
│   │   │           ├── galoisfield.go
│   │   │           ├── gfpoly.go
│   │   │           ├── reedsolomon.go
│   │   │           └── runeint.go
│   │   ├── davecgh/
│   │   │   └── go-spew/
│   │   │       ├── LICENSE
│   │   │       └── spew/
│   │   │           ├── bypass.go
│   │   │           ├── bypasssafe.go
│   │   │           ├── common.go
│   │   │           ├── config.go
│   │   │           ├── doc.go
│   │   │           ├── dump.go
│   │   │           ├── format.go
│   │   │           └── spew.go
│   │   ├── fsnotify/
│   │   │   └── fsnotify/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── AUTHORS
│   │   │       ├── CHANGELOG.md
│   │   │       ├── CONTRIBUTING.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── fen.go
│   │   │       ├── fsnotify.go
│   │   │       ├── inotify.go
│   │   │       ├── inotify_poller.go
│   │   │       ├── kqueue.go
│   │   │       ├── open_mode_bsd.go
│   │   │       ├── open_mode_darwin.go
│   │   │       └── windows.go
│   │   ├── go-sql-driver/
│   │   │   └── mysql/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── AUTHORS
│   │   │       ├── CHANGELOG.md
│   │   │       ├── CONTRIBUTING.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── appengine.go
│   │   │       ├── buffer.go
│   │   │       ├── collations.go
│   │   │       ├── connection.go
│   │   │       ├── connection_go18.go
│   │   │       ├── const.go
│   │   │       ├── driver.go
│   │   │       ├── dsn.go
│   │   │       ├── errors.go
│   │   │       ├── fields.go
│   │   │       ├── infile.go
│   │   │       ├── packets.go
│   │   │       ├── result.go
│   │   │       ├── rows.go
│   │   │       ├── statement.go
│   │   │       ├── transaction.go
│   │   │       ├── utils.go
│   │   │       ├── utils_go17.go
│   │   │       └── utils_go18.go
│   │   ├── google/
│   │   │   └── go-cmp/
│   │   │       ├── LICENSE
│   │   │       └── cmp/
│   │   │           ├── cmpopts/
│   │   │           │   ├── equate.go
│   │   │           │   ├── ignore.go
│   │   │           │   ├── sort.go
│   │   │           │   ├── struct_filter.go
│   │   │           │   └── xform.go
│   │   │           ├── compare.go
│   │   │           ├── export_panic.go
│   │   │           ├── export_unsafe.go
│   │   │           ├── internal/
│   │   │           │   ├── diff/
│   │   │           │   │   ├── debug_disable.go
│   │   │           │   │   ├── debug_enable.go
│   │   │           │   │   └── diff.go
│   │   │           │   ├── flags/
│   │   │           │   │   ├── flags.go
│   │   │           │   │   ├── toolchain_legacy.go
│   │   │           │   │   └── toolchain_recent.go
│   │   │           │   ├── function/
│   │   │           │   │   └── func.go
│   │   │           │   └── value/
│   │   │           │       ├── pointer_purego.go
│   │   │           │       ├── pointer_unsafe.go
│   │   │           │       ├── sort.go
│   │   │           │       └── zero.go
│   │   │           ├── options.go
│   │   │           ├── path.go
│   │   │           ├── report.go
│   │   │           ├── report_compare.go
│   │   │           ├── report_reflect.go
│   │   │           ├── report_slices.go
│   │   │           ├── report_text.go
│   │   │           └── report_value.go
│   │   ├── hashicorp/
│   │   │   ├── golang-lru/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── 2q.go
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   ├── arc.go
│   │   │   │   ├── lru.go
│   │   │   │   └── simplelru/
│   │   │   │       └── lru.go
│   │   │   └── hcl/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── Makefile
│   │   │       ├── README.md
│   │   │       ├── appveyor.yml
│   │   │       ├── decoder.go
│   │   │       ├── hcl/
│   │   │       │   ├── ast/
│   │   │       │   │   ├── ast.go
│   │   │       │   │   └── walk.go
│   │   │       │   ├── parser/
│   │   │       │   │   ├── error.go
│   │   │       │   │   └── parser.go
│   │   │       │   ├── scanner/
│   │   │       │   │   └── scanner.go
│   │   │       │   ├── strconv/
│   │   │       │   │   └── quote.go
│   │   │       │   └── token/
│   │   │       │       ├── position.go
│   │   │       │       └── token.go
│   │   │       ├── hcl.go
│   │   │       ├── json/
│   │   │       │   ├── parser/
│   │   │       │   │   ├── flatten.go
│   │   │       │   │   └── parser.go
│   │   │       │   ├── scanner/
│   │   │       │   │   └── scanner.go
│   │   │       │   └── token/
│   │   │       │       ├── position.go
│   │   │       │       └── token.go
│   │   │       ├── lex.go
│   │   │       └── parse.go
│   │   ├── magiconair/
│   │   │   └── properties/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── CHANGELOG.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── _third_party/
│   │   │       │   └── gopkg.in/
│   │   │       │       └── check.v1/
│   │   │       │           └── LICENSE
│   │   │       ├── decode.go
│   │   │       ├── doc.go
│   │   │       ├── integrate.go
│   │   │       ├── lex.go
│   │   │       ├── load.go
│   │   │       ├── parser.go
│   │   │       ├── properties.go
│   │   │       └── rangecheck.go
│   │   ├── mitchellh/
│   │   │   └── mapstructure/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── decode_hooks.go
│   │   │       ├── error.go
│   │   │       └── mapstructure.go
│   │   ├── pelletier/
│   │   │   ├── go-buffruneio/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── .travis.yml
│   │   │   │   ├── README.md
│   │   │   │   └── buffruneio.go
│   │   │   └── go-toml/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── clean.sh
│   │   │       ├── doc.go
│   │   │       ├── example-crlf.toml
│   │   │       ├── example.toml
│   │   │       ├── keysparsing.go
│   │   │       ├── lexer.go
│   │   │       ├── match.go
│   │   │       ├── parser.go
│   │   │       ├── position.go
│   │   │       ├── query.go
│   │   │       ├── querylexer.go
│   │   │       ├── queryparser.go
│   │   │       ├── test.sh
│   │   │       ├── token.go
│   │   │       ├── toml.go
│   │   │       └── tomltree_conversions.go
│   │   ├── pkg/
│   │   │   └── errors/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── appveyor.yml
│   │   │       ├── errors.go
│   │   │       └── stack.go
│   │   ├── pquerna/
│   │   │   └── otp/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── NOTICE
│   │   │       ├── README.md
│   │   │       ├── doc.go
│   │   │       ├── hotp/
│   │   │       │   └── hotp.go
│   │   │       ├── otp.go
│   │   │       └── totp/
│   │   │           └── totp.go
│   │   ├── spf13/
│   │   │   ├── afero/
│   │   │   │   ├── .travis.yml
│   │   │   │   ├── LICENSE.txt
│   │   │   │   ├── README.md
│   │   │   │   ├── afero.go
│   │   │   │   ├── appveyor.yml
│   │   │   │   ├── basepath.go
│   │   │   │   ├── cacheOnReadFs.go
│   │   │   │   ├── const_bsds.go
│   │   │   │   ├── const_win_unix.go
│   │   │   │   ├── copyOnWriteFs.go
│   │   │   │   ├── httpFs.go
│   │   │   │   ├── ioutil.go
│   │   │   │   ├── mem/
│   │   │   │   │   ├── dir.go
│   │   │   │   │   ├── dirmap.go
│   │   │   │   │   └── file.go
│   │   │   │   ├── memmap.go
│   │   │   │   ├── memradix.go
│   │   │   │   ├── os.go
│   │   │   │   ├── path.go
│   │   │   │   ├── readonlyfs.go
│   │   │   │   ├── regexpfs.go
│   │   │   │   ├── unionFile.go
│   │   │   │   └── util.go
│   │   │   ├── cast/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   ├── cast.go
│   │   │   │   └── caste.go
│   │   │   ├── jwalterweatherman/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   └── thatswhyyoualwaysleaveanote.go
│   │   │   └── pflag/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── bool.go
│   │   │       ├── count.go
│   │   │       ├── duration.go
│   │   │       ├── flag.go
│   │   │       ├── float32.go
│   │   │       ├── float64.go
│   │   │       ├── golangflag.go
│   │   │       ├── int.go
│   │   │       ├── int32.go
│   │   │       ├── int64.go
│   │   │       ├── int8.go
│   │   │       ├── int_slice.go
│   │   │       ├── ip.go
│   │   │       ├── ipmask.go
│   │   │       ├── ipnet.go
│   │   │       ├── string.go
│   │   │       ├── string_slice.go
│   │   │       ├── uint.go
│   │   │       ├── uint16.go
│   │   │       ├── uint32.go
│   │   │       ├── uint64.go
│   │   │       └── uint8.go
│   │   └── superkkt/
│   │       ├── go-logging/
│   │       │   ├── .travis.yml
│   │       │   ├── CHANGELOG.md
│   │       │   ├── CONTRIBUTORS
│   │       │   ├── LICENSE
│   │       │   ├── README.md
│   │       │   ├── backend.go
│   │       │   ├── format.go
│   │       │   ├── level.go
│   │       │   ├── log_nix.go
│   │       │   ├── log_windows.go
│   │       │   ├── logger.go
│   │       │   ├── memory.go
│   │       │   ├── multi.go
│   │       │   ├── syslog.go
│   │       │   └── syslog_fallback.go
│   │       └── viper/
│   │           ├── .gitignore
│   │           ├── .travis.yml
│   │           ├── LICENSE
│   │           ├── README.md
│   │           ├── flags.go
│   │           ├── nohup.out
│   │           ├── util.go
│   │           └── viper.go
│   ├── golang.org/
│   │   └── x/
│   │       ├── sys/
│   │       │   ├── AUTHORS
│   │       │   ├── CONTRIBUTORS
│   │       │   ├── LICENSE
│   │       │   ├── PATENTS
│   │       │   └── unix/
│   │       │       ├── .gitignore
│   │       │       ├── asm.s
│   │       │       ├── asm_darwin_386.s
│   │       │       ├── asm_darwin_amd64.s
│   │       │       ├── asm_darwin_arm.s
│   │       │       ├── asm_darwin_arm64.s
│   │       │       ├── asm_dragonfly_amd64.s
│   │       │       ├── asm_freebsd_386.s
│   │       │       ├── asm_freebsd_amd64.s
│   │       │       ├── asm_freebsd_arm.s
│   │       │       ├── asm_linux_386.s
│   │       │       ├── asm_linux_amd64.s
│   │       │       ├── asm_linux_arm.s
│   │       │       ├── asm_linux_arm64.s
│   │       │       ├── asm_linux_mips64x.s
│   │       │       ├── asm_linux_ppc64x.s
│   │       │       ├── asm_linux_s390x.s
│   │       │       ├── asm_netbsd_386.s
│   │       │       ├── asm_netbsd_amd64.s
│   │       │       ├── asm_netbsd_arm.s
│   │       │       ├── asm_openbsd_386.s
│   │       │       ├── asm_openbsd_amd64.s
│   │       │       ├── asm_solaris_amd64.s
│   │       │       ├── bluetooth_linux.go
│   │       │       ├── constants.go
│   │       │       ├── env_unix.go
│   │       │       ├── env_unset.go
│   │       │       ├── flock.go
│   │       │       ├── flock_linux_32bit.go
│   │       │       ├── gccgo.go
│   │       │       ├── gccgo_c.c
│   │       │       ├── gccgo_linux_amd64.go
│   │       │       ├── mkall.sh
│   │       │       ├── mkerrors.sh
│   │       │       ├── mkpost.go
│   │       │       ├── mksyscall.pl
│   │       │       ├── mksyscall_solaris.pl
│   │       │       ├── mksysctl_openbsd.pl
│   │       │       ├── mksysnum_darwin.pl
│   │       │       ├── mksysnum_dragonfly.pl
│   │       │       ├── mksysnum_freebsd.pl
│   │       │       ├── mksysnum_linux.pl
│   │       │       ├── mksysnum_netbsd.pl
│   │       │       ├── mksysnum_openbsd.pl
│   │       │       ├── race.go
│   │       │       ├── race0.go
│   │       │       ├── sockcmsg_linux.go
│   │       │       ├── sockcmsg_unix.go
│   │       │       ├── str.go
│   │       │       ├── syscall.go
│   │       │       ├── syscall_bsd.go
│   │       │       ├── syscall_darwin.go
│   │       │       ├── syscall_darwin_386.go
│   │       │       ├── syscall_darwin_amd64.go
│   │       │       ├── syscall_darwin_arm.go
│   │       │       ├── syscall_darwin_arm64.go
│   │       │       ├── syscall_dragonfly.go
│   │       │       ├── syscall_dragonfly_amd64.go
│   │       │       ├── syscall_freebsd.go
│   │       │       ├── syscall_freebsd_386.go
│   │       │       ├── syscall_freebsd_amd64.go
│   │       │       ├── syscall_freebsd_arm.go
│   │       │       ├── syscall_linux.go
│   │       │       ├── syscall_linux_386.go
│   │       │       ├── syscall_linux_amd64.go
│   │       │       ├── syscall_linux_arm.go
│   │       │       ├── syscall_linux_arm64.go
│   │       │       ├── syscall_linux_mips64x.go
│   │       │       ├── syscall_linux_ppc64x.go
│   │       │       ├── syscall_linux_s390x.go
│   │       │       ├── syscall_netbsd.go
│   │       │       ├── syscall_netbsd_386.go
│   │       │       ├── syscall_netbsd_amd64.go
│   │       │       ├── syscall_netbsd_arm.go
│   │       │       ├── syscall_no_getwd.go
│   │       │       ├── syscall_openbsd.go
│   │       │       ├── syscall_openbsd_386.go
│   │       │       ├── syscall_openbsd_amd64.go
│   │       │       ├── syscall_solaris.go
│   │       │       ├── syscall_solaris_amd64.go
│   │       │       ├── syscall_unix.go
│   │       │       ├── types_darwin.go
│   │       │       ├── types_dragonfly.go
│   │       │       ├── types_freebsd.go
│   │       │       ├── types_linux.go
│   │       │       ├── types_netbsd.go
│   │       │       ├── types_openbsd.go
│   │       │       ├── types_solaris.go
│   │       │       ├── zerrors_darwin_386.go
│   │       │       ├── zerrors_darwin_amd64.go
│   │       │       ├── zerrors_darwin_arm.go
│   │       │       ├── zerrors_darwin_arm64.go
│   │       │       ├── zerrors_dragonfly_amd64.go
│   │       │       ├── zerrors_freebsd_386.go
│   │       │       ├── zerrors_freebsd_amd64.go
│   │       │       ├── zerrors_freebsd_arm.go
│   │       │       ├── zerrors_linux_386.go
│   │       │       ├── zerrors_linux_amd64.go
│   │       │       ├── zerrors_linux_arm.go
│   │       │       ├── zerrors_linux_arm64.go
│   │       │       ├── zerrors_linux_mips64.go
│   │       │       ├── zerrors_linux_mips64le.go
│   │       │       ├── zerrors_linux_ppc64.go
│   │       │       ├── zerrors_linux_ppc64le.go
│   │       │       ├── zerrors_linux_s390x.go
│   │       │       ├── zerrors_netbsd_386.go
│   │       │       ├── zerrors_netbsd_amd64.go
│   │       │       ├── zerrors_netbsd_arm.go
│   │       │       ├── zerrors_openbsd_386.go
│   │       │       ├── zerrors_openbsd_amd64.go
│   │       │       ├── zerrors_solaris_amd64.go
│   │       │       ├── zsyscall_darwin_386.go
│   │       │       ├── zsyscall_darwin_amd64.go
│   │       │       ├── zsyscall_darwin_arm.go
│   │       │       ├── zsyscall_darwin_arm64.go
│   │       │       ├── zsyscall_dragonfly_amd64.go
│   │       │       ├── zsyscall_freebsd_386.go
│   │       │       ├── zsyscall_freebsd_amd64.go
│   │       │       ├── zsyscall_freebsd_arm.go
│   │       │       ├── zsyscall_linux_386.go
│   │       │       ├── zsyscall_linux_amd64.go
│   │       │       ├── zsyscall_linux_arm.go
│   │       │       ├── zsyscall_linux_arm64.go
│   │       │       ├── zsyscall_linux_mips64.go
│   │       │       ├── zsyscall_linux_mips64le.go
│   │       │       ├── zsyscall_linux_ppc64.go
│   │       │       ├── zsyscall_linux_ppc64le.go
│   │       │       ├── zsyscall_linux_s390x.go
│   │       │       ├── zsyscall_netbsd_386.go
│   │       │       ├── zsyscall_netbsd_amd64.go
│   │       │       ├── zsyscall_netbsd_arm.go
│   │       │       ├── zsyscall_openbsd_386.go
│   │       │       ├── zsyscall_openbsd_amd64.go
│   │       │       ├── zsyscall_solaris_amd64.go
│   │       │       ├── zsysctl_openbsd.go
│   │       │       ├── zsysnum_darwin_386.go
│   │       │       ├── zsysnum_darwin_amd64.go
│   │       │       ├── zsysnum_darwin_arm.go
│   │       │       ├── zsysnum_darwin_arm64.go
│   │       │       ├── zsysnum_dragonfly_amd64.go
│   │       │       ├── zsysnum_freebsd_386.go
│   │       │       ├── zsysnum_freebsd_amd64.go
│   │       │       ├── zsysnum_freebsd_arm.go
│   │       │       ├── zsysnum_linux_386.go
│   │       │       ├── zsysnum_linux_amd64.go
│   │       │       ├── zsysnum_linux_arm.go
│   │       │       ├── zsysnum_linux_arm64.go
│   │       │       ├── zsysnum_linux_mips64.go
│   │       │       ├── zsysnum_linux_mips64le.go
│   │       │       ├── zsysnum_linux_ppc64.go
│   │       │       ├── zsysnum_linux_ppc64le.go
│   │       │       ├── zsysnum_linux_s390x.go
│   │       │       ├── zsysnum_netbsd_386.go
│   │       │       ├── zsysnum_netbsd_amd64.go
│   │       │       ├── zsysnum_netbsd_arm.go
│   │       │       ├── zsysnum_openbsd_386.go
│   │       │       ├── zsysnum_openbsd_amd64.go
│   │       │       ├── zsysnum_solaris_amd64.go
│   │       │       ├── ztypes_darwin_386.go
│   │       │       ├── ztypes_darwin_amd64.go
│   │       │       ├── ztypes_darwin_arm.go
│   │       │       ├── ztypes_darwin_arm64.go
│   │       │       ├── ztypes_dragonfly_amd64.go
│   │       │       ├── ztypes_freebsd_386.go
│   │       │       ├── ztypes_freebsd_amd64.go
│   │       │       ├── ztypes_freebsd_arm.go
│   │       │       ├── ztypes_linux_386.go
│   │       │       ├── ztypes_linux_amd64.go
│   │       │       ├── ztypes_linux_arm.go
│   │       │       ├── ztypes_linux_arm64.go
│   │       │       ├── ztypes_linux_mips64.go
│   │       │       ├── ztypes_linux_mips64le.go
│   │       │       ├── ztypes_linux_ppc64.go
│   │       │       ├── ztypes_linux_ppc64le.go
│   │       │       ├── ztypes_linux_s390x.go
│   │       │       ├── ztypes_netbsd_386.go
│   │       │       ├── ztypes_netbsd_amd64.go
│   │       │       ├── ztypes_netbsd_arm.go
│   │       │       ├── ztypes_openbsd_386.go
│   │       │       ├── ztypes_openbsd_amd64.go
│   │       │       └── ztypes_solaris_amd64.go
│   │       └── text/
│   │           ├── AUTHORS
│   │           ├── CONTRIBUTORS
│   │           ├── LICENSE
│   │           ├── PATENTS
│   │           ├── internal/
│   │           │   ├── gen/
│   │           │   │   ├── code.go
│   │           │   │   └── gen.go
│   │           │   ├── triegen/
│   │           │   │   ├── compact.go
│   │           │   │   ├── print.go
│   │           │   │   └── triegen.go
│   │           │   └── ucd/
│   │           │       └── ucd.go
│   │           ├── transform/
│   │           │   └── transform.go
│   │           └── unicode/
│   │               ├── cldr/
│   │               │   ├── base.go
│   │               │   ├── cldr.go
│   │               │   ├── collate.go
│   │               │   ├── decode.go
│   │               │   ├── makexml.go
│   │               │   ├── resolve.go
│   │               │   ├── slice.go
│   │               │   └── xml.go
│   │               └── norm/
│   │                   ├── composition.go
│   │                   ├── forminfo.go
│   │                   ├── input.go
│   │                   ├── iter.go
│   │                   ├── maketables.go
│   │                   ├── normalize.go
│   │                   ├── readwriter.go
│   │                   ├── tables.go
│   │                   ├── transform.go
│   │                   ├── trie.go
│   │                   └── triegen.go
│   ├── google.golang.org/
│   │   └── appengine/
│   │       ├── LICENSE
│   │       └── cloudsql/
│   │           ├── cloudsql.go
│   │           ├── cloudsql_classic.go
│   │           └── cloudsql_vm.go
│   └── gopkg.in/
│       ├── asn1-ber.v1/
│       │   ├── .travis.yml
│       │   ├── LICENSE
│       │   ├── README.md
│       │   ├── ber.go
│       │   ├── content_int.go
│       │   ├── header.go
│       │   ├── identifier.go
│       │   ├── length.go
│       │   └── util.go
│       ├── ldap.v3/
│       │   ├── .gitignore
│       │   ├── .travis.yml
│       │   ├── CONTRIBUTING.md
│       │   ├── LICENSE
│       │   ├── Makefile
│       │   ├── README.md
│       │   ├── add.go
│       │   ├── bind.go
│       │   ├── client.go
│       │   ├── compare.go
│       │   ├── conn.go
│       │   ├── control.go
│       │   ├── debug.go
│       │   ├── del.go
│       │   ├── dn.go
│       │   ├── doc.go
│       │   ├── error.go
│       │   ├── filter.go
│       │   ├── ldap.go
│       │   ├── moddn.go
│       │   ├── modify.go
│       │   ├── passwdmodify.go
│       │   └── search.go
│       └── yaml.v2/
│           ├── .travis.yml
│           ├── LICENSE
│           ├── LICENSE.libyaml
│           ├── README.md
│           ├── apic.go
│           ├── decode.go
│           ├── emitterc.go
│           ├── encode.go
│           ├── parserc.go
│           ├── readerc.go
│           ├── resolve.go
│           ├── scannerc.go
│           ├── sorter.go
│           ├── writerc.go
│           ├── yaml.go
│           ├── yamlh.go
│           └── yamlprivateh.go
└── version.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitlab-ci.yml
================================================
image: golang:1.12

before_script:
  - mkdir -p /go/src/github.com/superkkt
  - cp -rp /builds/superkkt/cherry /go/src/github.com/superkkt
    
stages:
  - build
  - test

build_all:
  stage: build
  script:
    - cd /go/src/github.com/superkkt/cherry
    - go build $(go list ./... | grep -v /vendor/)

test_all:
  stage: test
  script:
    - cd /go/src/github.com/superkkt/cherry
    - go test $(go list ./... | grep -v /vendor/)

================================================
FILE: Changelog
================================================
* v0.14.2 (2019-09-20)

3faead4 Fix the unexpected master change (See #44)

* v0.14.1 (2019-09-03)

b321987 Remove password plain text log (See #43)

* v0.14.0 (2019-08-02)

fad9247 Change ui server middleware order (See #42)
e02444b Change name of host table timestamp column (See #41)
7ee607a Revert "Set hard-timeout to clear stale flows"
71199c6 Change data column type in log table (See #38)
3b8fe3e Apply LDAP (See #31)
715f48f Change validation of input length (See #36)
6a81a12 Change timestamp column option in host table (See #37)
9cf45b8 Apply TOTP (See #30)
6f28b01 Prevent gateway from being set as reserved IP (See #35)
4faeba4 Change host update API (See #26)
efaab76 Change IP structure (See #27)
8f0eb70 Add get host API (See #34)
040d871 Add gateway within network (See #25)
501c3d3 Add network search (See #24)
8740e05 Add spec feature within host (See #29)
2e8ed92 Add Component UI API (See #28)
3f301a2 Add Category UI API (See #23)
80606bb Add Log UI API (See #18)
519ecce Fix a bug to add an invalid IP address to the database when adding a network (See #33)
c4c6fdf NULL MAC address to disconnect a host from the network (See #32)
3504fd6 Dedicated IP address for ARP host discovery (See #12)
cb92e4a Use reserved IP addresses (TEST-NET-1) for DHCP and ARP discovery
79d95da Validate TCP and UDP packet lengths
a5415ba Fix the broken UDP checksum
6ce8b01 Implement a DHCP server
c01b487 refactoring: apply the custom response writer to the UI API
cf82a97 revise
abf5e1a refactoring: apply pagination with structure
fbf94f0 refactoring: ui transaction returns instance reference
936f21d Add Host List API (See #20)
74ff82e fix add, update host
9e013c9 refactoring: call database logics in a closure
b9b85d4 refactoring: apply the custom response writer to the core API
726f009 refactoring: custom response writer with logging
58362ed Add Host UI API (See #20)
c31fdaa Add VIP UI API (See #19)
a13a7dc Refactoring: re-organize the source tree structure of the API package
5667f06 Add Switch UI API (See #14)
0090f4b Add Network UI API (See #15)
1729ffa Add Host group UI API (See #17)
4e4188f Add User UI API (See #16)
b10bfa7 Add extra comment for time interval of the flow manager
a4aaac9 Set hard-timeout to clear stale flows
0c939a7 ARP announcer (See #22)
cd32572 Devide UI API server (See #13)
9af1b5b Fix the broken test case
e2e8add Replace godep with dep to vendor libraries
9cddf5f Add extra debug logs for broadcast packets
b1e6584 Update the buffered socket stream to avoid a potential internal buffer corruption
ef776e5 Add the GitLab CI
f4f235f Fix a typo
1fa1d05 Fix broken test cases
146b172 Fix the IP conflict by ARP probes (See #12)

* v0.13.5 (2018-05-15)

06fe675 Discovery: workaround for old OSes that have a broken TCP/IP stack (See #6)

* v0.13.4 (2018-04-22)

4767d4c Fix the node discovery bug (See #5)

* v0.13.3 (2018-04-22)

619eefc Revert "Decrease the PACKET_IN read buffer size"

* v0.13.2 (2018-04-20)

05f3fc0 Adjust log levels
412988e Use string parameters in the YAML config file
1114081 MySQL: validate the cluster address
fe7f912 Update the MySQL driver
c3b6288 mysql: new cluster dialer and query function that pass Tx instead of DB
a760e5e Ignore the WRITE fsnotify operation to avoid reading empty config
d4d48f7 Increase the flow idle timeout
df3e5ed Make a switch drops all incoming packets (except ARP and LLDP) for a while on start up
0bfdb5b Sort networks by address
3809a8c Re-ordering DB tables in the MySQL schema
9eb8066 Decrease the ARP probe interval
480d6b5 Fix missing time interval change
7cfdccb Decrease the flow manager interval
6f8780c Add extra comments
151ab37 Decrease the device explorer interval to 1 minute
0e11b0d Update a debug message
1fc910c Decrease ARP sender's loop interval to 1.5 sec.
5472f62 Add a comment for time buffering
750627a Drop the some PACKET_INs for proper device setup on start up
0670200 Drop the packets before ethernet parsing if the device is not yet ready
e7d0e91 Decrease ARP sender's loop interval
3f3fbc3 Send ARP probes immediately on start up for fast discovery
a77d304 Fix aaa0e4fd797 as OF1.0 does not support the cookie mask
5ade735 Deny the API request if we are not the master controller
5e2633e Keep the ARP flow unless the switch device reconnects
aaa0e4f Flow cache to avoid duplicate and repeated flow installation (See #1)
f8bb64f Minor refactoring
109e393 Refactoring of the switch device negotiation procedure
c527c28 Add extra debug messages
e8d4b50 Decrease the timeout for a staled host
6d42974 Decrease the PACKET_IN read buffer size
78f098a Use FLOW_ADD instead of FLOW_MODIFY for a broken switch device (i.e., Dell S3148) (See #1)
7770802 Log DPID when we get an openflow error packet
018b460 Ignore the invalid echo responses

* v0.13.1 (Sat Aug 05 16:45:00 2017 +0900)

075e31c Ignore the ARP reply received from an edge among switches

* v0.13.0 (Fri Aug 04 23:37:48 2017 +0900)

fe412ce Remove duplicated link down check
5bfbf68 Decrease the flow manager interval to 1 minute
0130939 Flow manager to keep the flows update
b92618c Fix the deadlock between the topology and the device
698ce6a Minor refactoring
7a88c77 Set idle and hard flow timeouts from the config
ae4e791 Log flow removed timestamp
13ba29f Remove all the flow histories on the device down event
fd8b1a4 Warning log on the port down event
72b66c2 Backoff-delayed ARP announcer for all the registered hosts
fbc8759 Backoff-delayed ARP announcer
0509b0c Invalidate the ARP caches when a host is removed
9d0500e Fix the broken VIP toggling by repeated toggles in a moment
d468086 Minor refactoring of README
f7cee84 Update README for the new configuration file
ae3ee97 Fix the broken VIP toggling by the Discovery module
ad5b2d9 Revert a weird patch 601ac8055
ce25c01 Minor refactoring by function renaming
daaeaed Log switch device up/down events
a34bdce Fix the broken Dockerfile
ee8f7a4 Flow history on the database
e46bce5 Adjust switch port numbers based on its first printed port number
b8eb6e9 Dynamic config reloading
0a3a53f Increase log level of toggling VIP addresses
5841fd6 Remove the old Golang X Context package
9c62ce2 Fix the unintended package import
a014cee Adjust log message level
38bbac7 Implement automatic master election
0be0c21 New host stale field instead of its UNIX timestamp
584e230 Minor refactoring
31e2491 Adjust loop intervals
4acb3e3 Remove useless comment
a5b152e Periodic switch port scanning
bef4a14 Minor refactoring for the device expolorer interval
aee62af Periodically send LLDPs to keep the network topology updated
a730b7e Dynamic discovery of physical host locations using the ARP probe
67911b1 Fix unexpected foreign key error from deleting a network address
bba56c1 Add debug messages for ECHO_REQUEST and ECHO_REPLY packets
e0b7e53 Decrease the capacity of the reader channel

* v0.12.1 (Wed Aug 31 15:06:31 2016 +0900)

3d35bfb Log the number of unread remaining packets in the reader channel
e1cfa8b Ignore soft errors from OpenFlow EchoReply
6d6e729 Fix the incorrect log levels of the config file

* v0.12.0 (Sun Aug 28 18:57:08 2016 +0900)

46a636c Fix the bug caused by unnecessary protocol vercion checking
e40cda8 Run the packet reader thread in the OpenFlow transceiver
6a16954 Rename the openflow/trans package to openflow/transceiver
14fd96d Replace the custom logger with the go-logging library
b5ca266 Reorganize the package structure
9f48eb6 Adopt a temporary error to ignore soft errors
b522598 Vendoring by Godeps
a107e1f Do not support multiple DB hosts and set the wait_time MySQL variable to 120s

* v0.11.0 (Mon Jun 6 15:42:29 2016 +0900)

4599801 (HEAD, tag: v0.11.0, origin/v0.11, origin/master, origin/HEAD, v0.11, master) Bump version to 0.11.0
601ac80 Fix the duplicated DPID by disconnecting the previous main connection (see #8313)
2cb100e Vendoring all libraries
21b7e2f Update Changelog and LICENSE
4797aa3 Change version to 0.11-RC3
6700906 Send the alarm email asynchronously (see #6547)
c21420a Change version to 0.11-RC2
25ac489 Enable the monitor app (see #6547)
f26e497 Change version to 0.11-RC
29f152a Implement notification when a device is up and down (see #6547)

* v0.10.0 (Sat Oct 24 17:57:16 2015 +0900)

18fb269 (tag: v0.10.0, origin/v0.10) Change version to 0.10-RC
87b02be Implement a broadcast storm controller (see #6534)
59c98c0 Add version flag

* v0.9.1 (Tue Oct 20 22:28:58 2015 +0900)

9a00866 (tag: v0.9.1, origin/v0.9) Implement a flow cache to avoid duplicated flow installation
4299780 Remove hard timeout of a L2 switch's flow
07ee1e2 Add the version flag

* v0.9.0 (Fri Oct 9 00:34:00 2015 +0900)

35a345c (tag: v0.9.0) Update README.md
1650f6a Update README.md
3310bcc Add Changelog
2933299 Add origin header
3ee079f Improve VIP toggling logs
d305027 Remove useless modules
b66bcb3 Remove foreign key delete cascade as MySQL does not call triggers on the cascding
e471dbc Implement manual toggle VIP active/standby hosts (see #6109)
38f8be4 Drop useless removing flows when removeVIP API is called
211df46 Add VIP toggle log messages
a2ea75e Fix incorrect query string
4f383e3 Add VIPParam validation
db7db86 Minor refactoring
d24b64d Implement floating virtual IP (see #6109)
34c7956 Improve MAC address handling of the REST module
e0eaced Fix incorrect IP and MAC parser and add log messages
7c762a2 Fix decoding MAC address routine that results in panic
5ef7ab8 Implement host list, add, and remove REST APIs
c2a5f0f Refactoring of REST APIs
2aa69f3 Implement network list, add, and delete APIs via REST
66469a1 Change default REST port number from 8080 to 7070
06b7fad Implement switch list, add, and delete APIs via REST
91b9b28 Do not return error if we cannot find a neighbor device or its port to avoid unexpected device disconnection
a82d8df Send barrier reqeust after setting ARP sender flow
1a88dd4 Remove incorrect log message of ProxyARP
4d42ee8 Improve ARP announcement checker
6c732c3 Allow database connection error if there is at least one avaliable server on the database pool (see #6236)
22e6838 Log malicious ARP packet whose ethernet destination MAC is not the broadcast address
1570025 Refactoring ARP sender flow routines
f82246b Add a permanent flow for ARP packets to forward them to the controller
545625b Improve DB index
259e06d Improve DB indices
4a81851 Fix incorrect unique keys of host DB table
5558f15 Make DB DELETE to be cascaded
b03ea16 Add host description field to the database schema
4d7fcbf Implement multiple database connections (see #6115)
b44a7b6 Check ARP announcement before ARP operation (see #6109)
0ba70d7 Drop ARP announcement packets (see #6109)
3d31799 Fix typo
ac588a8 Implement ARP packet description
ceb047a Remove useless assigning of return values (see #6104)
c7935d6 Implement MySQL deadlock protection (see #6104)
4959db7 Add OFPFF_CHECK_OVERLAP flag to FLOW_MOD (see #6108)
1037c73 Change host DB table schema
253cf47 Remove flows when port down event is detected (see #6108)
90da465 Implement fixed host location (see #6103)
3827e3d Clear all learned MAC addresses when the topology is updated (see #6102)
d5e0bde Fix incorrect Deadline interface
0832255 Remove ARP announcement routines from the ProxyARP module
691a2db Remove the router module
9676380 Implement VLAN ID of the OpenFlow action
94dd8e6 Add the router module
fd3eb21 Implement per-device host database in the topology
9ac9595 Remove the router northbound application
ecd84f5 Implement InPort output action
136ee97 Fix missing IP ToS wildcard
6ced806 Fix incorrect IPv4 address handling
7961ab5 Implement SetEnqueue for QoS in the router application (see #5950)
cf3eef5 Implement QueueGetConfigRequest (see #5950)
2844e19 Checks northbound applications' dependencies among them (see #6001)
d2613f6 Minor typo changes
eafc9b1 Remove useless comments
299f581 Remove OnFlowRemoved callback handler from northbound applications
4863b61 Change OF action's output type from map to slice
dbab7c4 Drop an incoming packet heading to a private address
e49fb98 Add SIGHUP handler to northbound applications and extra debugging messages
2bf9592 Drop an incoming packet heading to link-local address
05db1b0 Add extra debugging messages
9c42639 Fix missing flow reverse
10df6b1 Add verbose debugging messages
ba0ed3e Implement HUP signal handler to show current daemon status (see #5974)
386fa87 Refactoring of Dockerfile and entrypoint script
240ad0a Update README.md
7858b41 Update README.md
1ac3427 Update README.md
e708323 Update README.md
a389236 Update README.md
eaf16e0 Update README.md
5412891 Remove MySQL from Dockerfile
8b733aa Remove SIGHUP from the Docker entrypoint script
d536fa5 Update README.md
3eb59ea Update README.md
8c5308c Update README.md
7473a51 Update README.md
3d25588 Update README.md
3e94b80 Add Dockerfile
cbdbe46 Remove internal prefixes of import paths
da3f8c1 Implement ICMP echo reply
9225b3c Update README.md
062645b Change MAC address type of the database schema
529b1aa Separate database module
65aea0a Preventing IP spoofing
9e9d0a7 Preventing IP spoofing

* v0.8.0 (Thu Jul 2 23:43:09 2015 +0900)

d42c3d5 Router's outgoing packet handler (see #5084)
548de57 Router's incoming packet handler (see #5084)
593060b Update README.md
d730618 Update README.md
d19a1fc Update copyright
b4ccf88 Update copyright
43eaee1 Update README.md
3cc461f Implement custom log writer that supports log level filter
9ce0b7f Update README.md
5321096 Update README.md
c281b64 Update README.md
1cbdc63 Move the LICENSE file
7af5145 Create README.md
24d6324 Default config to use only L2Switch
6568a71 Replace git.sds.co.kr with github.com
f6550bd Add GPLv2 License
bd771ee Fix duplicated packet problem
a85ec70 Implement ProxyARP application (see #5084)
ae8751c Minor refactoring
9e4d7a4 Implement network event listener (see #5084)
e7be8db Getting OpenFlow factory from a device and cleanup flows when a device is disconnected (see #5084)
6369c0d Refactoring of the L2 switch application (see #5634)
ccf4648 Implement north-bound L2 switch applicaion (#5634)
797986b Implement north-bound application layout (see #5634)
8039ed5 Implement path finding (see #5634)
2d9ac36 Implement LLDP timer (see #5634)
96638bd Remove debugging messages
920a429 Refactoring package structure (see #5634)
ff0c33a Remove comment out for testing
7b30eb0 Refactoring auxiliary connections (see #5634)
c004856 Refactoring network packages (see #5634)
c97a99b Refactoring of the controller package (see #5634)
f6624bf Change the number of goroutines that can be executed simultaneously
4d9434b Refactoring of the OpenFlow package (see #5634)
c63ed26 Fix host DB consistency (see #5510)
6a55b26 Implement ARP announcement (see #5084)
3b8c0d5 Implement event listener (see #5084)
b8e7c93 Implement event listener (see #5084)
4963470 Remove L3 switch application (see #5084)
2c32400 Implement ProxyARP (see #5084)
b71e288 Change package name of device to controller
079cda9 Minor refactoring
89af5b1 Use both hardware and software flow tables of HP-2920G (see #5084)
46c62ea Minor refactoring
008630c Split L2 and L3 switches (see #5084)
31ccf27 Implement configuration of plugin applications (see #5084)
0490fba Implement UDP protocol (see #5454)
b2cdd8a Implement TCP protocol (see #5454)
bf85523 Fix incorrect netmask on the flow rule of L2 MAC learning switch (see #5453)
e67d097 Improve switch compatibilities (see #5453)
bf8ebff Minor refactoring of VirtualRouter
82f9db8 Add ethernet parsing routine for a IEEE 802.1Q-tagged frame (see #5454)
f8dbd02 Implment ICMP Echo protocol (see #5454)
4ccac40 Implement IPv4 protocol (see #5454)
2229248 Implement ARP protocol (see #5454)
8675846 Implement L2 switch application on OF1.0 (see #5388)
0dfcdf0 Fix abnormal broadcast when src and dst nodes are on a same switch (see #5448)
8b26a71 Fix duplicated packet problem (see #5447)
40e16f9 Implement custom routines for HP-2920 (see #5388)
0df3f20 Implement a packet processor (see #5388)
19e5e85 Implement a L2 MAC learning switch module (see #5388)
90b40da Fix port modification bugs (see #5086)
0b85e51 Fix abnormal broadcast storm (see #5086)
ee7c554 Implement L2 switch application on OF1.3 (see #5388)
2c20909 Minor refactoring (see #5086)
3933699 Remove comments
b8aa530 Implement Kruskal's algorithm (see #5086)
525f8c2 Implement Breadth-First Search (see #5086)
1b801b6 Minor refactoring
371a960 Minor fix for removing edge and vertex (see #5086)
82a6fc3 Implement minimum spanning tree using Prim's algorithm (see #5086)
dbabb82 Implement Ethernet & LLDP protocols (see #5086)
70988f7 Rollback to do not remove all flow entries when a switch connects (see #5083)
28dbc7c Fix incorrect data offset of PACKET_IN (see #5083)
46b3142 Implement port modification (see #5083)
4556131 Implement PACKET_IN (see #5083)
6700855 Add comments about switch characteristics (see #0)
68fb0e3 Implement flow_removed and packet_out message (see #5083)
a97c74e Implement flow_removed and packet_out message (see #5083)
beedd9f Add interfaces to install a flow rule (see #5083)
beb0090 Implement flow_mod (see #5083)
959f590 Implement flow action (see #5083)
c17b009 Refactoring of openflow.Message (see #5083)
6007efb Implement flow match (see #5083)
33c3ba0 Implement port status message (see #5083)
f2332d8 Add packet length validation for FeaturesReply (see #0)
76ea7fe Refactoring of error message (see #5083)
c027ba4 Implement error message (see #5083)
d05648f Implement port description (see #5083)
7144add minor refactoring (see #0)
954fbbf minor refactoring (see #0)
2172a5a Implement switch descriptions (see #5083)
fcd4c87 Implement switch configuration messages (see #5083)
0660110 Implement device pool (see #5083)
d2f8346 Split common routines OF10 and OF13 transceivers (see #5083)
6a15233 Implement a baseline for OF10 and OF13 protocols (see #5083)
c99c940 Minor refactoring (see #0)
b135795 Minor refactoring (see #0)
4234069 Refactoring for auxiliary connections (see #5083)
0c7c0ff Use map for switch ports information instead of slice (see #0)
32a3684 Minor refactoring (see #0)
d781a30 Refactoring hello phase (see #0)
7a587d4 Implement port modification message (see #5087)
c0fad5e Add atomic increment of transaction ID for concurrent usage (see #0)
6569ffd Implement barrier request and reply (see #5082)
5b5d356 Implement switch configs (see #0)
7699d4c Refactoring of FlowMatch (see #0)
cad74ff Refactoring of handleMessage() (see #0)
7c19e07 Implement all 12-tuples of flow_match (see #0)
28c918f Fix incorrect flow_match due to lack of ether_type (see #0)
3fd30d4 Implement flow_stats request and reply (see #0)
c259128 Fix the connection bug between us and a switch (see #0)
3a850d9 Refactoring of FlowMatch marshaler (see #0)
9b3ce8c Fix incorrect IP representation in a flow match structure (see #0)
14a0b1b Implement packet-out message (see #0)
14664cd Implement packet-in and flow-removed messages (see #0)
a34a56e Implement adding/removing flow rules (see #0)
6e3ccbe Fix incorrect flow action's marshal routines (see #0)
7d5cb40 Implement flow actions (see #0)
d3d43ce Implement port status message (see #0)
8dc17da Implement echo request and reply messages (see #0)
9a2d6b0 Refactoring, and implement feature capabilities and actions (see #0)
52d690c Implement HelloMessage, ErrorMessage, FeaturesRequestMessage and FeaturesReplyMessage (see #0)
f9d2ae9 Initial commit (see #0)



================================================
FILE: Dockerfile
================================================
# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang:1.8

MAINTAINER Kitae Kim

# Copy the local package files to the container's workspace.
ADD . /go/src/github.com/superkkt/cherry/
COPY ./cherry.yaml /usr/local/etc/
 
# Build cherry inside the container.
RUN go install github.com/superkkt/cherry

# Run the cherry command by default when the container starts.
ENTRYPOINT ["/go/bin/cherry"]

# Document that the service listens on port 6633.
EXPOSE 6633


================================================
FILE: Godeps/Godeps.json
================================================
{
	"ImportPath": "github.com/superkkt/cherry",
	"GoVersion": "go1.10",
	"GodepVersion": "v79",
	"Packages": [
		"./..."
	],
	"Deps": [
		{
			"ImportPath": "github.com/ant0ine/go-json-rest/rest",
			"Comment": "v3.3.1-8-g3a807d6",
			"Rev": "3a807d6d8d36e0f9175d6c292030fce09bcbb2db"
		},
		{
			"ImportPath": "github.com/ant0ine/go-json-rest/rest/trie",
			"Comment": "v3.3.1-8-g3a807d6",
			"Rev": "3a807d6d8d36e0f9175d6c292030fce09bcbb2db"
		},
		{
			"ImportPath": "github.com/fsnotify/fsnotify",
			"Comment": "v1.3.0",
			"Rev": "30411dbcefb7a1da7e84f75530ad3abe4011b4f8"
		},
		{
			"ImportPath": "github.com/go-sql-driver/mysql",
			"Comment": "v1.3-59-g1a676ac",
			"Rev": "1a676ac6e4dce68e9303a1800773861350374a9e"
		},
		{
			"ImportPath": "github.com/hashicorp/golang-lru",
			"Rev": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6"
		},
		{
			"ImportPath": "github.com/hashicorp/golang-lru/simplelru",
			"Rev": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/hcl/ast",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/hcl/parser",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/hcl/scanner",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/hcl/strconv",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/hcl/token",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/json/parser",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/json/scanner",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/hashicorp/hcl/json/token",
			"Rev": "d7400db7143f8e869812e50a53acd6c8d92af3b8"
		},
		{
			"ImportPath": "github.com/magiconair/properties",
			"Comment": "v1.7.0",
			"Rev": "c265cfa48dda6474e208715ca93e987829f572f8"
		},
		{
			"ImportPath": "github.com/mitchellh/mapstructure",
			"Rev": "d2dd0262208475919e1a362f675cfc0e7c10e905"
		},
		{
			"ImportPath": "github.com/pelletier/go-buffruneio",
			"Rev": "df1e16fde7fc330a0ca68167c23bf7ed6ac31d6d"
		},
		{
			"ImportPath": "github.com/pelletier/go-toml",
			"Comment": "v0.3.5-19-g7cb9880",
			"Rev": "7cb988051d5045890cb91402a0b5fddc76c627bc"
		},
		{
			"ImportPath": "github.com/pkg/errors",
			"Comment": "v0.7.1",
			"Rev": "17b591df37844cde689f4d5813e5cea0927d8dd2"
		},
		{
			"ImportPath": "github.com/spf13/afero",
			"Rev": "06b7e5f50606ecd49148a01a6008942d9b669217"
		},
		{
			"ImportPath": "github.com/spf13/afero/mem",
			"Rev": "06b7e5f50606ecd49148a01a6008942d9b669217"
		},
		{
			"ImportPath": "github.com/spf13/cast",
			"Rev": "27b586b42e29bec072fe7379259cc719e1289da6"
		},
		{
			"ImportPath": "github.com/spf13/jwalterweatherman",
			"Rev": "33c24e77fb80341fe7130ee7c594256ff08ccc46"
		},
		{
			"ImportPath": "github.com/spf13/pflag",
			"Rev": "cb88ea77998c3f024757528e3305022ab50b43be"
		},
		{
			"ImportPath": "github.com/superkkt/go-logging",
			"Comment": "v1-8-gd6a8aba",
			"Rev": "d6a8aba149c56e15219853fff6500375e1cbb1f2"
		},
		{
			"ImportPath": "github.com/superkkt/viper",
			"Rev": "7a4f83d485c248540ad95ae0501252323b8b8682"
		},
		{
			"ImportPath": "golang.org/x/sys/unix",
			"Rev": "076b546753157f758b316e59bcb51e6807c04057"
		},
		{
			"ImportPath": "golang.org/x/text/transform",
			"Rev": "4440cd4f4c2ea31e1872e00de675a86d0c19006c"
		},
		{
			"ImportPath": "golang.org/x/text/unicode/norm",
			"Rev": "4440cd4f4c2ea31e1872e00de675a86d0c19006c"
		},
		{
			"ImportPath": "gopkg.in/yaml.v2",
			"Rev": "a83829b6f1293c91addabc89d0571c246397bbf4"
		}
	]
}


================================================
FILE: Godeps/Readme
================================================
This directory tree is generated automatically by godep.

Please do not edit.

See https://github.com/tools/godep for more information.


================================================
FILE: Gopkg.toml
================================================
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
#   name = "github.com/user/project"
#   version = "1.0.0"
#
# [[constraint]]
#   name = "github.com/user/project2"
#   branch = "dev"
#   source = "github.com/myfork/project2"
#
# [[override]]
#   name = "github.com/x/y"
#   version = "2.4.0"
#
# [prune]
#   non-go = false
#   go-tests = true
#   unused-packages = true


[[constraint]]
  name = "github.com/davecgh/go-spew"
  version = "1.1.1"

[[constraint]]
  name = "github.com/fsnotify/fsnotify"
  version = "1.3.0"

[[constraint]]
  name = "github.com/pkg/errors"
  version = "0.7.1"

[[constraint]]
  branch = "master"
  name = "github.com/superkkt/go-logging"

[[constraint]]
  branch = "master"
  name = "github.com/superkkt/viper"

[prune]
  go-tests = true
  unused-packages = true


================================================
FILE: LICENSE
================================================
       GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS


================================================
FILE: README.md
================================================
# Cherry

Cherry is an OpenFlow controller written in Go that supports OpenFlow 1.0 and 1.3 protocols. This project is not designed for general purpose, and it instead focuses on SDN (Software-Defined Networking) for an IT service provider.

## Features

* Supports OpenFlow 1.0 and 1.3 protocols
* Focuses on compatibility with commercial OpenFlow-enabled switches
* Supports network topology that has loops in it
* Provides several northbound applications: ProxyARP, L2Switch, Floating-IP, etc.
* Provides simple plugin system for northbound applications
* RESTful API to manage the controller itself

## Supported OpenFlow Switches (Fully Tested)

* Dell Force10 S4810
* Dell Force10 S3048-ON
* Dell Force10 S3148
* Open vSwitch

## Tested OpenFlow Switches

* HP 2920G
* Pica8 P-3295
* Quanta T1048-LB9

## Requirements

* MySQL (or MariaDB) database server

## Quick Start

You can install Cherry on Docker or natively from source based on your preference. 

### Installing on Docker

* Install Docker if you don't have it on your system by following instruction: https://docs.docker.com/installation/
* Clone Cherry:

 ```$ git clone https://github.com/superkkt/cherry.git```

* Copy the template configuration: 
 
 ```$ sudo cp cherry/cherry.yaml /usr/local/etc```

* Edit the configuration file */usr/local/etc/cherry.yaml* as you want.

* Build Docker image as root:

 ```# cd cherry; docker build -t cherry .```

* Run as root:

 ```# docker run -d -p 6633:6633 -v /dev/log:/dev/log -v /your/config/cherry.yaml:/usr/local/etc/cherry.yaml cherry```

 The bind mount of /dev/log is to collect syslog messages from the container and then write to the host's syslog daemon.

* That's it! Cherry will be started in L2 switch mode.

### Installing from source

* Install Go language if you don't have it on your system by following instruction: http://golang.org/doc/install
* Clone and compile Cherry: 

 ```$ go get github.com/superkkt/cherry```

* Copy the compiled binary and template configuration: 
 
 ```$ sudo cp $GOPATH/bin/cherry /usr/local/bin```
 
 ```$ sudo cp $GOPATH/src/github.com/superkkt/cherry/cherry.yaml /usr/local/etc```

* Edit the configuration file */usr/local/etc/cherry.yaml* as you want.

* Run:

 ```$ /usr/local/bin/cherry &```

* That's it! Cherry will be started in L2 switch mode.

## Copyright and License

```
Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.
Kitae Kim <superkkt@sds.co.kr>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
```


================================================
FILE: api/core/api.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package core

import (
	"encoding/json"
	"fmt"
	"net"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
	"github.com/superkkt/go-logging"
)

var (
	logger = logging.MustGetLogger("core")
)

type API struct {
	api.Server
}

func (r *API) Serve() error {
	return r.Server.Serve(
		rest.Post("/api/v1/status", api.ResponseHandler(r.status)),
		rest.Post("/api/v1/remove", api.ResponseHandler(r.remove)),
		rest.Post("/api/v1/announce", api.ResponseHandler(r.announce)),
	)
}

func (r *API) status(w api.ResponseWriter, req *rest.Request) {
	logger.Debugf("status request from %v", req.RemoteAddr)

	w.Write(api.Response{
		Status: api.StatusOkay,
		Data: struct {
			Master bool `json:"master"`
		}{
			Master: r.Observer.IsMaster(),
		},
	})
}

func (r *API) remove(w api.ResponseWriter, req *rest.Request) {
	p := new(removeParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("remove request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if p.MAC == nil {
		if err := r.Controller.RemoveFlows(); err != nil {
			w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove flows: %v", err.Error())})
			return
		}
	} else {
		if err := r.Controller.RemoveFlowsByMAC(p.MAC); err != nil {
			w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove flows by MAC: %v", err.Error())})
			return
		}
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeParam struct {
	MAC net.HardwareAddr
}

func (r *removeParam) UnmarshalJSON(data []byte) error {
	v := struct {
		MAC string `json:"mac"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	// If MAC is empty, remove all flows.
	if len(v.MAC) == 0 {
		return nil
	}

	addr, err := net.ParseMAC(v.MAC)
	if err != nil {
		return err
	}
	r.MAC = addr

	return nil
}

func (r *API) announce(w api.ResponseWriter, req *rest.Request) {
	p := new(announceParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("announce request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if err := r.Controller.Announce(p.IP, p.MAC); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to announce a new ARP entry: %v", err.Error())})
		return
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type announceParam struct {
	IP  net.IP
	MAC net.HardwareAddr
}

func (r *announceParam) UnmarshalJSON(data []byte) error {
	v := struct {
		IP  string `json:"ip"`
		MAC string `json:"mac"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	ip := net.ParseIP(v.IP)
	if ip == nil {
		return fmt.Errorf("invalid IP address: %v", v.IP)
	}
	mac, err := net.ParseMAC(v.MAC)
	if err != nil {
		return err
	}
	r.IP = ip
	r.MAC = mac

	return nil
}


================================================
FILE: api/response.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package api

import (
	"net/http"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

/*
 * Status Codes:
 *
 * 200 = Okay.
 * 4xx = Client-side errors.
 * 5xx = Server-side errors.
 */
type Status int

const (
	StatusOkay = 200

	StatusInvalidParameter    = 400
	StatusIncorrectCredential = 401
	StatusUnknownSession      = 402
	StatusPermissionDenied    = 403
	StatusDuplicated          = 404
	StatusNotFound            = 405
	StatusBlockedAccount      = 406
	StatusBlockedHost         = 407

	StatusInternalServerError = 500
	StatusServiceUnavailable  = 501
)

type Response struct {
	Status  Status      `json:"status"`
	Message string      `json:"message,omitempty"` // Human readable message related with the status code.
	Data    interface{} `json:"data,omitempty"`
}

func ResponseHandler(f func(ResponseWriter, *rest.Request)) func(rest.ResponseWriter, *rest.Request) {
	return func(w rest.ResponseWriter, req *rest.Request) {
		lw := &logWriter{w: w}
		f(lw, req)
	}
}

type ResponseWriter interface {
	// Identical to the http.ResponseWriter interface
	Header() http.Header

	Write(Response)

	// Similar to the http.ResponseWriter interface, with additional JSON related
	// headers set.
	WriteHeader(int)
}

type logWriter struct {
	w rest.ResponseWriter
}

func (r *logWriter) Header() http.Header {
	return r.w.Header()
}

func (r *logWriter) Write(resp Response) {
	switch {
	case resp.Status >= StatusInternalServerError:
		logger.Errorf("server-side error response: status=%v, message=%v", resp.Status, resp.Message)
	case resp.Status >= StatusInvalidParameter:
		logger.Infof("client-side error response: status=%v, message=%v", resp.Status, resp.Message)
	default:
		logger.Debugf("success response: %v", spew.Sdump(resp))
	}

	if err := r.w.WriteJson(resp); err != nil {
		logger.Errorf("failed to write a JSON response: %v", err)
	}
}

func (r *logWriter) WriteHeader(status int) {
	r.w.WriteHeader(status)
}


================================================
FILE: api/server.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package api

import (
	"errors"
	"fmt"
	"net"
	"net/http"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/superkkt/go-logging"
)

var (
	logger = logging.MustGetLogger("api")
)

type Server struct {
	Port uint16
	TLS  struct {
		Cert string // Path for a TLS certification file.
		Key  string // Path for a TLS private key file.
	}
	Observer   Observer
	Controller Controller
}

type Observer interface {
	IsMaster() bool
}

type Controller interface {
	Announce(net.IP, net.HardwareAddr) error
	RemoveFlows() error
	RemoveFlowsByMAC(net.HardwareAddr) error
}

func (r *Server) validate() error {
	if r.Observer == nil {
		return errors.New("nil observer")
	}
	if r.Controller == nil {
		return errors.New("nil controller")
	}

	return nil
}

func (r *Server) Serve(routes ...*rest.Route) error {
	if err := r.validate(); err != nil {
		return err
	}

	api := rest.NewApi()
	// Middleware to set the CORS header.
	api.Use(rest.MiddlewareSimple(func(handler rest.HandlerFunc) rest.HandlerFunc {
		return func(writer rest.ResponseWriter, request *rest.Request) {
			writer.Header().Set("Access-Control-Allow-Origin", "*")
			handler(writer, request)
		}
	}))
	// Middleware to deny the client requests if we are not the master controller.
	api.Use(rest.MiddlewareSimple(func(handler rest.HandlerFunc) rest.HandlerFunc {
		return func(writer rest.ResponseWriter, request *rest.Request) {
			if r.Observer.IsMaster() == false {
				writer.WriteJson(Response{Status: StatusServiceUnavailable, Message: "use the master controller server"})
				return
			}
			handler(writer, request)
		}
	}))
	router, err := rest.MakeRouter(routes...)
	if err != nil {
		return err
	}
	api.SetApp(router)

	// Listen on all interfaces.
	addr := fmt.Sprintf(":%v", r.Port)
	if r.TLS.Cert != "" && r.TLS.Key != "" {
		err = http.ListenAndServeTLS(addr, r.TLS.Cert, r.TLS.Key, api.MakeHandler())
	} else {
		err = http.ListenAndServe(addr, api.MakeHandler())
	}

	return err
}


================================================
FILE: api/ui/api.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"errors"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/superkkt/go-logging"
)

var (
	logger = logging.MustGetLogger("ui")
)

type API struct {
	api.Server
	DB   Database
	LDAP LDAP

	session *session
}

type Database interface {
	// Exec executes all queries of f in a single transaction. f should return the error raised from the Transaction
	// without any change or wrapping it for deadlock protection.
	Exec(f func(Transaction) error) error
}

type LDAP interface {
	Auth(username, password string) (ok bool, err error)
}

type Transaction interface {
	UserTransaction
	GroupTransaction
	SwitchTransaction
	NetworkTransaction
	IPTransaction
	HostTransaction
	VIPTransaction
	LogTransaction
	CategoryTransaction
	ComponentTransaction
}

type Search struct {
	Key   Column `json:"key"`
	Value string `json:"value"`
}

func (r *Search) Validate() error {
	switch r.Key {
	case ColumnIP:
		return validateIP(r.Value)
	case ColumnMAC:
		return validateMAC(r.Value)
	case ColumnLogType:
		return LogType(r.Value).Validate()
	case ColumnLogMethod:
		return LogMethod(r.Value).Validate()
	case ColumnPort, ColumnGroup, ColumnDescription, ColumnUser:
		if len(r.Value) == 0 {
			return errors.New("empty search value")
		}
		return nil
	default:
		return fmt.Errorf("invalid search key: %v", r.Key)
	}
}

// IP format is '1.*.*.*', '1.2.*.*', '1.2.3.*', '1.2.3.4'.
func validateIP(ip string) error {
	invalid := fmt.Errorf("invalid IP address: %v", ip)

	token := strings.Split(ip, ".")
	if len(token) != 4 {
		return invalid
	}

	var wildcard [4]bool
	for i, v := range token {
		if v == "*" {
			wildcard[i] = true
			continue
		}
		d, err := strconv.Atoi(v)
		if err != nil || (d < 0 || d > 255) {
			return invalid
		}
	}

	if wildcard[0] == true {
		return invalid
	}
	if wildcard[1] == true && (wildcard[2] == false || wildcard[3] == false) {
		return invalid
	}
	if wildcard[2] == true && wildcard[3] == false {
		return invalid
	}

	return nil
}

// MAC format is 'A1:*:*:*:*:*', 'A1:A2:*:*:*:*', 'A1:A2:A3:*:*:*', 'A1:A2:A3:A4:*:*', 'A1:A2:A3:A4:A5:*', 'A1:A2:A3:A4:A5:A6'.
func validateMAC(mac string) error {
	invalid := fmt.Errorf("invalid MAC address: %v", mac)

	token := strings.Split(mac, ":")
	if len(token) != 6 {
		return invalid
	}

	var wildcard [6]bool
	for i, v := range token {
		if v == "*" {
			wildcard[i] = true
			continue
		}
		d, err := strconv.ParseUint(v, 16, 8)
		if len(v) != 2 || err != nil || (d < 0 || d > 255) {
			return invalid
		}
	}

	if wildcard[0] == true {
		return invalid
	}
	if wildcard[1] == true && (wildcard[2] == false || wildcard[3] == false || wildcard[4] == false || wildcard[5] == false) {
		return invalid
	}
	if wildcard[2] == true && (wildcard[3] == false || wildcard[4] == false || wildcard[5] == false) {
		return invalid
	}
	if wildcard[3] == true && (wildcard[4] == false || wildcard[5] == false) {
		return invalid
	}
	if wildcard[4] == true && wildcard[5] == false {
		return invalid
	}

	return nil
}

type Sort struct {
	Key   Column `json:"key"`
	Order Order  `json:"order"`
}

func (r *Sort) Validate() error {
	if r.Order <= OrderInvalid || r.Order > OrderDescending {
		return errors.New("invalid sort order")
	}
	if r.Key <= ColumnInvalid || r.Key > ColumnGroup {
		return fmt.Errorf("invalid sort key: %v", r.Key)
	}

	return nil
}

type Column int

const (
	ColumnInvalid Column = iota
	ColumnTime
	ColumnIP
	ColumnMAC
	ColumnPort
	ColumnGroup
	ColumnDescription
	ColumnUser
	ColumnLogType
	ColumnLogMethod
)

type Order int

const (
	OrderInvalid Order = iota
	OrderAscending
	OrderDescending
)

type Pagination struct {
	Offset uint32 `json:"offset"`
	Limit  uint8  `json:"limit"`
}

func (r *API) Serve() error {
	if r.DB == nil {
		return errors.New("nil DB")
	}
	r.session = newSession(256, 2*time.Hour)

	return r.Server.Serve(
		rest.Post("/api/v1/user/login", api.ResponseHandler(r.login)),
		rest.Post("/api/v1/user/logout", api.ResponseHandler(r.logout)),
		rest.Post("/api/v1/user/list", api.ResponseHandler(r.listUser)),
		rest.Post("/api/v1/user/add", api.ResponseHandler(r.addUser)),
		rest.Post("/api/v1/user/update", api.ResponseHandler(r.updateUser)),
		rest.Post("/api/v1/user/reset", api.ResponseHandler(r.resetOTP)),
		rest.Post("/api/v1/group/list", api.ResponseHandler(r.listGroup)),
		rest.Post("/api/v1/group/add", api.ResponseHandler(r.addGroup)),
		rest.Post("/api/v1/group/update", api.ResponseHandler(r.updateGroup)),
		rest.Post("/api/v1/group/remove", api.ResponseHandler(r.removeGroup)),
		rest.Post("/api/v1/switch/list", api.ResponseHandler(r.listSwitch)),
		rest.Post("/api/v1/switch/add", api.ResponseHandler(r.addSwitch)),
		rest.Post("/api/v1/switch/remove", api.ResponseHandler(r.removeSwitch)),
		rest.Post("/api/v1/network/list", api.ResponseHandler(r.listNetwork)),
		rest.Post("/api/v1/network/add", api.ResponseHandler(r.addNetwork)),
		rest.Post("/api/v1/network/remove", api.ResponseHandler(r.removeNetwork)),
		rest.Post("/api/v1/network/ip", api.ResponseHandler(r.listIP)),
		rest.Post("/api/v1/host/list", api.ResponseHandler(r.listHost)),
		rest.Post("/api/v1/host/get", api.ResponseHandler(r.getHost)),
		rest.Post("/api/v1/host/add", api.ResponseHandler(r.addHost)),
		rest.Post("/api/v1/host/update", api.ResponseHandler(r.updateHost)),
		rest.Post("/api/v1/host/activate", api.ResponseHandler(r.activateHost)),
		rest.Post("/api/v1/host/deactivate", api.ResponseHandler(r.deactivateHost)),
		rest.Post("/api/v1/host/remove", api.ResponseHandler(r.removeHost)),
		rest.Post("/api/v1/vip/list", api.ResponseHandler(r.listVIP)),
		rest.Post("/api/v1/vip/add", api.ResponseHandler(r.addVIP)),
		rest.Post("/api/v1/vip/remove", api.ResponseHandler(r.removeVIP)),
		rest.Post("/api/v1/vip/toggle", api.ResponseHandler(r.toggleVIP)),
		rest.Post("/api/v1/log/list", api.ResponseHandler(r.listLog)),
		rest.Post("/api/v1/category/list", api.ResponseHandler(r.listCategory)),
		rest.Post("/api/v1/category/add", api.ResponseHandler(r.addCategory)),
		rest.Post("/api/v1/category/update", api.ResponseHandler(r.updateCategory)),
		rest.Post("/api/v1/category/remove", api.ResponseHandler(r.removeCategory)),
		rest.Post("/api/v1/component/list", api.ResponseHandler(r.listComponent)),
		rest.Post("/api/v1/component/add", api.ResponseHandler(r.addComponent)),
		rest.Post("/api/v1/component/update", api.ResponseHandler(r.updateComponent)),
		rest.Post("/api/v1/component/remove", api.ResponseHandler(r.removeComponent)),
	)
}

func (r *API) announce(cidr, mac string) error {
	i, _, err := net.ParseCIDR(cidr)
	if err != nil {
		return err
	}
	m, err := net.ParseMAC(mac)
	if err != nil {
		return err
	}

	logger.Debugf("sending ARP announcement to all hosts to update their ARP caches: ip=%v, mac=%v", i, m)
	if err := r.Controller.Announce(i, m); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	} else {
		logger.Debugf("updated all hosts ARP caches: ip=%v, mac=%v", i, m)
	}

	return nil
}


================================================
FILE: api/ui/category.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type CategoryTransaction interface {
	// Categories returns a list of registered categories. Pagination limit can be 0 that means no pagination.
	Categories(Pagination) ([]*Category, error)
	AddCategory(requesterID uint64, name string) (category *Category, duplicated bool, err error)
	// UpdateCategory updates name of a category specified by id and then returns information of the category. It returns nil if the category does not exist.
	UpdateCategory(requesterID, categoryID uint64, name string) (category *Category, duplicated bool, err error)
	// RemoveCategory removes a category specified by id and then returns information of the category before removing. It returns nil if the category does not exist.
	RemoveCategory(requesterID, categoryID uint64) (*Category, error)
}

type Category struct {
	ID        uint64
	Name      string
	Timestamp time.Time
}

func (r *Category) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
		Timestamp int64  `json:"timestamp"`
	}{
		ID:        r.ID,
		Name:      r.Name,
		Timestamp: r.Timestamp.Unix(),
	})
}

func (r *API) listCategory(w api.ResponseWriter, req *rest.Request) {
	p := new(listCategoryParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("listCategory request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var category []*Category
	f := func(tx Transaction) (err error) {
		category, err = tx.Categories(p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the category list: %v", err.Error())})
		return
	}
	logger.Debugf("queried category list: %v", spew.Sdump(category))

	w.Write(api.Response{Status: api.StatusOkay, Data: category})
}

type listCategoryParam struct {
	SessionID  string
	Pagination Pagination
}

func (r *listCategoryParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listCategoryParam(v)

	return r.validate()
}

func (r *listCategoryParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}

	return nil
}

func (r *API) addCategory(w api.ResponseWriter, req *rest.Request) {
	p := new(addCategoryParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("addCategory request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var category *Category
	var duplicated bool
	f := func(tx Transaction) (err error) {
		category, duplicated, err = tx.AddCategory(session.(*User).ID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new category: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated category: %v", p.Name)})
		return
	}
	logger.Debugf("added category info: %v", spew.Sdump(category))

	w.Write(api.Response{Status: api.StatusOkay, Data: category})
}

type addCategoryParam struct {
	SessionID string
	Name      string
}

func (r *addCategoryParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = addCategoryParam(v)

	return r.validate()
}

func (r *addCategoryParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 255 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) updateCategory(w api.ResponseWriter, req *rest.Request) {
	p := new(updateCategoryParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("updateCategory request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var category *Category
	var duplicated bool
	f := func(tx Transaction) (err error) {
		category, duplicated, err = tx.UpdateCategory(session.(*User).ID, p.ID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to update category info: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated category: %v", p.Name)})
		return
	}
	if category == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found category to update: %v", p.ID)})
		return
	}
	logger.Debugf("updated category info: %v", spew.Sdump(category))

	w.Write(api.Response{Status: api.StatusOkay, Data: category})
}

type updateCategoryParam struct {
	SessionID string
	ID        uint64
	Name      string
}

func (r *updateCategoryParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = updateCategoryParam(v)

	return r.validate()
}

func (r *updateCategoryParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid category id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 255 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) removeCategory(w api.ResponseWriter, req *rest.Request) {
	p := new(removeCategoryParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("removeCategory request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var category *Category
	f := func(tx Transaction) (err error) {
		category, err = tx.RemoveCategory(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove category info: %v", err.Error())})
		return
	}

	if category == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found category to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed category info: %v", spew.Sdump(category))

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeCategoryParam struct {
	SessionID string
	ID        uint64
}

func (r *removeCategoryParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeCategoryParam(v)

	return r.validate()
}

func (r *removeCategoryParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid category id")
	}

	return nil
}


================================================
FILE: api/ui/component.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type ComponentTransaction interface {
	// Components returns a list of registered components. Pagination limit can be 0 that means no pagination.
	Components(categoryID uint64, pagination Pagination) ([]*Component, error)
	AddComponent(requesterID, categoryID uint64, name string) (component *Component, duplicated bool, err error)
	// UpdateComponent updates name of a component specified by id and then returns information of the component. It returns nil if the component does not exist.
	UpdateComponent(requesterID, componentID uint64, name string) (component *Component, duplicated bool, err error)
	// RemoveComponent removes a component specified by id and then returns information of the component before removing. It returns nil if the component does not exist.
	RemoveComponent(requesterID, componentID uint64) (*Component, error)
}

type Component struct {
	ID        uint64
	Category  Category
	Name      string
	Timestamp time.Time
}

func (r *Component) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID        uint64   `json:"id"`
		Category  Category `json:"category"`
		Name      string   `json:"name"`
		Timestamp int64    `json:"timestamp"`
	}{
		ID:        r.ID,
		Category:  r.Category,
		Name:      r.Name,
		Timestamp: r.Timestamp.Unix(),
	})
}

func (r *API) listComponent(w api.ResponseWriter, req *rest.Request) {
	p := new(listComponentParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("listComponent request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var component []*Component
	f := func(tx Transaction) (err error) {
		component, err = tx.Components(p.CategoryID, p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the component list: %v", err.Error())})
		return
	}
	logger.Debugf("queried component list: %v", spew.Sdump(component))

	w.Write(api.Response{Status: api.StatusOkay, Data: component})
}

type listComponentParam struct {
	SessionID  string
	CategoryID uint64
	Pagination Pagination
}

func (r *listComponentParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		CategoryID uint64     `json:"category_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listComponentParam(v)

	return r.validate()
}

func (r *listComponentParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.CategoryID == 0 {
		return errors.New("invalid category id")
	}

	return nil
}

func (r *API) addComponent(w api.ResponseWriter, req *rest.Request) {
	p := new(addComponentParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("addComponent request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var component *Component
	var duplicated bool
	f := func(tx Transaction) (err error) {
		component, duplicated, err = tx.AddComponent(session.(*User).ID, p.CategoryID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new component: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated component: category_id=%v, name=%v", p.CategoryID, p.Name)})
		return
	}
	logger.Debugf("added component info: %v", spew.Sdump(component))

	w.Write(api.Response{Status: api.StatusOkay, Data: component})
}

type addComponentParam struct {
	SessionID  string
	CategoryID uint64
	Name       string
}

func (r *addComponentParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string `json:"session_id"`
		CategoryID uint64 `json:"category_id"`
		Name       string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = addComponentParam(v)

	return r.validate()
}

func (r *addComponentParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.CategoryID == 0 {
		return errors.New("invalid category id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 255 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) updateComponent(w api.ResponseWriter, req *rest.Request) {
	p := new(updateComponentParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("updateComponent request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var component *Component
	var duplicated bool
	f := func(tx Transaction) (err error) {
		component, duplicated, err = tx.UpdateComponent(session.(*User).ID, p.ID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to update component info: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated component: %v", p.Name)})
		return
	}
	if component == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found component to update: %v", p.ID)})
		return
	}
	logger.Debugf("updated component info: %v", spew.Sdump(component))

	w.Write(api.Response{Status: api.StatusOkay, Data: component})
}

type updateComponentParam struct {
	SessionID string
	ID        uint64
	Name      string
}

func (r *updateComponentParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = updateComponentParam(v)

	return r.validate()
}

func (r *updateComponentParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid component id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 255 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) removeComponent(w api.ResponseWriter, req *rest.Request) {
	p := new(removeComponentParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("removeComponent request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var component *Component
	f := func(tx Transaction) (err error) {
		component, err = tx.RemoveComponent(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove component info: %v", err.Error())})
		return
	}

	if component == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found component to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed component info: %v", spew.Sdump(component))

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeComponentParam struct {
	SessionID string
	ID        uint64
}

func (r *removeComponentParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeComponentParam(v)

	return r.validate()
}

func (r *removeComponentParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid component id")
	}

	return nil
}


================================================
FILE: api/ui/group.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type GroupTransaction interface {
	// Groups returns a list of registered groups. Pagination limit can be 0 that means no pagination.
	Groups(Pagination) ([]*Group, error)
	AddGroup(requesterID uint64, name string) (group *Group, duplicated bool, err error)
	// UpdateGroup updates name of a group specified by id and then returns information of the group. It returns nil if the group does not exist.
	UpdateGroup(requesterID, groupID uint64, name string) (group *Group, duplicated bool, err error)
	// RemoveGroup removes a group specified by id and then returns information of the group before removing. It returns nil if the group does not exist.
	RemoveGroup(requesterID, groupID uint64) (*Group, error)
}

type Group struct {
	ID        uint64    `json:"id"`
	Name      string    `json:"name"`
	Timestamp time.Time `json:"timestamp"`
}

func (r *Group) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
		Timestamp int64  `json:"timestamp"`
	}{
		ID:        r.ID,
		Name:      r.Name,
		Timestamp: r.Timestamp.Unix(),
	})
}

func (r *API) listGroup(w api.ResponseWriter, req *rest.Request) {
	p := new(listGroupParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listGroup request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var group []*Group
	f := func(tx Transaction) (err error) {
		group, err = tx.Groups(p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the groups: %v", err.Error())})
		return
	}
	logger.Debugf("queried group list: %v", spew.Sdump(group))

	w.Write(api.Response{Status: api.StatusOkay, Data: group})
}

type listGroupParam struct {
	SessionID  string
	Pagination Pagination
}

func (r *listGroupParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listGroupParam(v)

	return r.validate()
}

func (r *listGroupParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}

	return nil
}

func (r *API) addGroup(w api.ResponseWriter, req *rest.Request) {
	p := new(addGroupParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("addGroup request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var group *Group
	var duplicated bool
	f := func(tx Transaction) (err error) {
		group, duplicated, err = tx.AddGroup(session.(*User).ID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new group: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated group: %v", p.Name)})
		return
	}
	logger.Debugf("added group info: %v", spew.Sdump(group))

	w.Write(api.Response{Status: api.StatusOkay, Data: group})
}

type addGroupParam struct {
	SessionID string
	Name      string
}

func (r *addGroupParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = addGroupParam(v)

	return r.validate()
}

func (r *addGroupParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 25 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) updateGroup(w api.ResponseWriter, req *rest.Request) {
	p := new(updateGroupParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("updateGroup request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var group *Group
	var duplicated bool
	f := func(tx Transaction) (err error) {
		group, duplicated, err = tx.UpdateGroup(session.(*User).ID, p.ID, p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to update a group: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated group: %v", p.Name)})
		return
	}
	if group == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found group to update: %v", p.ID)})
		return
	}
	logger.Debugf("updated the group: %v", spew.Sdump(group))

	w.Write(api.Response{Status: api.StatusOkay, Data: group})
}

type updateGroupParam struct {
	SessionID string
	ID        uint64
	Name      string
}

func (r *updateGroupParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = updateGroupParam(v)

	return r.validate()
}

func (r *updateGroupParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid group id")
	}
	if utf8.RuneCountInString(r.Name) < 2 || utf8.RuneCountInString(r.Name) > 25 {
		return fmt.Errorf("invalid name: %v", r.Name)
	}

	return nil
}

func (r *API) removeGroup(w api.ResponseWriter, req *rest.Request) {
	p := new(removeGroupParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("removeGroup request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var group *Group
	f := func(tx Transaction) (err error) {
		group, err = tx.RemoveGroup(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove a group: %v", err.Error())})
		return
	}

	if group == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found group to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed the group: %v", spew.Sdump(group))

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeGroupParam struct {
	SessionID string
	ID        uint64
}

func (r *removeGroupParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeGroupParam(v)

	return r.validate()
}

func (r *removeGroupParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid group id")
	}

	return nil
}


================================================
FILE: api/ui/host.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"time"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"
	"github.com/superkkt/cherry/network"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

var (
	errDuplicated = errors.New("duplicated error")
	errNotFound   = errors.New("not found error")
	errBlocked    = errors.New("blocked error")
)

type HostTransaction interface {
	Host(id uint64) (*Host, error)
	// Hosts returns a list of registered hosts. Search can be nil that means no search. Pagination limit can be 0 that means no pagination.
	Hosts(*Search, Sort, Pagination) ([]*Host, error)
	AddHost(requesterID, ipID uint64, groupID *uint64, mac net.HardwareAddr, desc string, spec []SpecParam) (host *Host, duplicated bool, err error)
	// UpdateHost updates a host specified by id and then returns information of the host. The parameters used for update can be nil that means no update about the parameters.
	UpdateHost(requesterID, hostID uint64, ipID, groupID *uint64, mac net.HardwareAddr, description *string, spec []SpecParam) (host *Host, duplicated bool, err error)
	// ActivateHost enables a host specified by id and then returns information of the host. It returns nil if the host does not exist.
	ActivateHost(requesterID, hostID uint64) (*Host, error)
	// DeactivateHost disables a host specified by id and then returns information of the host. It returns nil if the host does not exist.
	DeactivateHost(requesterID, hostID uint64) (*Host, error)
	CountVIPByHostID(id uint64) (count uint64, err error)
	// RemoveHost removes a host specified by id and then returns information of the host before removing. It returns nil if the host does not exist.
	RemoveHost(requesterID, hostID uint64) (*Host, error)
}

type Host struct {
	ID          uint64
	IP          string // FIXME: Use a native type.
	Port        string
	Group       string
	MAC         string // FIXME: Use a native type.
	Description string
	Enabled     bool
	Stale       bool
	Spec        []*Spec
	Timestamp   time.Time
}

func (r *Host) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID          uint64  `json:"id"`
		IP          string  `json:"ip"`
		Port        string  `json:"port"`
		Group       string  `json:"group"`
		MAC         string  `json:"mac"`
		Description string  `json:"description"`
		Enabled     bool    `json:"enabled"`
		Stale       bool    `json:"stale"`
		Spec        []*Spec `json:"spec"`
		Timestamp   int64   `json:"timestamp"`
	}{
		ID:          r.ID,
		IP:          r.IP,
		Port:        r.Port,
		Group:       r.Group,
		MAC:         r.MAC,
		Description: r.Description,
		Enabled:     r.Enabled,
		Stale:       r.Stale,
		Spec:        r.Spec,
		Timestamp:   r.Timestamp.Unix(),
	})
}

type Spec struct {
	ID        uint64    `json:"id"`
	Component Component `json:"component"`
	Count     uint16    `json:"count"`
}

func (r *API) listHost(w api.ResponseWriter, req *rest.Request) {
	p := new(listHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host []*Host
	f := func(tx Transaction) (err error) {
		host, err = tx.Hosts(p.Search, p.Sort, p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the hosts: %v", err.Error())})
		return
	}
	logger.Debugf("queried host list: %v", spew.Sdump(host))

	w.Write(api.Response{Status: api.StatusOkay, Data: host})
}

type listHostParam struct {
	SessionID  string
	Search     *Search
	Sort       Sort
	Pagination Pagination
}

func (r *listHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Search     *Search    `json:"search"`
		Sort       Sort       `json:"sort"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listHostParam(v)

	return r.validate()
}

func (r *listHostParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	// If search is nil, fetch hosts without using search.
	if r.Search != nil {
		if r.Search.Key <= ColumnTime || r.Search.Key > ColumnDescription {
			return errors.New("invalid search key")
		}
		if err := r.Search.Validate(); err != nil {
			return err
		}
	}
	if err := r.Sort.Validate(); err != nil {
		return err
	}

	return nil
}

func (r *API) getHost(w api.ResponseWriter, req *rest.Request) {
	p := new(getHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("getHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host *Host
	f := func(tx Transaction) (err error) {
		host, err = tx.Host(p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the host info: %v", err.Error())})
		return
	}

	if host == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found host: %v", p.ID)})
		return
	}
	logger.Debugf("queried host info: %v", spew.Sdump(host))

	w.Write(api.Response{Status: api.StatusOkay, Data: host})
}

type getHostParam struct {
	SessionID string
	ID        uint64
}

func (r *getHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = getHostParam(v)

	return r.validate()
}

func (r *getHostParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid host id")
	}

	return nil
}

func (r *API) addHost(w api.ResponseWriter, req *rest.Request) {
	p := new(addHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("addHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host []*Host
	f := func(tx Transaction) (err error) {
		for _, v := range p.IPID {
			h, duplicated, err := tx.AddHost(session.(*User).ID, v, p.GroupID, p.MAC, p.Description, p.Spec)
			if err != nil {
				return err
			}
			if duplicated {
				return errDuplicated
			}

			host = append(host, h)
		}

		return nil
	}
	if err := r.DB.Exec(f); err != nil {
		if err == errDuplicated {
			w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated host: ip_id=%v", p.IPID)})
		} else {
			w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new host: %v", err.Error())})
		}
		return
	}

	logger.Debugf("added host info: %v", spew.Sdump(host))

	for _, v := range host {
		if err := r.announce(v.IP, v.MAC); err != nil {
			// Ignore this error.
			logger.Errorf("failed to send ARP announcement: %v", err)
		}
	}

	w.Write(api.Response{Status: api.StatusOkay, Data: host})
}

type addHostParam struct {
	SessionID   string
	IPID        []uint64
	GroupID     *uint64
	MAC         net.HardwareAddr
	Description string
	Spec        []SpecParam
}

func (r *addHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID   string      `json:"session_id"`
		IPID        []uint64    `json:"ip_id"`
		GroupID     *uint64     `json:"group_id"`
		MAC         string      `json:"mac"`
		Description string      `json:"description"`
		Spec        []SpecParam `json:"spec"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	if len(v.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if len(v.IPID) == 0 {
		return errors.New("empty ip id")
	}
	if len(v.IPID) > 10 {
		return errors.New("too many ip ids")
	}
	for _, i := range v.IPID {
		if i == 0 {
			return errors.New("invalid ip id")
		}
	}
	if utf8.RuneCountInString(v.Description) > 255 {
		return errors.New("too long description")
	}
	mac, err := net.ParseMAC(v.MAC)
	if err != nil {
		return err
	}
	for _, v := range r.Spec {
		if err := v.Validate(); err != nil {
			return err
		}
	}

	r.SessionID = v.SessionID
	r.IPID = v.IPID
	r.GroupID = v.GroupID
	r.MAC = mac
	r.Description = v.Description
	r.Spec = v.Spec

	return nil
}

type SpecParam struct {
	ComponentID uint64 `json:"component_id"`
	Count       uint16 `json:"count"`
}

func (r *SpecParam) Validate() error {
	if r.ComponentID == 0 {
		return errors.New("invalid component id")
	}
	if r.Count == 0 {
		return errors.New("invalid count")
	}

	return nil
}

func (r *API) updateHost(w api.ResponseWriter, req *rest.Request) {
	p := new(updateHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("updateHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var old, new *Host
	f := func(tx Transaction) (err error) {
		count, err := tx.CountVIPByHostID(p.ID)
		if err != nil {
			return err
		}
		if count > 0 {
			return errors.New("VIP member host cannot be updated")
		}

		old, err = tx.Host(p.ID)
		if err != nil {
			return err
		}
		if old == nil {
			return errNotFound
		}
		if old.Enabled == false {
			return errBlocked
		}

		h, duplicated, err := tx.UpdateHost(session.(*User).ID, p.ID, p.IPID, p.GroupID, p.MAC, p.Description, p.Spec)
		if err != nil {
			return err
		}
		if duplicated {
			return errDuplicated
		}
		new = h

		return nil
	}
	if err := r.DB.Exec(f); err != nil {
		switch err {
		case errNotFound:
			w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found host to update: %v", p.ID)})
		case errBlocked:
			w.Write(api.Response{Status: api.StatusBlockedHost, Message: fmt.Sprintf("unable to update blocked host: %v", p.ID)})
		case errDuplicated:
			w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated host: ip_id=%v", p.IPID)})
		default:
			w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to update a host: %v", err.Error())})
		}
		return
	}

	logger.Debugf("updated host info: %v", spew.Sdump(new))

	if err := r.announce(old.IP, network.NullMAC.String()); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}
	if err := r.announce(new.IP, new.MAC); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay, Data: new})
}

type updateHostParam struct {
	SessionID   string
	ID          uint64
	IPID        *uint64
	GroupID     *uint64
	MAC         net.HardwareAddr
	Description *string
	Spec        []SpecParam
}

func (r *updateHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID   string      `json:"session_id"`
		ID          uint64      `json:"id"`
		IPID        *uint64     `json:"ip_id"`
		GroupID     *uint64     `json:"group_id"`
		MAC         *string     `json:"mac"`
		Description *string     `json:"description"`
		Spec        []SpecParam `json:"spec"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	if len(v.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if v.ID == 0 {
		return errors.New("invalid host id")
	}
	if v.IPID == nil && v.GroupID == nil && v.MAC == nil && v.Description == nil && v.Spec == nil {
		return errors.New("not exist value to update")
	}
	if v.IPID != nil && *v.IPID == 0 {
		return errors.New("invalid ip id")
	}
	if v.GroupID != nil && *v.GroupID == 0 {
		return errors.New("invalid group id")
	}
	if v.Description != nil && utf8.RuneCountInString(*v.Description) > 255 {
		return errors.New("too long description")
	}
	for _, v := range r.Spec {
		if err := v.Validate(); err != nil {
			return err
		}
	}

	if v.MAC != nil {
		v, err := net.ParseMAC(*v.MAC)
		if err != nil {
			return err
		}
		r.MAC = v
	}

	r.SessionID = v.SessionID
	r.ID = v.ID
	r.IPID = v.IPID
	r.GroupID = v.GroupID
	r.Description = v.Description
	r.Spec = v.Spec

	return nil
}

func (r *API) activateHost(w api.ResponseWriter, req *rest.Request) {
	p := new(activateHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("activateHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host *Host
	f := func(tx Transaction) (err error) {
		host, err = tx.ActivateHost(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to activate a host: %v", err.Error())})
		return
	}

	if host == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found host to activate: %v", p.ID)})
		return
	}
	logger.Debugf("activated host info: %v", spew.Sdump(host))

	if err := r.announce(host.IP, host.MAC); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type activateHostParam struct {
	SessionID string
	ID        uint64
}

func (r *activateHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = activateHostParam(v)

	return r.validate()
}

func (r *activateHostParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid switch id")
	}

	return nil
}

func (r *API) deactivateHost(w api.ResponseWriter, req *rest.Request) {
	p := new(deactivateHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("deactivateHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host *Host
	f := func(tx Transaction) (err error) {
		count, err := tx.CountVIPByHostID(p.ID)
		if err != nil {
			return err
		}
		if count > 0 {
			return errors.New("VIP member host cannot be disabled")
		}

		host, err = tx.DeactivateHost(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to deactivate a host: %v", err.Error())})
		return
	}

	if host == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found host to deactivate: %v", p.ID)})
		return
	}
	logger.Debugf("deactivated host info: %v", spew.Sdump(host))

	if err := r.announce(host.IP, network.NullMAC.String()); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type deactivateHostParam struct {
	SessionID string
	ID        uint64
}

func (r *deactivateHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = deactivateHostParam(v)

	return r.validate()
}

func (r *deactivateHostParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid switch id")
	}

	return nil
}

func (r *API) removeHost(w api.ResponseWriter, req *rest.Request) {
	p := new(removeHostParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("removeHost request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var host *Host
	f := func(tx Transaction) (err error) {
		host, err = tx.RemoveHost(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove a host: %v", err.Error())})
		return
	}

	if host == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found host to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed host info: %v", spew.Sdump(host))

	if err := r.announce(host.IP, network.NullMAC.String()); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeHostParam struct {
	SessionID string
	ID        uint64
}

func (r *removeHostParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeHostParam(v)

	return r.validate()
}

func (r *removeHostParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid switch id")
	}

	return nil
}


================================================
FILE: api/ui/ip.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type IPTransaction interface {
	IPAddrs(networkID uint64) ([]*IP, error)
}

type IP struct {
	ID      uint64 `json:"id"`
	Address string `json:"address"` // FIXME: Use a native type.
	Used    bool   `json:"used"`
	Port    string `json:"port"`
	Host    struct {
		Description string `json:"description"`
		Enabled     bool   `json:"enabled"`
		Stale       bool   `json:"stale"`
	} `json:"host"`
}

func (r *API) listIP(w api.ResponseWriter, req *rest.Request) {
	p := new(listIPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listIP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var ip []*IP
	f := func(tx Transaction) (err error) {
		ip, err = tx.IPAddrs(p.NetworkID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the network ip list: %v", err.Error())})
		return
	}
	logger.Debugf("queried network ip list: %v", spew.Sdump(ip))

	w.Write(api.Response{Status: api.StatusOkay, Data: ip})
}

type listIPParam struct {
	SessionID string
	NetworkID uint64
}

func (r *listIPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		NetworkID uint64 `json:"network_id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listIPParam(v)

	return r.validate()
}

func (r *listIPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.NetworkID == 0 {
		return errors.New("invalid network id")
	}

	return nil
}


================================================
FILE: api/ui/log.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type LogType string

const (
	LogTypeUser      LogType = "USER"
	LogTypeGroup     LogType = "GROUP"
	LogTypeSwitch    LogType = "SWITCH"
	LogTypeNetwork   LogType = "NETWORK"
	LogTypeHost      LogType = "HOST"
	LogTypeVIP       LogType = "VIP"
	LogTypeCategory  LogType = "CATEGORY"
	LogTypeComponent LogType = "COMPONENT"
)

func (r LogType) Validate() error {
	if r != LogTypeUser && r != LogTypeGroup && r != LogTypeSwitch && r != LogTypeNetwork &&
		r != LogTypeHost && r != LogTypeVIP && r != LogTypeCategory && r != LogTypeComponent {
		return fmt.Errorf("invalid log type: %v", r)
	}

	return nil
}

type LogMethod string

const (
	LogMethodAdd    LogMethod = "ADD"
	LogMethodUpdate LogMethod = "UPDATE"
	LogMethodRemove LogMethod = "REMOVE"
)

func (r LogMethod) Validate() error {
	if r != LogMethodAdd && r != LogMethodUpdate && r != LogMethodRemove {
		return fmt.Errorf("invalid log method: %v", r)
	}

	return nil
}

type LogTransaction interface {
	// Logs returns a list of registered logs. Search can be nil that means no search.
	QueryLog(*Search, Pagination) ([]*Log, error)
}

type Log struct {
	ID        uint64
	User      string
	Type      LogType
	Method    LogMethod
	Data      string
	Timestamp time.Time
}

func (r *Log) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID        uint64 `json:"id"`
		User      string `json:"user"`
		Type      string `json:"type"`
		Method    string `json:"method"`
		Data      string `json:"data"`
		Timestamp int64  `json:"timestamp"`
	}{
		ID:        r.ID,
		User:      r.User,
		Type:      string(r.Type),
		Method:    string(r.Method),
		Data:      r.Data,
		Timestamp: r.Timestamp.Unix(),
	})
}

func (r *API) listLog(w api.ResponseWriter, req *rest.Request) {
	p := new(listLogParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listLog request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var log []*Log
	f := func(tx Transaction) (err error) {
		log, err = tx.QueryLog(p.Search, p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the log list: %v", err.Error())})
		return
	}
	logger.Debugf("queried log list: %v", spew.Sdump(log))

	w.Write(api.Response{Status: api.StatusOkay, Data: log})
}

type listLogParam struct {
	SessionID  string
	Search     *Search
	Pagination Pagination
}

func (r *listLogParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Search     *Search    `json:"search"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listLogParam(v)

	return r.validate()
}

func (r *listLogParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	// If search is nil, fetch logs without using search.
	if r.Search != nil {
		if r.Search.Key <= ColumnDescription || r.Search.Key > ColumnLogMethod {
			return errors.New("invalid search key")
		}
		if err := r.Search.Validate(); err != nil {
			return err
		}
	}
	if r.Pagination.Limit == 0 {
		return errors.New("invalid pagination limit")
	}

	return nil
}


================================================
FILE: api/ui/network.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"

	"github.com/superkkt/cherry/api"
	"github.com/superkkt/cherry/network"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type NetworkTransaction interface {
	// Networks returns a list of registered networks. Address can be nil that means no address search. Pagination limit can be 0 that means no pagination.
	Networks(address *string, pagination Pagination) ([]*Network, error)
	AddNetwork(requesterID uint64, addr net.IP, mask net.IPMask, gateway net.IP) (network *Network, duplicated bool, err error)
	// RemoveNetwork removes a network specified by id and then returns information of the network before removing. It returns nil if the network does not exist.
	RemoveNetwork(requesterID, netID uint64) (*Network, error)
}

type Network struct {
	ID      uint64 `json:"id"`
	Address string `json:"address"` // FIXME: Use a native type.
	Mask    uint8  `json:"mask"`    // FIXME: Use a native type.
	Gateway string `json:"gateway"` // FIXME: Use a native type.
}

func (r *API) listNetwork(w api.ResponseWriter, req *rest.Request) {
	p := new(listNetworkParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listNetwork request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var network []*Network
	f := func(tx Transaction) (err error) {
		network, err = tx.Networks(p.Address, p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the network list: %v", err.Error())})
		return
	}
	logger.Debugf("queried network list: %v", spew.Sdump(network))

	w.Write(api.Response{Status: api.StatusOkay, Data: network})
}

type listNetworkParam struct {
	SessionID  string
	Address    *string
	Pagination Pagination
}

func (r *listNetworkParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Address    *string    `json:"address"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listNetworkParam(v)

	return r.validate()
}

func (r *listNetworkParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.Address != nil {
		if err := validateIP(*r.Address); err != nil {
			return err
		}
	}

	return nil
}

func (r *API) addNetwork(w api.ResponseWriter, req *rest.Request) {
	p := new(addNetworkParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("addNetwork request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var network *Network
	var duplicated bool
	f := func(tx Transaction) (err error) {
		network, duplicated, err = tx.AddNetwork(session.(*User).ID, p.Address, p.Mask, p.Gateway)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new network: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated network: address=%v, mask=%v", p.Address, p.Mask)})
		return
	}
	logger.Debugf("added network info: %v", spew.Sdump(network))

	w.Write(api.Response{Status: api.StatusOkay, Data: network})
}

type addNetworkParam struct {
	SessionID string
	Address   net.IP
	Mask      net.IPMask
	Gateway   net.IP
}

func (r *addNetworkParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		Address   string `json:"address"`
		Mask      uint8  `json:"mask"`
		Gateway   string `json:"gateway"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	if len(v.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if v.Mask < 24 || v.Mask > 30 {
		return fmt.Errorf("invalid network mask: %v", v.Mask)
	}
	_, network, err := net.ParseCIDR(fmt.Sprintf("%v/%v", v.Address, v.Mask))
	if err != nil || network == nil {
		return fmt.Errorf("invalid network address: %v", v.Address)
	}
	gateway := net.ParseIP(v.Gateway)
	if gateway == nil {
		return fmt.Errorf("invalid network gateway: %v", v.Gateway)
	}
	if err := validateGateway(*network, gateway); err != nil {
		return err
	}

	r.SessionID = v.SessionID
	r.Mask = network.Mask
	r.Address = network.IP
	r.Gateway = gateway

	return nil
}

func validateGateway(n net.IPNet, g net.IP) error {
	invalid := fmt.Errorf("invalid network gateway: %v", g)
	broadcast := net.IP(make([]byte, 4))
	for i := range n.IP.To4() {
		broadcast[i] = n.IP.To4()[i] | ^n.Mask[i]
	}

	reserved, err := network.ReservedIP(n)
	if err != nil {
		return err
	}

	if n.Contains(g) == false {
		return invalid
	}
	if g.Equal(n.IP) || g.Equal(broadcast) || g.Equal(reserved) {
		return invalid
	}

	return nil
}

func (r *API) removeNetwork(w api.ResponseWriter, req *rest.Request) {
	p := new(removeNetworkParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("removeNetwork request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var network *Network
	f := func(tx Transaction) (err error) {
		network, err = tx.RemoveNetwork(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove a network: %v", err.Error())})
		return
	}

	if network == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found network to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed a network: %v", spew.Sdump(network))

	logger.Debug("removing all flows from the entire switches")
	if err := r.Controller.RemoveFlows(); err != nil {
		// Ignore this error.
		logger.Errorf("failed to remove flows: %v", err)
	} else {
		logger.Debug("removed all flows from the entire switches")
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeNetworkParam struct {
	SessionID string
	ID        uint64
}

func (r *removeNetworkParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeNetworkParam(v)

	return r.validate()
}

func (r *removeNetworkParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("empty network id")
	}

	return nil
}


================================================
FILE: api/ui/session.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math/rand"
	"strings"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/hashicorp/golang-lru"
)

type session struct {
	storage *lru.Cache
	timeout time.Duration
}

func newSession(size int, timeout time.Duration) *session {
	c, err := lru.New(size)
	if err != nil {
		panic(err)
	}

	return &session{
		storage: c,
		timeout: timeout,
	}
}

func (r *session) Add(v interface{}) (id string) {
	src := fmt.Sprintf("%v.%v.%v", spew.Sdump(v), time.Now().UnixNano(), rand.Float64())
	id = strings.ToUpper(hash(src))
	r.storage.Add(id, &sessionEntry{Data: v, Timestamp: time.Now()})

	return id
}

type sessionEntry struct {
	Data      interface{}
	Timestamp time.Time
}

func hash(value string) string {
	h := sha256.New()
	h.Write([]byte(value))

	return hex.EncodeToString(h.Sum(nil))
}

func (r *session) Get(id string) (interface{}, bool) {
	id = strings.ToUpper(id)

	v, ok := r.storage.Get(id)
	if ok == false {
		return nil, false
	}

	e := v.(*sessionEntry)
	if time.Since(e.Timestamp) > r.timeout {
		r.storage.Remove(id)
		return nil, false
	}
	e.Timestamp = time.Now()

	return e.Data, true
}

func (r *session) Remove(id string) bool {
	id = strings.ToUpper(id)

	if r.storage.Contains(id) == false {
		return false
	}
	r.storage.Remove(id)

	return true
}


================================================
FILE: api/ui/switch.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type SwitchTransaction interface {
	Switches(Pagination) ([]*Switch, error)
	AddSwitch(requesterID, dpid uint64, nPorts, firstPort, firstPrintedPort uint16, desc string) (sw *Switch, duplicated bool, err error)
	// RemoveSwitch removes a switch specified by id and then returns information of the switch before removing. It returns nil if the switch does not exist.
	RemoveSwitch(requesterID, swID uint64) (*Switch, error)
}

type Switch struct {
	ID               uint64 `json:"id"`
	DPID             uint64 `json:"dpid"`
	NumPorts         uint16 `json:"n_ports"`
	FirstPort        uint16 `json:"first_port"`
	FirstPrintedPort uint16 `json:"first_printed_port"`
	Description      string `json:"description"`
}

func (r *Switch) MarshalJSON() ([]byte, error) {
	s := new(struct {
		ID   uint64 `json:"id"`
		DPID struct {
			Int uint64 `json:"int"`
			Hex string `json:"hex"`
		} `json:"dpid"`
		NumPorts         uint16 `json:"n_ports"`
		FirstPort        uint16 `json:"first_port"`
		FirstPrintedPort uint16 `json:"first_printed_port"`
		Description      string `json:"description"`
	})

	s.ID = r.ID
	s.DPID.Int = r.DPID
	s.DPID.Hex = hexDPID(r.DPID)
	s.NumPorts = r.NumPorts
	s.FirstPort = r.FirstPort
	s.FirstPrintedPort = r.FirstPrintedPort
	s.Description = r.Description

	return json.Marshal(&s)
}

func hexDPID(dpid uint64) string {
	hex := fmt.Sprintf("%016x", dpid)
	re := regexp.MustCompile("..")
	return strings.TrimRight(re.ReplaceAllString(hex, "$0:"), ":")
}

func (r *API) listSwitch(w api.ResponseWriter, req *rest.Request) {
	p := new(listSwitchParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listSwitch request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var sw []*Switch
	f := func(tx Transaction) (err error) {
		sw, err = tx.Switches(p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the switch list: %v", err.Error())})
		return
	}
	logger.Debugf("queried switch list: %v", spew.Sdump(sw))

	w.Write(api.Response{Status: api.StatusOkay, Data: sw})
}

type listSwitchParam struct {
	SessionID  string
	Pagination Pagination
}

func (r *listSwitchParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listSwitchParam(v)

	return r.validate()
}

func (r *listSwitchParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.Pagination.Limit == 0 {
		return errors.New("invalid pagination limit")
	}

	return nil
}

func (r *API) addSwitch(w api.ResponseWriter, req *rest.Request) {
	p := new(addSwitchParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("addSwitch request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var sw *Switch
	var duplicated bool
	f := func(tx Transaction) (err error) {
		sw, duplicated, err = tx.AddSwitch(session.(*User).ID, p.DPID, p.NumPorts, p.FirstPort, p.FirstPrintedPort, p.Description)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new switch: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated switch: dpid=%v", p.DPID)})
		return
	}
	logger.Debugf("added switch info: %v", spew.Sdump(sw))

	w.Write(api.Response{Status: api.StatusOkay, Data: sw})
}

type addSwitchParam struct {
	SessionID        string
	DPID             uint64
	NumPorts         uint16
	FirstPort        uint16
	FirstPrintedPort uint16
	Description      string
}

func (r *addSwitchParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID        string `json:"session_id"`
		DPID             string `json:"dpid"`
		NumPorts         uint16 `json:"n_ports"`
		FirstPort        uint16 `json:"first_port"`
		FirstPrintedPort uint16 `json:"first_printed_port"`
		Description      string `json:"description"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	if len(v.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if v.NumPorts == 0 {
		return errors.New("invalid number of ports")
	}
	if v.NumPorts > 512 {
		return errors.New("too many ports")
	}
	if utf8.RuneCountInString(v.Description) > 255 {
		return errors.New("too long description")
	}
	if uint32(v.FirstPort)+uint32(v.NumPorts) > 0xFFFF {
		return errors.New("too high first port number")
	}
	ok, err := regexp.MatchString("^([0-9a-fA-F]{2}:){7}([0-9a-fA-F]{2})$", v.DPID)
	if err != nil {
		return err
	}

	// Is the DP id in hex format?
	if ok {
		v.DPID = strings.Replace(v.DPID, ":", "", -1)
		if r.DPID, err = strconv.ParseUint(v.DPID, 16, 64); err != nil {
			return err
		}
	} else {
		if r.DPID, err = strconv.ParseUint(v.DPID, 10, 64); err != nil {
			return err
		}
	}

	r.SessionID = v.SessionID
	r.NumPorts = v.NumPorts
	r.FirstPort = v.FirstPort
	r.FirstPrintedPort = v.FirstPrintedPort
	r.Description = v.Description

	return nil
}

func (r *API) removeSwitch(w api.ResponseWriter, req *rest.Request) {
	p := new(removeSwitchParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("removeSwitch request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var sw *Switch
	f := func(tx Transaction) (err error) {
		sw, err = tx.RemoveSwitch(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove a switch: %v", err.Error())})
		return
	}

	if sw == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found switch to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed a switch: %v", spew.Sdump(sw))

	logger.Debug("removing all flows from the entire switches")
	if err := r.Controller.RemoveFlows(); err != nil {
		// Ignore this error.
		logger.Errorf("failed to remove flows: %v", err)
	} else {
		logger.Debug("removed all flows from the entire switches")
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeSwitchParam struct {
	SessionID string
	ID        uint64
}

func (r *removeSwitchParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeSwitchParam(v)

	return r.validate()
}

func (r *removeSwitchParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid switch id")
	}

	return nil
}


================================================
FILE: api/ui/user.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/superkkt/cherry/api"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
	"github.com/pquerna/otp"
	"github.com/pquerna/otp/totp"
)

type UserTransaction interface {
	User(name string) (*User, error)
	Users(Pagination) ([]*User, error)
	AddUser(requesterID uint64, name, key string) (user *User, duplicated bool, err error)
	// UpdateUser updates enabled and admin authorization of a user specified by id and then returns information of the user. It returns nil if the user does not exist.
	UpdateUser(requesterID, userID uint64, enabled, admin *bool) (*User, error)
	ResetOTPKey(name, key string) (ok bool, err error)
}

type User struct {
	ID        uint64
	Name      string
	Key       string // Key used in OTP Authentication.
	Enabled   bool
	Admin     bool
	Timestamp time.Time
}

func (r *User) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		ID        uint64 `json:"id"`
		Name      string `json:"name"`
		Enabled   bool   `json:"enabled"`
		Admin     bool   `json:"admin"`
		Timestamp int64  `json:"timestamp"`
	}{
		ID:        r.ID,
		Name:      r.Name,
		Enabled:   r.Enabled,
		Admin:     r.Admin,
		Timestamp: r.Timestamp.Unix(),
	})
}

func (r *API) login(w api.ResponseWriter, req *rest.Request) {
	p := new(loginParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("login request from %v: %v", req.RemoteAddr, spew.Sdump(&struct {
		Name string `json:"name"`
		Code string `json:"code"`
	}{
		Name: p.Name,
		Code: p.Code,
	}))

	var user *User
	f := func(tx Transaction) (err error) {
		user, err = tx.User(p.Name)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query an user account: %v", err.Error())})
		return
	}

	if user == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found user to login: %v", p.Name)})
		return
	}
	if user.Enabled == false {
		w.Write(api.Response{Status: api.StatusBlockedAccount, Message: fmt.Sprintf("login attempt with a blocked account: %v", p.Name)})
		return
	}

	ok, err := r.LDAP.Auth(p.Name, p.Password)
	if err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to authenticate an user account: %v", err.Error())})
		return
	}
	if ok == false {
		w.Write(api.Response{Status: api.StatusIncorrectCredential, Message: fmt.Sprintf("incorrect username or password: %v", p.Name)})
		return
	}

	if ok := totp.Validate(p.Code, user.Key); ok == false {
		w.Write(api.Response{Status: api.StatusIncorrectCredential, Message: fmt.Sprintf("incorrect OTP code: %v", p.Code)})
		return
	}

	id := r.session.Add(user)
	logger.Debugf("login success: user=%v, sessionID=%v", spew.Sdump(user), id)

	w.Write(api.Response{
		Status: api.StatusOkay,
		Data: struct {
			SessionID string `json:"session_id"`
			ID        uint64 `json:"id"`
			Admin     bool   `json:"admin"`
		}{
			SessionID: id,
			ID:        user.ID,
			Admin:     user.Admin,
		},
	})
}

type loginParam struct {
	Name     string
	Password string
	Code     string // OTP Authentication Code.
}

func (r *loginParam) UnmarshalJSON(data []byte) error {
	v := struct {
		Name     string `json:"name"`
		Password string `json:"password"`
		Code     string `json:"code"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = loginParam(v)

	return r.validate()
}

func (r *loginParam) validate() error {
	if len(r.Name) == 0 {
		return errors.New("empty name")
	}
	if len(r.Password) == 0 {
		return errors.New("empty password")
	}
	if len(r.Code) != 6 {
		return fmt.Errorf("invalid OTP code: %v", r.Code)
	}

	return nil
}

func (r *API) logout(w api.ResponseWriter, req *rest.Request) {
	p := new(logoutParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("logout request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if r.session.Remove(p.SessionID) == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("logout attempt with an unknown session ID: %v", p.SessionID)})
		return
	}
	logger.Debugf("session removed: sessionID=%v", p.SessionID)

	w.Write(api.Response{Status: api.StatusOkay})
}

type logoutParam struct {
	SessionID string
}

func (r *logoutParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = logoutParam(v)

	return r.validate()
}

func (r *logoutParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}

	return nil
}

func (r *API) listUser(w api.ResponseWriter, req *rest.Request) {
	p := new(listUserParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listUser request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}
	if session.(*User).Admin == false {
		w.Write(api.Response{Status: api.StatusPermissionDenied, Message: fmt.Sprintf("not allowed session id: %v", p.SessionID)})
		return
	}

	var user []*User
	f := func(tx Transaction) (err error) {
		user, err = tx.Users(p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the user accounts: %v", err.Error())})
		return
	}
	logger.Debugf("queried user accounts: %v", spew.Sdump(user))

	w.Write(api.Response{Status: api.StatusOkay, Data: user})
}

type listUserParam struct {
	SessionID  string
	Pagination Pagination
}

func (r *listUserParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listUserParam(v)

	return r.validate()
}

func (r *listUserParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.Pagination.Limit == 0 {
		return errors.New("invalid pagination limit")
	}

	return nil
}

func (r *API) addUser(w api.ResponseWriter, req *rest.Request) {
	p := new(addUserParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("addUser request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}
	if session.(*User).Admin == false {
		w.Write(api.Response{Status: api.StatusPermissionDenied, Message: fmt.Sprintf("not allowed session id: %v", p.SessionID)})
		return
	}

	key, err := generateOTPKey(p.Name)
	if err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to generate OTP key: %v", err)})
		return
	}

	var user *User
	var duplicated bool
	f := func(tx Transaction) (err error) {
		user, duplicated, err = tx.AddUser(session.(*User).ID, p.Name, key.Secret())
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new user account: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated user account: %v", p.Name)})
		return
	}
	logger.Debugf("added the user account: %v", spew.Sdump(user))

	w.Write(api.Response{
		Status: api.StatusOkay,
		Data: &struct {
			User *User  `json:"user"`
			OTP  string `json:"otp"`
		}{
			User: user,
			OTP:  key.String(),
		},
	})
}

type addUserParam struct {
	SessionID string
	Name      string
}

func (r *addUserParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = addUserParam(v)

	return r.validate()
}

func (r *addUserParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if len(r.Name) == 0 {
		return errors.New("empty name")
	}

	return nil
}

func generateOTPKey(account string) (*otp.Key, error) {
	return totp.Generate(totp.GenerateOpts{
		Issuer:      "Cherry",
		AccountName: account,
	})
}

func (r *API) updateUser(w api.ResponseWriter, req *rest.Request) {
	p := new(updateUserParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("updateUser request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}
	if session.(*User).Admin == false {
		w.Write(api.Response{Status: api.StatusPermissionDenied, Message: fmt.Sprintf("not allowed session id: %v", p.SessionID)})
		return
	}

	var user *User
	f := func(tx Transaction) (err error) {
		user, err = tx.UpdateUser(session.(*User).ID, p.ID, p.Enabled, p.Admin)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to update a user account: %v", err.Error())})
		return
	}

	if user == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found user to update: %v", p.ID)})
		return
	}
	logger.Debugf("updated the user account: %v", spew.Sdump(user))

	w.Write(api.Response{Status: api.StatusOkay, Data: user})
}

type updateUserParam struct {
	SessionID string
	ID        uint64
	Enabled   *bool
	Admin     *bool
}

func (r *updateUserParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
		Enabled   *bool  `json:"enabled"`
		Admin     *bool  `json:"admin"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = updateUserParam(v)

	return r.validate()
}

func (r *updateUserParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid user ID")
	}
	if r.Enabled == nil && r.Admin == nil {
		return errors.New("empty parameter")
	}

	return nil
}

func (r *API) resetOTP(w api.ResponseWriter, req *rest.Request) {
	p := new(resetOTPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode params: %v", err.Error())})
		return
	}
	logger.Debugf("resetOTP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}
	if session.(*User).Admin == false {
		w.Write(api.Response{Status: api.StatusPermissionDenied, Message: fmt.Sprintf("not allowed session id: %v", p.SessionID)})
		return
	}

	key, err := generateOTPKey(p.Name)
	if err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to generate OTP key: %v", err)})
		return
	}

	f := func(tx Transaction) (err error) {
		ok, err = tx.ResetOTPKey(p.Name, key.Secret())
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to reset OTP of a user account: %v", err.Error())})
		return
	}

	if ok == false {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found user to reset OTP: %v", p.Name)})
		return
	}
	logger.Debugf("reset OTP of the user account: %v", p.Name)

	w.Write(api.Response{Status: api.StatusOkay, Data: key.String()})
}

type resetOTPParam struct {
	SessionID string
	Name      string
}

func (r *resetOTPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		Name      string `json:"name"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = resetOTPParam(v)

	return r.validate()
}

func (r *resetOTPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if len(r.Name) == 0 {
		return errors.New("empty name")
	}

	return nil
}


================================================
FILE: api/ui/vip.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package ui

import (
	"encoding/json"
	"errors"
	"fmt"
	"unicode/utf8"

	"github.com/superkkt/cherry/api"
	"github.com/superkkt/cherry/network"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/davecgh/go-spew/spew"
)

type VIPTransaction interface {
	VIPs(Pagination) ([]*VIP, error)
	AddVIP(requesterID, ipID, activeID, standbyID uint64, desc string) (vip *VIP, duplicated bool, err error)
	// RemoveVIP removes a VIP specified by id and then returns information of the VIP before removing. It returns nil if the VIP does not exist.
	RemoveVIP(requesterID, vipID uint64) (*VIP, error)
	// ToggleVIP swaps active host and standby host of a VIP specified by id and then returns information of the VIP. It returns nil if the VIP does not exist.
	ToggleVIP(requesterID, vipID uint64) (*VIP, error)
}

type VIP struct {
	ID          uint64 `json:"id"`
	IP          string `json:"ip"` // FIXME: Use a native type.
	ActiveHost  Host   `json:"active_host"`
	StandbyHost Host   `json:"standby_host"`
	Description string `json:"description"`
}

func (r *API) listVIP(w api.ResponseWriter, req *rest.Request) {
	p := new(listVIPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("listVIP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	if _, ok := r.session.Get(p.SessionID); ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var vip []*VIP
	f := func(tx Transaction) (err error) {
		vip, err = tx.VIPs(p.Pagination)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to query the VIP list: %v", err.Error())})
		return
	}
	logger.Debugf("queried VIP list: %v", spew.Sdump(vip))

	w.Write(api.Response{Status: api.StatusOkay, Data: vip})
}

type listVIPParam struct {
	SessionID  string
	Pagination Pagination
}

func (r *listVIPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID  string     `json:"session_id"`
		Pagination Pagination `json:"pagination"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = listVIPParam(v)

	return r.validate()
}

func (r *listVIPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.Pagination.Limit == 0 {
		return errors.New("invalid pagination limit")
	}

	return nil
}

func (r *API) addVIP(w api.ResponseWriter, req *rest.Request) {
	p := new(addVIPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("addVIP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var vip *VIP
	var duplicated bool
	f := func(tx Transaction) (err error) {
		vip, duplicated, err = tx.AddVIP(session.(*User).ID, p.IPID, p.ActiveHostID, p.StandbyHostID, p.Description)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to add a new VIP: %v", err.Error())})
		return
	}

	if duplicated {
		w.Write(api.Response{Status: api.StatusDuplicated, Message: fmt.Sprintf("duplicated VIP: ip_id=%v", p.IPID)})
		return
	}
	logger.Debugf("added a new VIP: %v", spew.Sdump(vip))

	if err := r.announce(vip.IP, vip.ActiveHost.MAC); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay, Data: vip})
}

type addVIPParam struct {
	SessionID     string
	IPID          uint64
	ActiveHostID  uint64
	StandbyHostID uint64
	Description   string
}

func (r *addVIPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID     string `json:"session_id"`
		IPID          uint64 `json:"ip_id"`
		ActiveHostID  uint64 `json:"active_host_id"`
		StandbyHostID uint64 `json:"standby_host_id"`
		Description   string `json:"description"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = addVIPParam(v)

	return r.validate()
}

func (r *addVIPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ActiveHostID == 0 {
		return errors.New("invalid active host id")
	}
	if r.StandbyHostID == 0 {
		return errors.New("invalid standby host id")
	}
	if r.ActiveHostID == r.StandbyHostID {
		return errors.New("same host for the active and standby")
	}
	if utf8.RuneCountInString(r.Description) > 255 {
		return errors.New("too long description")
	}

	return nil
}

func (r *API) removeVIP(w api.ResponseWriter, req *rest.Request) {
	p := new(removeVIPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("removeVIP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var vip *VIP
	f := func(tx Transaction) (err error) {
		vip, err = tx.RemoveVIP(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to remove a VIP: %v", err.Error())})
		return
	}

	if vip == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found VIP to remove: %v", p.ID)})
		return
	}
	logger.Debugf("removed the VIP: %v", spew.Sdump(vip))

	if err := r.announce(vip.IP, network.NullMAC.String()); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type removeVIPParam struct {
	SessionID string
	ID        uint64
}

func (r *removeVIPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = removeVIPParam(v)

	return r.validate()
}

func (r *removeVIPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid VIP id")
	}

	return nil
}

func (r *API) toggleVIP(w api.ResponseWriter, req *rest.Request) {
	p := new(toggleVIPParam)
	if err := req.DecodeJsonPayload(p); err != nil {
		w.Write(api.Response{Status: api.StatusInvalidParameter, Message: fmt.Sprintf("failed to decode param: %v", err.Error())})
		return
	}
	logger.Debugf("toggleVIP request from %v: %v", req.RemoteAddr, spew.Sdump(p))

	session, ok := r.session.Get(p.SessionID)
	if ok == false {
		w.Write(api.Response{Status: api.StatusUnknownSession, Message: fmt.Sprintf("unknown session id: %v", p.SessionID)})
		return
	}

	var vip *VIP
	f := func(tx Transaction) (err error) {
		vip, err = tx.ToggleVIP(session.(*User).ID, p.ID)
		return err
	}
	if err := r.DB.Exec(f); err != nil {
		w.Write(api.Response{Status: api.StatusInternalServerError, Message: fmt.Sprintf("failed to toggle a VIP: %v", err.Error())})
		return
	}

	if vip == nil {
		w.Write(api.Response{Status: api.StatusNotFound, Message: fmt.Sprintf("not found VIP to toggle: %v", p.ID)})
		return
	}
	logger.Debugf("toggled the VIP: %v", spew.Sdump(vip))

	if err := r.announce(vip.IP, vip.ActiveHost.MAC); err != nil {
		// Ignore this error.
		logger.Errorf("failed to send ARP announcement: %v", err)
	}

	w.Write(api.Response{Status: api.StatusOkay})
}

type toggleVIPParam struct {
	SessionID string
	ID        uint64
}

func (r *toggleVIPParam) UnmarshalJSON(data []byte) error {
	v := struct {
		SessionID string `json:"session_id"`
		ID        uint64 `json:"id"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	*r = toggleVIPParam(v)

	return r.validate()
}

func (r *toggleVIPParam) validate() error {
	if len(r.SessionID) != 64 {
		return errors.New("invalid session id")
	}
	if r.ID == 0 {
		return errors.New("invalid VIP id")
	}

	return nil
}


================================================
FILE: cmd/cherry/cherry.yaml
================================================
default:
    port: 6633
    # The logger will only write log messages whose level is equal to or higher than log_level.
    # Lower log level is more verbose. (DEBUG < INFO < WARNING < ERROR < CRITICAL)
    # This log_level value can be dynamically changed without restarting the daemon.
    log_level: "INFO"
    # North-bound applications separated by comma. They will receive a packet in order they appear.
    applications: "DHCP, VirtualIP, Discovery, Monitor, ProxyARP, L2Switch, Announcer"
    # Email address that will be notified when an abnormal events occur.
    admin_email: "name@domain.com"
    # Default VLAN ID. All switches should have this VLAN ID on all OF ports.
    vlan_id: 1000

mysql:
    # host:port[,host:port,host:port,...]
    addr: "localhost:3306"
    username: "username"
    password: "password"
    name: "dbname"

rest:
    port: 7070
    tls: true
    cert_file: "/your_tls_cert_file"
    key_file: "/your_tls_key_file"

================================================
FILE: cmd/cherry/main.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.
 * Kitae Kim <superkkt@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package main

import (
	"context"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/superkkt/cherry"
	"github.com/superkkt/cherry/api"
	"github.com/superkkt/cherry/api/core"
	"github.com/superkkt/cherry/database"
	"github.com/superkkt/cherry/election"
	"github.com/superkkt/cherry/log"
	"github.com/superkkt/cherry/network"
	"github.com/superkkt/cherry/northbound"

	"github.com/fsnotify/fsnotify"
	"github.com/pkg/errors"
	"github.com/superkkt/go-logging"
	"github.com/superkkt/viper"
)

const (
	programName     = "cherry"
	programVersion  = cherry.Version
	defaultLogLevel = logging.INFO
)

var (
	logger            = logging.MustGetLogger("main")
	loggerLeveled     logging.LeveledBackend
	showVersion       = flag.Bool("version", false, "Show program version and exit")
	defaultConfigFile = flag.String("config", fmt.Sprintf("/usr/local/etc/%v.yaml", programName), "absolute path of the configuration file")
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()
	if *showVersion {
		fmt.Printf("Version: %v\n", programVersion)
		os.Exit(0)
	}

	initConfig()
	if err := initLog(getLogLevel(viper.GetString("default.log_level"))); err != nil {
		logger.Fatalf("failed to init log: %v", err)
	}

	ctx, cancel := context.WithCancel(context.Background())
	db, err := database.NewMySQL()
	if err != nil {
		logger.Fatalf("failed to init MySQL database: %v", err)
	}

	observer := initElectionObserver(ctx, db)
	controller := network.NewController(db)
	initAPIServer(observer, controller)
	manager, err := createAppManager(db)
	if err != nil {
		logger.Fatalf("failed to create application manager: %v", err)
	}
	manager.AddEventSender(controller)

	initSignalHandler(controller, manager, cancel)

	listen(ctx, viper.GetInt("default.port"), controller, observer)
}

func initConfig() {
	viper.SetConfigFile(*defaultConfigFile)
	// Read the config file.
	if err := viper.ReadInConfig(); err != nil {
		logger.Fatalf("failed to read the config file: %v", err)
	}
	// Watching and re-reading config file whenever it changes.
	viper.OnConfigChange(func(e fsnotify.Event) {
		// Ignore the WRITE operation to avoid reading empty config.
		if e.Op != fsnotify.Write {
			return
		}

		if loggerLeveled != nil {
			// Set log level for all modules
			loggerLeveled.SetLevel(getLogLevel(viper.GetString("default.log_level")), "")
		}
	})
	viper.WatchConfig()
	if err := validateConfig(); err != nil {
		logger.Fatalf("failed to validate the configuration: %v", err)
	}
}

func validateConfig() error {
	if port := viper.GetInt("default.port"); port <= 0 || port > 0xFFFF {
		return errors.New("invalid default.port")
	}
	if len(viper.GetString("default.log_level")) == 0 {
		return errors.New("invalid default.log_level")
	}
	if len(viper.GetString("default.applications")) == 0 {
		return errors.New("invalid default.applications")
	}
	if len(viper.GetString("default.admin_email")) == 0 {
		return errors.New("invalid default.admin_email")
	}
	vlanID := viper.GetInt("default.vlan_id")
	if vlanID < 0 || vlanID > 4095 {
		return errors.New("invalid default.vlan_id in the config file")
	}

	return nil
}

func initElectionObserver(ctx context.Context, db *database.MySQL) *election.Observer {
	observer := election.New(db)
	go func() {
		if err := observer.Run(ctx); err != nil {
			logger.Fatalf("failed to run the election observer: %v", err)
		}
		logger.Debugf("election observer terminated")
	}()

	return observer
}

func initAPIServer(observer *election.Observer, controller *network.Controller) {
	go func() {
		s := api.Server{}
		s.Port = uint16(viper.GetInt("rest.port"))
		if viper.GetBool("rest.tls") == true {
			s.TLS.Cert = viper.GetString("rest.cert_file")
			s.TLS.Key = viper.GetString("rest.key_file")
		}
		s.Observer = observer
		s.Controller = controller

		srv := &core.API{Server: s}
		if err := srv.Serve(); err != nil {
			logger.Fatalf("failed to run the API server: %v", err)
		}
	}()
}

func initSignalHandler(controller *network.Controller, manager *northbound.Manager, cancel context.CancelFunc) {
	go func() {
		c := make(chan os.Signal, 5)
		// All incoming signals will be transferred to the channel
		signal.Notify(c)

		// Infinte loop.
		for {
			s := <-c
			if s == syscall.SIGTERM || s == syscall.SIGINT {
				// Graceful shutdown
				logger.Warning("Shutting down...")
				cancel()
				// Timeout for cancelation
				time.Sleep(5 * time.Second)
				os.Exit(0)
			} else if s == syscall.SIGHUP {
				fmt.Println("* Controller status:")
				fmt.Println(controller.String())
				fmt.Printf("\n* Manager status:\n")
				fmt.Println(manager.String())
			}
		}
	}()
}

func initLog(level logging.Level) error {
	backend, err := log.NewSyslog(programName)
	if err != nil {
		return err
	}
	backend = logging.NewBackendFormatter(backend, logging.MustStringFormatter(`%{level}: %{shortpkg}.%{shortfunc}: %{message}`))

	loggerLeveled = logging.AddModuleLevel(backend)
	// Set log level for all modules
	loggerLeveled.SetLevel(level, "")
	logging.SetBackend(loggerLeveled)

	return nil
}

func getLogLevel(level string) logging.Level {
	level = strings.ToUpper(level)
	ret, err := logging.LogLevel(level)
	if err != nil {
		logger.Infof("invalid log level=%v, defaulting to %v..", level, defaultLogLevel)
		return defaultLogLevel
	}

	return ret
}

func listen(ctx context.Context, port int, controller *network.Controller, observer *election.Observer) {
	type KeepAliver interface {
		SetKeepAlive(keepalive bool) error
		SetKeepAlivePeriod(d time.Duration) error
	}

	listener, err := net.Listen("tcp", fmt.Sprintf(":%v", port))
	if err != nil {
		logger.Errorf("failed to listen on %v port: %v", port, err)
		return
	}
	defer listener.Close()

	// Connection dispatcher.
	f := func(c chan<- net.Conn) {
		for {
			conn, err := listener.Accept()
			if err != nil {
				logger.Errorf("failed to accept a new connection: %v", err)
				continue
			}
			logger.Infof("new device is connected from %v", conn.RemoteAddr())

			// Only the master controller can serve the connections!
			if observer.IsMaster() == false {
				logger.Warningf("disconnecting the newly connected device (%v) because we are not the master controller!", conn.RemoteAddr())
				conn.Close()
				continue
			}

			// Pass the new connection into the backlog queue.
			c <- conn
		}
	}
	backlog := make(chan net.Conn, 32)
	go f(backlog)

	// Infinite loop
	for {
		select {
		case <-ctx.Done():
			logger.Debug("terminating the main listener loop...")
			return
		case conn := <-backlog:
			logger.Debug("fetching a new connection from the backlog..")
			if v, ok := conn.(KeepAliver); ok {
				logger.Debug("trying to enable socket keepalive..")
				if err := v.SetKeepAlive(true); err == nil {
					logger.Debug("setting socket keepalive period...")
					// Makes a broken connection will be disconnected within 45 seconds.
					// http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html
					v.SetKeepAlivePeriod(time.Duration(5) * time.Second)
				} else {
					logger.Errorf("failed to enable socket keepalive: %v", err)
				}
			}
			controller.AddConnection(ctx, conn)
		}
	}
}

func createAppManager(db *database.MySQL) (*northbound.Manager, error) {
	manager, err := northbound.NewManager(db)
	if err != nil {
		return nil, err
	}

	apps, err := parseApplications()
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse applications")
	}
	for _, v := range apps {
		if err := manager.Enable(v); err != nil {
			return nil, errors.Wrap(err, fmt.Sprintf("enabling %v", v))
		}
	}

	return manager, nil
}

func parseApplications() ([]string, error) {
	// Remove spaces, and then split it using comma
	tokens := strings.Split(strings.Replace(viper.GetString("default.applications"), " ", "", -1), ",")
	if len(tokens) == 0 {
		return nil, errors.New("empty application")
	}

	return tokens, nil
}


================================================
FILE: cmd/walnut/main.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.
 *
 *  Kitae Kim <superkkt@sds.co.kr>
 *  Donam Kim <donam.kim@sds.co.kr>
 *  Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *  Changjin Choi <ccj9707@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/superkkt/cherry"
	"github.com/superkkt/cherry/api"
	"github.com/superkkt/cherry/api/ui"
	"github.com/superkkt/cherry/database"
	"github.com/superkkt/cherry/ldap"
	"github.com/superkkt/cherry/log"

	"github.com/fsnotify/fsnotify"
	"github.com/superkkt/go-logging"
	"github.com/superkkt/viper"
)

const (
	programName     = "walnut"
	programVersion  = cherry.Version
	defaultLogLevel = logging.INFO
)

var (
	logger        = logging.MustGetLogger("main")
	loggerLeveled logging.LeveledBackend

	showHelp          = flag.Bool("help", false, "show this help and exit")
	showVersion       = flag.Bool("version", false, "show program version and exit")
	defaultConfigFile = flag.String("config", fmt.Sprintf("/usr/local/etc/%v.yaml", programName), "absolute path of the configuration file")
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	rand.Seed(time.Now().Unix())
}

func main() {
	parseCmdLines()
	initConfig()
	initLog()
	initAPIServer()
	waitSignal()
	logger.Infof("%v (version %v) shutdown complete!", programName, programVersion)
}

// Handle the command-line arguments.
func parseCmdLines() {
	flag.Parse()
	if *showHelp {
		flag.Usage()
		os.Exit(0)
	}
	if *showVersion {
		fmt.Printf("%v v%v\n", programName, programVersion)
		os.Exit(0)
	}
}

func initConfig() {
	viper.SetConfigFile(*defaultConfigFile)

	// Read the config file.
	if err := viper.ReadInConfig(); err != nil {
		logger.Fatalf("failed to read the config file: %v", err)
	}

	// Watching and re-reading config file whenever it changes.
	viper.OnConfigChange(func(e fsnotify.Event) {
		// Ignore all the fsnotify operations except WRITE to avoid reading empty config.
		if e.Op != fsnotify.Write {
			return
		}
		logger.Infof("config file changed: %v", e.Name)
		// Set log level for all modules
		loggerLeveled.SetLevel(getLogLevel(), "")
	})
	viper.WatchConfig()

	if err := validateConfig(); err != nil {
		logger.Fatalf("invalid configuration: %v", err)
	}
}

// validateConfig validates essential configurations.
func validateConfig() error {
	// TODO: Add validation you want.
	return nil
}

func initLog() {
	logDriver := viper.GetString("log.driver")

	var err error
	var backend logging.Backend
	switch strings.ToLower(logDriver) {
	case "stderr":
		backend = logging.NewLogBackend(os.Stderr, "", 0)
		backend = logging.NewBackendFormatter(backend, logging.MustStringFormatter(`%{time} [%{pid}] %{level}: %{shortpkg}.%{longfunc}: %{message}`))
	case "syslog":
		backend, err = log.NewSyslog(programName)
		if err != nil {
			logger.Fatalf("failed to init log: %v", err)
		}
		backend = logging.NewBackendFormatter(backend, logging.MustStringFormatter(`%{level}: %{shortpkg}.%{longfunc}: %{message}`))
	default:
		logger.Fatalf("unsupported log driver: %v", logDriver)
	}

	loggerLeveled = logging.AddModuleLevel(backend)
	// Set log level for all modules
	loggerLeveled.SetLevel(getLogLevel(), "")
	logging.SetBackend(loggerLeveled)
}

func getLogLevel() logging.Level {
	level := strings.ToUpper(viper.GetString("log.level"))
	ret, err := logging.LogLevel(level)
	if err != nil {
		logger.Errorf("invalid log.level=%v, defaulting to %v..", level, defaultLogLevel)
		return defaultLogLevel
	}

	return ret
}

func initDatabase() *database.MySQL {
	db, err := database.NewMySQL()
	if err != nil {
		logger.Fatalf("failed to init MySQL database: %v", err)
	}

	return db
}

func initCoreSDK() *coreSDK {
	client, err := newCoreSDK(viper.GetString("core_api_url"))
	if err != nil {
		logger.Fatalf("failed to init the core API's SDK: %v", err)
	}

	return client
}

func initLDAPClient() *ldap.Client {
	return ldap.New(viper.Sub("ldap"), 5)
}

func initAPIServer() {
	go func() {
		s := api.Server{}
		s.Port = uint16(viper.GetInt("rest.port"))
		if viper.GetBool("rest.tls") == true {
			s.TLS.Cert = viper.GetString("rest.cert_file")
			s.TLS.Key = viper.GetString("rest.key_file")
		}
		sdk := initCoreSDK()
		s.Observer = sdk
		s.Controller = sdk

		srv := &ui.API{Server: s, DB: initDatabase(), LDAP: initLDAPClient()}
		if err := srv.Serve(); err != nil {
			logger.Fatalf("failed to run the API server: %v", err)
		}
	}()
}

// waitSignal waits until we receive SIGTERM or SIGINT signals.
func waitSignal() {
	c := make(chan os.Signal, 1)
	// Following signals will be transferred to the channel c.
	signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGPIPE)

	// Infinite loop.
	for {
		s := <-c
		switch s {
		case syscall.SIGTERM, syscall.SIGINT:
			logger.Infof("caught %v signal: shutting down...", s)
			return
		default:
			logger.Infof("caught %v signal: ignored!", s)
		}
	}
}


================================================
FILE: cmd/walnut/sdk.go
================================================
/*
 * Copyright 2019 Samjung Data Service, Inc. All Rights Reserved.
 *
 * Authors:
 * 	Kitae Kim <superkkt@sds.co.kr>
 * 	Donam Kim <donam.kim@sds.co.kr>
 *	Jooyoung Kang <jooyoung.kang@sds.co.kr>
 *	Changjin Choi <ccj9707@sds.co.kr>
 */

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"time"
)

type coreSDK struct {
	baseURL string
	client  *http.Client
}

func newCoreSDK(baseURL string) (*coreSDK, error) {
	if _, err := url.Parse(baseURL); err != nil {
		return nil, err
	}

	return &coreSDK{
		baseURL: baseURL,
		client: &http.Client{
			Transport: &http.Transport{
				TLSHandshakeTimeout: 10 * time.Second,
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: true,
				},
			},
			Timeout: 30 * time.Second,
		},
	}, nil
}

func (r *coreSDK) Announce(ip net.IP, mac net.HardwareAddr) error {
	arg := &struct {
		IP  string `json:"ip"`
		MAC string `json:"mac"`
	}{
		IP:  ip.String(),
		MAC: mac.String(),
	}

	return r.call("POST", "/api/v1/announce", arg, nil)
}

func (r *coreSDK) RemoveFlows() error {
	return r.call("POST", "/api/v1/remove", nil, nil)
}

func (r *coreSDK) RemoveFlowsByMAC(mac net.HardwareAddr) error {
	arg := &struct {
		MAC string `json:"mac"`
	}{mac.String()}

	return r.call("POST", "/api/v1/remove", arg, nil)
}

func (r *coreSDK) IsMaster() bool {
	res := new(struct {
		Master bool `json:"master"`
	})
	if err := r.call("POST", "/api/v1/status", nil, res); err != nil {
		return false
	}

	return res.Master
}

func (r *coreSDK) call(method, command string, param interface{}, result interface{}) error {
	payload, err := json.Marshal(param)
	if err != nil {
		return err
	}
	logger.Debugf("REST request: %v", string(payload))

	req, err := http.NewRequest(method, r.baseURL+command, bytes.NewReader(payload))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")

	resp, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("unexpected HTTP status code: %v", resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	logger.Debugf("REST response: %v", string(body))

	res := new(struct {
		Status  int             `json:"status"`
		Message string          `json:"message"`
		Data    json.RawMessage `json:"data"`
	})
	if err := json.Unmarshal(body, res); err != nil {
		return err
	}
	if res.Status != 200 {
		return fmt.Errorf("unexpected response status: status=%v, message=%v", res.Status, res.Message)
	}

	if result == nil {
		// Ignore the query result.
		return nil
	}

	return json.Unmarshal(res.Data, &result)
}


================================================
FILE: cmd/walnut/walnut.yaml
================================================
# NOTE:
#
# Parameters marked as a DYNAMIC can be dynamically updated without restarting the daemon.

log:
    # (DYNAMIC)
    # The logger will only write log messages whose level is equal to or higher
    # than this level. It should be one of DEBUG, INFO, WARNING, ERROR or CRITICAL.
    # Lower log level is more verbose. (DEBUG < INFO < WARNING < ERROR < CRITICAL)
    level: "INFO"
    # log_driver can be one of stderr or syslog.
    driver: "stderr"

mysql:
    # host:port[,host:port,host:port,...]
    addr: "localhost:3306"
    username: "username"
    password: "password"
    name: "database"

rest:
    port: 4500
    tls: true
    cert_file: "/your_tls_cert_file"
    key_file: "/your_tls_key_file"

core_api_url: "http://localhost:7070"

ldap:
    addr: "localhost:636"
    base_dn: "DC=direct,DC=co,DC=kr"
    admin:
        name: "name"
        password: "password"
    attr:
        login: "sAMAccountName"

================================================
FILE: database/mysql.go
================================================
/*
 * Cherry - An OpenFlow Controller
 *
 * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.
 * Kitae Kim <superkkt@sds.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package database

import (
	"database/sql"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"math"
	"math/rand"
	"net"
	"runtime"
	"strings"
	"time"

	"github.com/superkkt/cherry/api/ui"
	"github.com/superkkt/cherry/network"
	"github.com/superkkt/cherry/northbound/app/announcer"
	"github.com/superkkt/cherry/northbound/app/dhcp"
	"github.com/superkkt/cherry/northbound/app/discovery"
	"github.com/superkkt/cherry/northbound/app/virtualip"

	"github.com/go-sql-driver/mysql"
	"github.com/superkkt/go-logging"
	"github.com/superkkt/viper"
)

const (
	maxDeadlockRetry = 5

	deadlockErrCode   uint16 = 1213
	duplicatedErrCode uint16 = 1062
	foreignkeyErrCode uint16 = 1451

	clusterDialerNetwork = "cluster"
)

var (
	logger = logging.MustGetLogger("database")

	maxIdleConn = runtime.NumCPU()
	maxOpenConn = maxIdleConn * 2
)

type MySQL struct {
	db     *sql.DB
	random *rand.Rand
}

func NewMySQL() (*MySQL, error) {
	addr := viper.GetString("mysql.addr")
	if err := validateClusterAddr(addr); err != nil {
		return nil, err
	}
	// Register the custom dialer.
	mysql.RegisterDial(clusterDialerNetwork, clusterDialer)

	param := "readTimeout=1m&writeTimeout=1m&parseTime=true&loc=Local&maxAllowedPacket=0"
	dsn := fmt.Sprintf("%v:%v@%v(%v)/%v?%v", viper.GetString("mysql.username"), viper.GetString("mysql.password"), clusterDialerNetwork, addr, viper.GetString("mysql.name"), param)
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, err
	}
	db.SetMaxOpenConns(maxOpenConn)
	db.SetMaxIdleConns(maxIdleConn)
	// Make sure that all the connections are established to a same node, instead of distributing them into multiple nodes.
	db.SetConnMaxLifetime(5 * time.Minute)
	if err := db.Ping(); err != nil {
		return nil, err
	}

	return &MySQL{
		db:     db,
		random: rand.New(&randomSource{src: rand.NewSource(time.Now().Unix())}),
	}, nil
}

func validateClusterAddr(addr string) error {
	if len(addr) == 0 {
		return errors.New("empty cluster address")
	}

	token := strings.Split(strings.Replace(addr, " ", "", -1), ",")
	if len(token) == 0 {
		return fmt.Errorf("invalid cluster address: %v", addr)
	}

	for _, v := range token {
		if _, err := net.ResolveTCPAddr("tcp", v); err != nil {
			return fmt.Errorf("invalid cluster address: %v: %v", v, err)
		}
	}

	return nil
}

// clusterDialer tries to sequentially connect to each hosts from the address in the
// order of their appearance and then returns the first successfully connected one.
func clusterDialer(addr string) (net.Conn, error) {
	token := strings.Split(strings.Replace(addr, " ", "", -1), ",")

	for _, v := range token {
		logger.Debugf("dialing to %v", v)
		conn, err := net.DialTimeout("tcp", v, 5*time.Second)
		if err == nil {
			// Connected!
			logger.Debugf("successfully connected to %v", v)
			return conn, nil
		}
		logger.Errorf("failed to dial: %v", err)
	}

	return nil, errors.New("failed to dial: no available cluster node")
}

func isDeadlock(err error) bool {
	e, ok := err.(*mysql.MySQLError)
	if !ok {
		return false
	}

	return e.Number == deadlockErrCode
}

func isDuplicated(err error) bool {
	e, ok := err.(*mysql.MySQLError)
	if !ok {
		return false
	}

	return e.Number == duplicatedErrCode
}

func isForeignkeyErr(err error) bool {
	e, ok := err.(*mysql.MySQLError)
	if !ok {
		return false
	}

	return e.Number == foreignkeyErrCode
}

func (r *MySQL) query(f func(*sql.Tx) error) error {
	deadlockRetry := 0

	for {
		tx, err := r.db.Begin()
		if err != nil {
			return err
		}

		err = f(tx)
		// Success?
		if err == nil {
			// Yes! but Commit also may raise an error.
			err = tx.Commit()
			// Success?
			if err == nil {
				// Transaction committed successfully!
				return nil
			}
			// Fallthrough!
		}
		// No! query failed.
		tx.Rollback()

		// Need to retry due to a deadlock?
		if !isDeadlock(err) || deadlockRetry >= maxDeadlockRetry {
			// No, do not retry and just return the error.
			return err
		}
		// Yes, a deadlock occurrs. Re-execute the queries again after some sleep!
		logger.Infof("query failed due to a deadlock: caller=%v", caller())
		time.Sleep(time.Duration(rand.Int31n(500)) * time.Millisecond)
		deadlockRetry++
	}
}

func caller() string {
	pc, file, line, ok := runtime.Caller(2)
	if !ok {
		return "unknown"
	}

	f := runtime.FuncForPC(pc)
	if f == nil {
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("%v (%v:%v)", f.Name(), file, line)
}

func (r *MySQL) MAC(ip net.IP) (mac net.HardwareAddr, ok bool, err error) {
	if ip == nil {
		panic("IP address is nil")
	}

	f := func(tx *sql.Tx) error {
		// Union query from both vip and host tables
		qry := `(SELECT B.mac, B.enabled
			 FROM vip 
			 A JOIN host B ON A.active_host_id = B.id 
			 JOIN ip C ON A.ip_id = C.id 
			 WHERE C.address = INET_ATON(?)
		 	) 
			UNION ALL 
			(SELECT A.mac, A.enabled
			 FROM host A 
			 JOIN ip B ON A.ip_id = B.id 
			 WHERE B.address = INET_ATON(?)
		 	) 
			LIMIT 1`
		row, err := tx.Query(qry, ip.String(), ip.String())
		if err != nil {
			return err
		}
		defer row.Close()

		// Unknown IP address?
		if !row.Next() {
			return nil
		}
		if err := row.Err(); err != nil {
			return err
		}

		var v []byte
		var enabled bool
		if err := row.Scan(&v, &enabled); err != nil {
			return err
		}
		if v == nil || len(v) != 6 {
			return errors.New("invalid MAC address")
		}
		if enabled == false {
			return nil
		}

		mac = net.HardwareAddr(v)
		ok = true

		return nil
	}
	err = r.query(f)

	return mac, ok, err
}

func (r *MySQL) Location(mac net.HardwareAddr) (dpid string, port uint32, status network.LocationStatus, err error) {
	if mac == nil {
		panic("MAC address is nil")
	}

	f := func(tx *sql.Tx) error {
		// Initial value.
		status = network.LocationUnregistered

		var portID sql.NullInt64
		qry := "SELECT `port_id` FROM `host` WHERE `mac` = ? ORDER BY `port_id` DESC LOCK IN SHARE MODE"
		if err := tx.QueryRow(qry, []byte(mac)).Scan(&portID); err != nil {
			// Unregistered host?
			if err == sql.ErrNoRows {
				return nil
			} else {
				return err
			}
		}
		// NULL port ID?
		if portID.Valid == false {
			// The node is registered, but we don't know its physical location yet.
			status = network.LocationUndiscovered
			return nil
		}

		qry = "SELECT B.`dpid`, A.`number` FROM `port` A JOIN `switch` B ON A.`switch_id` = B.`id` WHERE A.`id` = ?"
		if err := tx.QueryRow(qry, portID.Int64).Scan(&dpid, &port); err != nil {
			if err == sql.ErrNoRows { // FIXME: Is this possible?
				return nil
			} else {
				return err
			}
		}
		status = network.LocationDiscovered

		return nil
	}
	if err := r.query(f); err != nil {
		return "", 0, network.LocationUnregistered, err
	}

	return dpid, port, status, nil
}

func (r *MySQL) TogglePortVIP(swDPID uint64, portNum uint16) (result []virtualip.Address, err error) {
	f := func(tx *sql.Tx) error {
		portID, err := portID(tx, swDPID, portNum)
		if err != nil {
			return err
		}
		vips, err := getPortVIPs(tx, portID)
		if err != nil {
			return err
		}
		for _, v := range vips {
			if err := swapVIPHosts(tx, v); err != nil {
				return err
			}
			// Get standby's MAC address as the standby host will be active soon!
			mac, err := hostMAC(tx, v.standby)
			if err != nil {
				return err
			}
			result = append(result, virtualip.Address{IP: v.address, MAC: mac})
		}

		return nil
	}
	if err = r.query(f); err != nil {
		return nil, err
	}

	return result, nil
}

func (r *MySQL) ToggleDeviceVIP(swDPID uint64) (result []virtualip.Address, err error) {
	f := func(tx *sql.Tx) error {
		vips, err := getDeviceVIPs(tx, swDPID)
		if err != nil {
			return err
		}
		for _, v := range vips {
			if err := swapVIPHosts(tx, v); err != nil {
				return err
			}
			// Get standby's MAC address as the standby host will be active soon!
			mac, err := hostMAC(tx, v.standby)
			if err != nil {
				return err
			}
			result = append(result, virtualip.Address{IP: v.address, MAC: mac})
		}

		return nil
	}
	if err = r.query(f); err != nil {
		return nil, err
	}

	return result, nil
}

func portID(tx *sql.Tx, swDPID uint64, portNum uint16) (uint64, error) {
	qry := `SELECT A.id 
		FROM port A 
		JOIN switch B ON A.switch_id = B.id 
		WHERE A.number = ? AND B.dpid = ? 
		LOCK IN SHARE MODE`
	row, err := tx.Query(qry, portNum, swDPID)
	if err != nil {
		return 0, err
	}
	defer row.Close()
	// Empty row?
	if !row.Next() {
		return 0, fmt.Errorf("unknown switch port (DPID=%v, Number=%v)", swDPID, portNum)
	}

	var id uint64
	if err := row.Scan(&id); err != nil {
		return 0, err
	}

	return id, nil
}

type vip struct {
	id      uint64
	address net.IP
	active  uint64
	standby uint64
}

func getPortVIPs(tx *sql.Tx, portID uint64) (result []vip, err error) {
	qry := `SELECT A.id, INET_NTOA(C.address), A.active_host_id, A.standby_host_id 
		FROM vip A 
		JOIN host B ON A.active_host_id = B.id 
		JOIN ip C ON A.ip_id = C.id
		WHERE B.port_id = ? 
		FOR UPDATE`
	rows, err := tx.Query(qry, portID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var id, active, standby uint64
		var address string
		if err := rows.Scan(&id, &address, &active, &standby); err != nil {
			return nil, err
		}
		ip := net.ParseIP(address)
		if ip == nil {
			return nil, fmt.Errorf("invalid IPv4 address: %v", address)
		}
		result = append(result, vip{id, ip, active, standby})
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return result, nil
}

func getDeviceVIPs(tx *sql.Tx, swDPID uint64) (result []vip, err error) {
	qry := `SELECT A.id, INET_NTOA(E.address), A.active_host_id, A.standby_host_id 
		FROM vip A 
		JOIN host B ON A.active_host_id = B.id 
		JOIN port C ON B.port_id = C.id 
		JOIN switch D ON D.id = C.switch_id 
		JOIN ip E ON E.id = A.ip_id 
		WHERE D.dpid = ? 
		FOR UPDATE`
	rows, err := tx.Query(qry, swDPID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var id, active, standby uint64
		var address string
		if err := rows.Scan(&id, &address, &active, &standby); err != nil {
			return nil, err
		}
		ip := net.ParseIP(address)
		if ip == nil {
			return nil, fmt.Errorf("invalid IPv4 address: %v", address)
		}
		result = append(result, vip{id, ip, active, standby})
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return result, nil
}

func swapVIPHosts(tx *sql.Tx, v vip) error {
	qry := "UPDATE vip SET active_host_id = ?, standby_host_id = ? WHERE id = ?"
	// Swap active and standby hosts
	_, err := tx.Exec(qry, v.standby, v.active, v.id)
	if err != nil {
		return err
	}

	if err := updateARPTableEntryByVIP(tx, v.id, false); err != nil {
		return err
	}

	return nil
}

func hostMAC(tx *sql.Tx, hostID uint64) (net.HardwareAddr, error) {
	row, err := tx.Query("SELECT HEX(mac) FROM host WHERE id = ?", hostID)
	if err != nil {
		return nil, err
	}
	defer row.Close()
	// Empty row?
	if !row.Next() {
		return nil, fmt.Errorf("unknown host (ID=%v)", hostID)
	}

	var v string
	if err := row.Scan(&v); err != nil {
		return nil, err
	}
	mac, err := decodeMAC(v)
	if err != nil {
		return nil, err
	}

	return mac, nil
}

// GetUndiscoveredHosts returns IP addresses whose physical location is still
// undiscovered or staled more than expiration. result can be nil on empty result.
func (r *MySQL) GetUndiscoveredHosts(expiration time.Duration) (result []net.IPNet, err error) {
	f := func(tx *sql.Tx) error {
		// NOTE: Do not include VIP addresses!
		qry := "SELECT IFNULL(INET_NTOA(B.`address`), '0.0.0.0'), IFNULL(C.`mask`, 0) "
		qry += "FROM `host` A "
		qry += "JOIN `ip` B ON A.`ip_id` = B.`id` "
		qry += "JOIN `network` C ON B.`network_id` = C.`id` "
		qry += "WHERE A.`port_id` IS NULL OR A.`last_updated_timestamp` < NOW() - INTERVAL ? SECOND"

		rows, err := tx.Query(qry, uint64(expiration.Seconds()))
		if err != nil {
			return err
		}
		defer rows.Close()

		for rows.Next() {
			var addr string
			var mask int
			if err := rows.Scan(&addr, &mask); err != nil {
				return err
			}

			ip := net.ParseIP(addr)
			if ip == nil {
				return fmt.Errorf("invalid IP address: %v", addr)
			}
			if ip.IsUnspecified() {
				continue
			}

			netmask := net.CIDRMask(mask, 32)
			if netmask == nil {
				return fmt.Errorf("invalid network mask: IP=%v, Mask=%v", addr, mask)
			}

			result = append(result, net.IPNet{IP: ip, Mask: netmask})
		}

		return rows.Err()
	}

	if err = r.query(f); err != nil {
		return nil, err
	}

	return result, nil
}

// UpdateHostLocation updates the physical location of a host, whose MAC and IP
// addresses are matched with mac and ip, to the port identified by swDPID and
// portNum. updated will be true if its location has been actually updated.
func (r *MySQL) UpdateHostLocation(mac net.HardwareAddr, ip net.IP, swDPID uint64, portNum uint16) (updated bool, err error) {
	f := func(tx *sql.Tx) error {
		hostID, ok, err := getHostID(tx, mac, ip)
		if err != nil {
			return err
		}
		// Unknown host?
		if !ok {
			updated = false
			return nil
		}

		portID, err := portID(tx, swDPID, portNum)
		if err != nil {
			return err
		}

		updated, err = updateLocation(tx, hostID, portID)
		if err != nil {
			return err
		}

		return nil
	}
	if err = r.query(f); err != nil {
		return false, err
	}

	return updated, nil
}

func getHostID(tx *sql.Tx, mac net.HardwareAddr, ip net.IP) (hostID uint64, ok bool, err error) {
	qry := "SELECT A.`id` "
	qry += "FROM `host` A "
	qry += "JOIN `ip` B "
	qry += "ON A.`ip_id` = B.`id` "
	qry += "WHERE A.`mac` = ? AND B.`address` = INET_ATON(?) "
	qry += "LOCK IN SHARE MODE"

	row, err := tx.Query(qry, []byte(mac), ip.String())
	if err != nil {
		return 0, false, err
	}
	defer row.Close()

	// Empty row?
	if !row.Next() {
		return 0, false, nil
	}
	if err := row.Scan(&hostID); err != nil {
		return 0, false, err
	}

	return hostID, true, nil
}

func updateLocation(tx *sql.Tx, hostID, portID uint64) (updated bool, err error) {
	var id uint64
	qry := "SELECT `id` FROM `host` WHERE `id` = ? AND `port_id` = ?"
	err = tx.QueryRow(qry, hostID, portID).Scan(&id)
	// Real error?
	if err != nil && err != sql.ErrNoRows {
		return false, err
	}

	// Need to update?
	if err == sql.ErrNoRows {
		updated = true
	}
	qry = "UPDATE `host` SET `port_id` = ?, `last_updated_timestamp` = NOW() WHERE `id` = ?"
	_, err = tx.Exec(qry, portID, hostID)
	if err != nil {
		return false, err
	}

	return updated, nil
}

// ResetHostLocationsByPort sets NULL to the host locations that belong to the
// port specified by swDPID and portNum.
func (r *MySQL) ResetHostLocationsByPort(swDPID uint64, portNum uint16) error {
	f := func(tx *sql.Tx) error {
		portID, err := portID(tx, swDPID, portNum)
		if err != nil {
			return err
		}

		qry := "UPDATE `host` SET `port_id` = NULL WHERE `port_id` = ?"
		if _, err := tx.Exec(qry, portID); err != nil {
			return err
		}

		return nil
	}

	return r.query(f)
}

// ResetHostLocationsByDevice sets NULL to the host locations that belong to the
// device specified by swDPID.
func (r *MySQL) ResetHostLocationsByDevice(swDPID uint64) error {
	f := func(tx *sql.Tx) error {
		qry := "UPDATE `host` A "
		qry += "JOIN `port` B ON A.`port_id` = B.`id` "
		qry += "JOIN `switch` C ON B.`switch_id` = C.`id` "
		qry += "SET A.`port_id` = NULL "
		qry += "WHERE C.`dpid` = ?"

		_, err := tx.Exec(qry, swDPID)
		if err != nil {
			return err
		}

		return nil
	}

	return r.query(f)
}

// Elect selects a new master as uid if there is a no existing master that has
// been updated within expiration. elected will be true if this uid has been
// elected as the new master or was already elected.
func (r *MySQL) Elect(uid string, expiration time.Duration) (elected bool, err error) {
	qry := "INSERT INTO `master_election` (`id`, `name`, `timestamp`) VALUES (1, ?, NOW()) "
	qry += "ON DUPLICATE KEY UPDATE "
	qry += fmt.Sprin
Download .txt
gitextract_s279x8yc/

├── .gitlab-ci.yml
├── Changelog
├── Dockerfile
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── Gopkg.toml
├── LICENSE
├── README.md
├── api/
│   ├── core/
│   │   └── api.go
│   ├── response.go
│   ├── server.go
│   └── ui/
│       ├── api.go
│       ├── category.go
│       ├── component.go
│       ├── group.go
│       ├── host.go
│       ├── ip.go
│       ├── log.go
│       ├── network.go
│       ├── session.go
│       ├── switch.go
│       ├── user.go
│       └── vip.go
├── cmd/
│   ├── cherry/
│   │   ├── cherry.yaml
│   │   └── main.go
│   └── walnut/
│       ├── main.go
│       ├── sdk.go
│       └── walnut.yaml
├── database/
│   ├── mysql.go
│   ├── mysql_schema.sql
│   └── random.go
├── election/
│   └── election.go
├── graph/
│   ├── graph.go
│   └── graph_test.go
├── ldap/
│   ├── client.go
│   └── conn.go
├── log/
│   └── syslog.go
├── network/
│   ├── controller.go
│   ├── device.go
│   ├── error.go
│   ├── flow_cache.go
│   ├── link.go
│   ├── node.go
│   ├── of10_session.go
│   ├── of13_session.go
│   ├── port.go
│   ├── reserve.go
│   ├── reserve_test.go
│   ├── session.go
│   └── topology.go
├── northbound/
│   ├── app/
│   │   ├── announcer/
│   │   │   ├── announcer.go
│   │   │   └── backoff.go
│   │   ├── dhcp/
│   │   │   └── dhcp.go
│   │   ├── discovery/
│   │   │   └── discovery.go
│   │   ├── l2switch/
│   │   │   ├── storm_controller.go
│   │   │   ├── storm_controller_test.go
│   │   │   └── switch.go
│   │   ├── monitor/
│   │   │   ├── monitor.go
│   │   │   └── sendmail.go
│   │   ├── processor.go
│   │   ├── proxyarp/
│   │   │   ├── arp.go
│   │   │   └── error.go
│   │   └── virtualip/
│   │       └── virtualip.go
│   └── manager.go
├── openflow/
│   ├── action.go
│   ├── barrier.go
│   ├── config.go
│   ├── const.go
│   ├── description.go
│   ├── echo.go
│   ├── error.go
│   ├── factory.go
│   ├── features.go
│   ├── flow_mod.go
│   ├── flow_removed.go
│   ├── flow_stats.go
│   ├── hello.go
│   ├── instruction.go
│   ├── match.go
│   ├── message.go
│   ├── of10/
│   │   ├── action.go
│   │   ├── barrier.go
│   │   ├── config.go
│   │   ├── const.go
│   │   ├── description.go
│   │   ├── echo.go
│   │   ├── factory.go
│   │   ├── features.go
│   │   ├── flow_mod.go
│   │   ├── flow_removed.go
│   │   ├── flow_stats.go
│   │   ├── hello.go
│   │   ├── instruction.go
│   │   ├── match.go
│   │   ├── packet_in.go
│   │   ├── packet_out.go
│   │   ├── port.go
│   │   ├── port_status.go
│   │   └── queue.go
│   ├── of13/
│   │   ├── action.go
│   │   ├── barrier.go
│   │   ├── config.go
│   │   ├── const.go
│   │   ├── echo.go
│   │   ├── factory.go
│   │   ├── features.go
│   │   ├── flow_mod.go
│   │   ├── flow_removed.go
│   │   ├── hello.go
│   │   ├── instruction.go
│   │   ├── match.go
│   │   ├── multipart_description.go
│   │   ├── multipart_flow_stats.go
│   │   ├── multipart_port_description.go
│   │   ├── multipart_table_features.go
│   │   ├── packet_in.go
│   │   ├── packet_out.go
│   │   ├── port.go
│   │   ├── port_status.go
│   │   └── queue.go
│   ├── packet_in.go
│   ├── packet_out.go
│   ├── port.go
│   ├── port_description.go
│   ├── port_status.go
│   ├── queue.go
│   ├── table_features.go
│   └── transceiver/
│       ├── stream.go
│       └── transceiver.go
├── protocol/
│   ├── arp.go
│   ├── checksum.go
│   ├── dhcp.go
│   ├── dhcp_test.go
│   ├── ethernet.go
│   ├── icmp.go
│   ├── ipv4.go
│   ├── lldp.go
│   ├── tcp.go
│   └── udp.go
├── vendor/
│   ├── github.com/
│   │   ├── ant0ine/
│   │   │   └── go-json-rest/
│   │   │       ├── LICENSE
│   │   │       └── rest/
│   │   │           ├── access_log_apache.go
│   │   │           ├── access_log_json.go
│   │   │           ├── api.go
│   │   │           ├── auth_basic.go
│   │   │           ├── content_type_checker.go
│   │   │           ├── cors.go
│   │   │           ├── doc.go
│   │   │           ├── gzip.go
│   │   │           ├── if.go
│   │   │           ├── json_indent.go
│   │   │           ├── jsonp.go
│   │   │           ├── middleware.go
│   │   │           ├── powered_by.go
│   │   │           ├── recorder.go
│   │   │           ├── recover.go
│   │   │           ├── request.go
│   │   │           ├── response.go
│   │   │           ├── route.go
│   │   │           ├── router.go
│   │   │           ├── status.go
│   │   │           ├── timer.go
│   │   │           └── trie/
│   │   │               └── impl.go
│   │   ├── boombuler/
│   │   │   └── barcode/
│   │   │       ├── .gitignore
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── barcode.go
│   │   │       ├── qr/
│   │   │       │   ├── alphanumeric.go
│   │   │       │   ├── automatic.go
│   │   │       │   ├── blocks.go
│   │   │       │   ├── encoder.go
│   │   │       │   ├── errorcorrection.go
│   │   │       │   ├── numeric.go
│   │   │       │   ├── qrcode.go
│   │   │       │   ├── unicode.go
│   │   │       │   └── versioninfo.go
│   │   │       ├── scaledbarcode.go
│   │   │       └── utils/
│   │   │           ├── base1dcode.go
│   │   │           ├── bitlist.go
│   │   │           ├── galoisfield.go
│   │   │           ├── gfpoly.go
│   │   │           ├── reedsolomon.go
│   │   │           └── runeint.go
│   │   ├── davecgh/
│   │   │   └── go-spew/
│   │   │       ├── LICENSE
│   │   │       └── spew/
│   │   │           ├── bypass.go
│   │   │           ├── bypasssafe.go
│   │   │           ├── common.go
│   │   │           ├── config.go
│   │   │           ├── doc.go
│   │   │           ├── dump.go
│   │   │           ├── format.go
│   │   │           └── spew.go
│   │   ├── fsnotify/
│   │   │   └── fsnotify/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── AUTHORS
│   │   │       ├── CHANGELOG.md
│   │   │       ├── CONTRIBUTING.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── fen.go
│   │   │       ├── fsnotify.go
│   │   │       ├── inotify.go
│   │   │       ├── inotify_poller.go
│   │   │       ├── kqueue.go
│   │   │       ├── open_mode_bsd.go
│   │   │       ├── open_mode_darwin.go
│   │   │       └── windows.go
│   │   ├── go-sql-driver/
│   │   │   └── mysql/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── AUTHORS
│   │   │       ├── CHANGELOG.md
│   │   │       ├── CONTRIBUTING.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── appengine.go
│   │   │       ├── buffer.go
│   │   │       ├── collations.go
│   │   │       ├── connection.go
│   │   │       ├── connection_go18.go
│   │   │       ├── const.go
│   │   │       ├── driver.go
│   │   │       ├── dsn.go
│   │   │       ├── errors.go
│   │   │       ├── fields.go
│   │   │       ├── infile.go
│   │   │       ├── packets.go
│   │   │       ├── result.go
│   │   │       ├── rows.go
│   │   │       ├── statement.go
│   │   │       ├── transaction.go
│   │   │       ├── utils.go
│   │   │       ├── utils_go17.go
│   │   │       └── utils_go18.go
│   │   ├── google/
│   │   │   └── go-cmp/
│   │   │       ├── LICENSE
│   │   │       └── cmp/
│   │   │           ├── cmpopts/
│   │   │           │   ├── equate.go
│   │   │           │   ├── ignore.go
│   │   │           │   ├── sort.go
│   │   │           │   ├── struct_filter.go
│   │   │           │   └── xform.go
│   │   │           ├── compare.go
│   │   │           ├── export_panic.go
│   │   │           ├── export_unsafe.go
│   │   │           ├── internal/
│   │   │           │   ├── diff/
│   │   │           │   │   ├── debug_disable.go
│   │   │           │   │   ├── debug_enable.go
│   │   │           │   │   └── diff.go
│   │   │           │   ├── flags/
│   │   │           │   │   ├── flags.go
│   │   │           │   │   ├── toolchain_legacy.go
│   │   │           │   │   └── toolchain_recent.go
│   │   │           │   ├── function/
│   │   │           │   │   └── func.go
│   │   │           │   └── value/
│   │   │           │       ├── pointer_purego.go
│   │   │           │       ├── pointer_unsafe.go
│   │   │           │       ├── sort.go
│   │   │           │       └── zero.go
│   │   │           ├── options.go
│   │   │           ├── path.go
│   │   │           ├── report.go
│   │   │           ├── report_compare.go
│   │   │           ├── report_reflect.go
│   │   │           ├── report_slices.go
│   │   │           ├── report_text.go
│   │   │           └── report_value.go
│   │   ├── hashicorp/
│   │   │   ├── golang-lru/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── 2q.go
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   ├── arc.go
│   │   │   │   ├── lru.go
│   │   │   │   └── simplelru/
│   │   │   │       └── lru.go
│   │   │   └── hcl/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── Makefile
│   │   │       ├── README.md
│   │   │       ├── appveyor.yml
│   │   │       ├── decoder.go
│   │   │       ├── hcl/
│   │   │       │   ├── ast/
│   │   │       │   │   ├── ast.go
│   │   │       │   │   └── walk.go
│   │   │       │   ├── parser/
│   │   │       │   │   ├── error.go
│   │   │       │   │   └── parser.go
│   │   │       │   ├── scanner/
│   │   │       │   │   └── scanner.go
│   │   │       │   ├── strconv/
│   │   │       │   │   └── quote.go
│   │   │       │   └── token/
│   │   │       │       ├── position.go
│   │   │       │       └── token.go
│   │   │       ├── hcl.go
│   │   │       ├── json/
│   │   │       │   ├── parser/
│   │   │       │   │   ├── flatten.go
│   │   │       │   │   └── parser.go
│   │   │       │   ├── scanner/
│   │   │       │   │   └── scanner.go
│   │   │       │   └── token/
│   │   │       │       ├── position.go
│   │   │       │       └── token.go
│   │   │       ├── lex.go
│   │   │       └── parse.go
│   │   ├── magiconair/
│   │   │   └── properties/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── CHANGELOG.md
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── _third_party/
│   │   │       │   └── gopkg.in/
│   │   │       │       └── check.v1/
│   │   │       │           └── LICENSE
│   │   │       ├── decode.go
│   │   │       ├── doc.go
│   │   │       ├── integrate.go
│   │   │       ├── lex.go
│   │   │       ├── load.go
│   │   │       ├── parser.go
│   │   │       ├── properties.go
│   │   │       └── rangecheck.go
│   │   ├── mitchellh/
│   │   │   └── mapstructure/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── decode_hooks.go
│   │   │       ├── error.go
│   │   │       └── mapstructure.go
│   │   ├── pelletier/
│   │   │   ├── go-buffruneio/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── .travis.yml
│   │   │   │   ├── README.md
│   │   │   │   └── buffruneio.go
│   │   │   └── go-toml/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── clean.sh
│   │   │       ├── doc.go
│   │   │       ├── example-crlf.toml
│   │   │       ├── example.toml
│   │   │       ├── keysparsing.go
│   │   │       ├── lexer.go
│   │   │       ├── match.go
│   │   │       ├── parser.go
│   │   │       ├── position.go
│   │   │       ├── query.go
│   │   │       ├── querylexer.go
│   │   │       ├── queryparser.go
│   │   │       ├── test.sh
│   │   │       ├── token.go
│   │   │       ├── toml.go
│   │   │       └── tomltree_conversions.go
│   │   ├── pkg/
│   │   │   └── errors/
│   │   │       ├── .gitignore
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── appveyor.yml
│   │   │       ├── errors.go
│   │   │       └── stack.go
│   │   ├── pquerna/
│   │   │   └── otp/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── NOTICE
│   │   │       ├── README.md
│   │   │       ├── doc.go
│   │   │       ├── hotp/
│   │   │       │   └── hotp.go
│   │   │       ├── otp.go
│   │   │       └── totp/
│   │   │           └── totp.go
│   │   ├── spf13/
│   │   │   ├── afero/
│   │   │   │   ├── .travis.yml
│   │   │   │   ├── LICENSE.txt
│   │   │   │   ├── README.md
│   │   │   │   ├── afero.go
│   │   │   │   ├── appveyor.yml
│   │   │   │   ├── basepath.go
│   │   │   │   ├── cacheOnReadFs.go
│   │   │   │   ├── const_bsds.go
│   │   │   │   ├── const_win_unix.go
│   │   │   │   ├── copyOnWriteFs.go
│   │   │   │   ├── httpFs.go
│   │   │   │   ├── ioutil.go
│   │   │   │   ├── mem/
│   │   │   │   │   ├── dir.go
│   │   │   │   │   ├── dirmap.go
│   │   │   │   │   └── file.go
│   │   │   │   ├── memmap.go
│   │   │   │   ├── memradix.go
│   │   │   │   ├── os.go
│   │   │   │   ├── path.go
│   │   │   │   ├── readonlyfs.go
│   │   │   │   ├── regexpfs.go
│   │   │   │   ├── unionFile.go
│   │   │   │   └── util.go
│   │   │   ├── cast/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   ├── cast.go
│   │   │   │   └── caste.go
│   │   │   ├── jwalterweatherman/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── LICENSE
│   │   │   │   ├── README.md
│   │   │   │   └── thatswhyyoualwaysleaveanote.go
│   │   │   └── pflag/
│   │   │       ├── .travis.yml
│   │   │       ├── LICENSE
│   │   │       ├── README.md
│   │   │       ├── bool.go
│   │   │       ├── count.go
│   │   │       ├── duration.go
│   │   │       ├── flag.go
│   │   │       ├── float32.go
│   │   │       ├── float64.go
│   │   │       ├── golangflag.go
│   │   │       ├── int.go
│   │   │       ├── int32.go
│   │   │       ├── int64.go
│   │   │       ├── int8.go
│   │   │       ├── int_slice.go
│   │   │       ├── ip.go
│   │   │       ├── ipmask.go
│   │   │       ├── ipnet.go
│   │   │       ├── string.go
│   │   │       ├── string_slice.go
│   │   │       ├── uint.go
│   │   │       ├── uint16.go
│   │   │       ├── uint32.go
│   │   │       ├── uint64.go
│   │   │       └── uint8.go
│   │   └── superkkt/
│   │       ├── go-logging/
│   │       │   ├── .travis.yml
│   │       │   ├── CHANGELOG.md
│   │       │   ├── CONTRIBUTORS
│   │       │   ├── LICENSE
│   │       │   ├── README.md
│   │       │   ├── backend.go
│   │       │   ├── format.go
│   │       │   ├── level.go
│   │       │   ├── log_nix.go
│   │       │   ├── log_windows.go
│   │       │   ├── logger.go
│   │       │   ├── memory.go
│   │       │   ├── multi.go
│   │       │   ├── syslog.go
│   │       │   └── syslog_fallback.go
│   │       └── viper/
│   │           ├── .gitignore
│   │           ├── .travis.yml
│   │           ├── LICENSE
│   │           ├── README.md
│   │           ├── flags.go
│   │           ├── nohup.out
│   │           ├── util.go
│   │           └── viper.go
│   ├── golang.org/
│   │   └── x/
│   │       ├── sys/
│   │       │   ├── AUTHORS
│   │       │   ├── CONTRIBUTORS
│   │       │   ├── LICENSE
│   │       │   ├── PATENTS
│   │       │   └── unix/
│   │       │       ├── .gitignore
│   │       │       ├── asm.s
│   │       │       ├── asm_darwin_386.s
│   │       │       ├── asm_darwin_amd64.s
│   │       │       ├── asm_darwin_arm.s
│   │       │       ├── asm_darwin_arm64.s
│   │       │       ├── asm_dragonfly_amd64.s
│   │       │       ├── asm_freebsd_386.s
│   │       │       ├── asm_freebsd_amd64.s
│   │       │       ├── asm_freebsd_arm.s
│   │       │       ├── asm_linux_386.s
│   │       │       ├── asm_linux_amd64.s
│   │       │       ├── asm_linux_arm.s
│   │       │       ├── asm_linux_arm64.s
│   │       │       ├── asm_linux_mips64x.s
│   │       │       ├── asm_linux_ppc64x.s
│   │       │       ├── asm_linux_s390x.s
│   │       │       ├── asm_netbsd_386.s
│   │       │       ├── asm_netbsd_amd64.s
│   │       │       ├── asm_netbsd_arm.s
│   │       │       ├── asm_openbsd_386.s
│   │       │       ├── asm_openbsd_amd64.s
│   │       │       ├── asm_solaris_amd64.s
│   │       │       ├── bluetooth_linux.go
│   │       │       ├── constants.go
│   │       │       ├── env_unix.go
│   │       │       ├── env_unset.go
│   │       │       ├── flock.go
│   │       │       ├── flock_linux_32bit.go
│   │       │       ├── gccgo.go
│   │       │       ├── gccgo_c.c
│   │       │       ├── gccgo_linux_amd64.go
│   │       │       ├── mkall.sh
│   │       │       ├── mkerrors.sh
│   │       │       ├── mkpost.go
│   │       │       ├── mksyscall.pl
│   │       │       ├── mksyscall_solaris.pl
│   │       │       ├── mksysctl_openbsd.pl
│   │       │       ├── mksysnum_darwin.pl
│   │       │       ├── mksysnum_dragonfly.pl
│   │       │       ├── mksysnum_freebsd.pl
│   │       │       ├── mksysnum_linux.pl
│   │       │       ├── mksysnum_netbsd.pl
│   │       │       ├── mksysnum_openbsd.pl
│   │       │       ├── race.go
│   │       │       ├── race0.go
│   │       │       ├── sockcmsg_linux.go
│   │       │       ├── sockcmsg_unix.go
│   │       │       ├── str.go
│   │       │       ├── syscall.go
│   │       │       ├── syscall_bsd.go
│   │       │       ├── syscall_darwin.go
│   │       │       ├── syscall_darwin_386.go
│   │       │       ├── syscall_darwin_amd64.go
│   │       │       ├── syscall_darwin_arm.go
│   │       │       ├── syscall_darwin_arm64.go
│   │       │       ├── syscall_dragonfly.go
│   │       │       ├── syscall_dragonfly_amd64.go
│   │       │       ├── syscall_freebsd.go
│   │       │       ├── syscall_freebsd_386.go
│   │       │       ├── syscall_freebsd_amd64.go
│   │       │       ├── syscall_freebsd_arm.go
│   │       │       ├── syscall_linux.go
│   │       │       ├── syscall_linux_386.go
│   │       │       ├── syscall_linux_amd64.go
│   │       │       ├── syscall_linux_arm.go
│   │       │       ├── syscall_linux_arm64.go
│   │       │       ├── syscall_linux_mips64x.go
│   │       │       ├── syscall_linux_ppc64x.go
│   │       │       ├── syscall_linux_s390x.go
│   │       │       ├── syscall_netbsd.go
│   │       │       ├── syscall_netbsd_386.go
│   │       │       ├── syscall_netbsd_amd64.go
│   │       │       ├── syscall_netbsd_arm.go
│   │       │       ├── syscall_no_getwd.go
│   │       │       ├── syscall_openbsd.go
│   │       │       ├── syscall_openbsd_386.go
│   │       │       ├── syscall_openbsd_amd64.go
│   │       │       ├── syscall_solaris.go
│   │       │       ├── syscall_solaris_amd64.go
│   │       │       ├── syscall_unix.go
│   │       │       ├── types_darwin.go
│   │       │       ├── types_dragonfly.go
│   │       │       ├── types_freebsd.go
│   │       │       ├── types_linux.go
│   │       │       ├── types_netbsd.go
│   │       │       ├── types_openbsd.go
│   │       │       ├── types_solaris.go
│   │       │       ├── zerrors_darwin_386.go
│   │       │       ├── zerrors_darwin_amd64.go
│   │       │       ├── zerrors_darwin_arm.go
│   │       │       ├── zerrors_darwin_arm64.go
│   │       │       ├── zerrors_dragonfly_amd64.go
│   │       │       ├── zerrors_freebsd_386.go
│   │       │       ├── zerrors_freebsd_amd64.go
│   │       │       ├── zerrors_freebsd_arm.go
│   │       │       ├── zerrors_linux_386.go
│   │       │       ├── zerrors_linux_amd64.go
│   │       │       ├── zerrors_linux_arm.go
│   │       │       ├── zerrors_linux_arm64.go
│   │       │       ├── zerrors_linux_mips64.go
│   │       │       ├── zerrors_linux_mips64le.go
│   │       │       ├── zerrors_linux_ppc64.go
│   │       │       ├── zerrors_linux_ppc64le.go
│   │       │       ├── zerrors_linux_s390x.go
│   │       │       ├── zerrors_netbsd_386.go
│   │       │       ├── zerrors_netbsd_amd64.go
│   │       │       ├── zerrors_netbsd_arm.go
│   │       │       ├── zerrors_openbsd_386.go
│   │       │       ├── zerrors_openbsd_amd64.go
│   │       │       ├── zerrors_solaris_amd64.go
│   │       │       ├── zsyscall_darwin_386.go
│   │       │       ├── zsyscall_darwin_amd64.go
│   │       │       ├── zsyscall_darwin_arm.go
│   │       │       ├── zsyscall_darwin_arm64.go
│   │       │       ├── zsyscall_dragonfly_amd64.go
│   │       │       ├── zsyscall_freebsd_386.go
│   │       │       ├── zsyscall_freebsd_amd64.go
│   │       │       ├── zsyscall_freebsd_arm.go
│   │       │       ├── zsyscall_linux_386.go
│   │       │       ├── zsyscall_linux_amd64.go
│   │       │       ├── zsyscall_linux_arm.go
│   │       │       ├── zsyscall_linux_arm64.go
│   │       │       ├── zsyscall_linux_mips64.go
│   │       │       ├── zsyscall_linux_mips64le.go
│   │       │       ├── zsyscall_linux_ppc64.go
│   │       │       ├── zsyscall_linux_ppc64le.go
│   │       │       ├── zsyscall_linux_s390x.go
│   │       │       ├── zsyscall_netbsd_386.go
│   │       │       ├── zsyscall_netbsd_amd64.go
│   │       │       ├── zsyscall_netbsd_arm.go
│   │       │       ├── zsyscall_openbsd_386.go
│   │       │       ├── zsyscall_openbsd_amd64.go
│   │       │       ├── zsyscall_solaris_amd64.go
│   │       │       ├── zsysctl_openbsd.go
│   │       │       ├── zsysnum_darwin_386.go
│   │       │       ├── zsysnum_darwin_amd64.go
│   │       │       ├── zsysnum_darwin_arm.go
│   │       │       ├── zsysnum_darwin_arm64.go
│   │       │       ├── zsysnum_dragonfly_amd64.go
│   │       │       ├── zsysnum_freebsd_386.go
│   │       │       ├── zsysnum_freebsd_amd64.go
│   │       │       ├── zsysnum_freebsd_arm.go
│   │       │       ├── zsysnum_linux_386.go
│   │       │       ├── zsysnum_linux_amd64.go
│   │       │       ├── zsysnum_linux_arm.go
│   │       │       ├── zsysnum_linux_arm64.go
│   │       │       ├── zsysnum_linux_mips64.go
│   │       │       ├── zsysnum_linux_mips64le.go
│   │       │       ├── zsysnum_linux_ppc64.go
│   │       │       ├── zsysnum_linux_ppc64le.go
│   │       │       ├── zsysnum_linux_s390x.go
│   │       │       ├── zsysnum_netbsd_386.go
│   │       │       ├── zsysnum_netbsd_amd64.go
│   │       │       ├── zsysnum_netbsd_arm.go
│   │       │       ├── zsysnum_openbsd_386.go
│   │       │       ├── zsysnum_openbsd_amd64.go
│   │       │       ├── zsysnum_solaris_amd64.go
│   │       │       ├── ztypes_darwin_386.go
│   │       │       ├── ztypes_darwin_amd64.go
│   │       │       ├── ztypes_darwin_arm.go
│   │       │       ├── ztypes_darwin_arm64.go
│   │       │       ├── ztypes_dragonfly_amd64.go
│   │       │       ├── ztypes_freebsd_386.go
│   │       │       ├── ztypes_freebsd_amd64.go
│   │       │       ├── ztypes_freebsd_arm.go
│   │       │       ├── ztypes_linux_386.go
│   │       │       ├── ztypes_linux_amd64.go
│   │       │       ├── ztypes_linux_arm.go
│   │       │       ├── ztypes_linux_arm64.go
│   │       │       ├── ztypes_linux_mips64.go
│   │       │       ├── ztypes_linux_mips64le.go
│   │       │       ├── ztypes_linux_ppc64.go
│   │       │       ├── ztypes_linux_ppc64le.go
│   │       │       ├── ztypes_linux_s390x.go
│   │       │       ├── ztypes_netbsd_386.go
│   │       │       ├── ztypes_netbsd_amd64.go
│   │       │       ├── ztypes_netbsd_arm.go
│   │       │       ├── ztypes_openbsd_386.go
│   │       │       ├── ztypes_openbsd_amd64.go
│   │       │       └── ztypes_solaris_amd64.go
│   │       └── text/
│   │           ├── AUTHORS
│   │           ├── CONTRIBUTORS
│   │           ├── LICENSE
│   │           ├── PATENTS
│   │           ├── internal/
│   │           │   ├── gen/
│   │           │   │   ├── code.go
│   │           │   │   └── gen.go
│   │           │   ├── triegen/
│   │           │   │   ├── compact.go
│   │           │   │   ├── print.go
│   │           │   │   └── triegen.go
│   │           │   └── ucd/
│   │           │       └── ucd.go
│   │           ├── transform/
│   │           │   └── transform.go
│   │           └── unicode/
│   │               ├── cldr/
│   │               │   ├── base.go
│   │               │   ├── cldr.go
│   │               │   ├── collate.go
│   │               │   ├── decode.go
│   │               │   ├── makexml.go
│   │               │   ├── resolve.go
│   │               │   ├── slice.go
│   │               │   └── xml.go
│   │               └── norm/
│   │                   ├── composition.go
│   │                   ├── forminfo.go
│   │                   ├── input.go
│   │                   ├── iter.go
│   │                   ├── maketables.go
│   │                   ├── normalize.go
│   │                   ├── readwriter.go
│   │                   ├── tables.go
│   │                   ├── transform.go
│   │                   ├── trie.go
│   │                   └── triegen.go
│   ├── google.golang.org/
│   │   └── appengine/
│   │       ├── LICENSE
│   │       └── cloudsql/
│   │           ├── cloudsql.go
│   │           ├── cloudsql_classic.go
│   │           └── cloudsql_vm.go
│   └── gopkg.in/
│       ├── asn1-ber.v1/
│       │   ├── .travis.yml
│       │   ├── LICENSE
│       │   ├── README.md
│       │   ├── ber.go
│       │   ├── content_int.go
│       │   ├── header.go
│       │   ├── identifier.go
│       │   ├── length.go
│       │   └── util.go
│       ├── ldap.v3/
│       │   ├── .gitignore
│       │   ├── .travis.yml
│       │   ├── CONTRIBUTING.md
│       │   ├── LICENSE
│       │   ├── Makefile
│       │   ├── README.md
│       │   ├── add.go
│       │   ├── bind.go
│       │   ├── client.go
│       │   ├── compare.go
│       │   ├── conn.go
│       │   ├── control.go
│       │   ├── debug.go
│       │   ├── del.go
│       │   ├── dn.go
│       │   ├── doc.go
│       │   ├── error.go
│       │   ├── filter.go
│       │   ├── ldap.go
│       │   ├── moddn.go
│       │   ├── modify.go
│       │   ├── passwdmodify.go
│       │   └── search.go
│       └── yaml.v2/
│           ├── .travis.yml
│           ├── LICENSE
│           ├── LICENSE.libyaml
│           ├── README.md
│           ├── apic.go
│           ├── decode.go
│           ├── emitterc.go
│           ├── encode.go
│           ├── parserc.go
│           ├── readerc.go
│           ├── resolve.go
│           ├── scannerc.go
│           ├── sorter.go
│           ├── writerc.go
│           ├── yaml.go
│           ├── yamlh.go
│           └── yamlprivateh.go
└── version.go
Download .txt
Showing preview only (4,268K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (55883 symbols across 542 files)

FILE: api/core/api.go
  type API (line 44) | type API struct
    method Serve (line 48) | func (r *API) Serve() error {
    method status (line 56) | func (r *API) status(w api.ResponseWriter, req *rest.Request) {
    method remove (line 69) | func (r *API) remove(w api.ResponseWriter, req *rest.Request) {
    method announce (line 118) | func (r *API) announce(w api.ResponseWriter, req *rest.Request) {
  type removeParam (line 92) | type removeParam struct
    method UnmarshalJSON (line 96) | func (r *removeParam) UnmarshalJSON(data []byte) error {
  type announceParam (line 134) | type announceParam struct
    method UnmarshalJSON (line 139) | func (r *announceParam) UnmarshalJSON(data []byte) error {

FILE: api/response.go
  type Status (line 42) | type Status
  constant StatusOkay (line 45) | StatusOkay = 200
  constant StatusInvalidParameter (line 47) | StatusInvalidParameter    = 400
  constant StatusIncorrectCredential (line 48) | StatusIncorrectCredential = 401
  constant StatusUnknownSession (line 49) | StatusUnknownSession      = 402
  constant StatusPermissionDenied (line 50) | StatusPermissionDenied    = 403
  constant StatusDuplicated (line 51) | StatusDuplicated          = 404
  constant StatusNotFound (line 52) | StatusNotFound            = 405
  constant StatusBlockedAccount (line 53) | StatusBlockedAccount      = 406
  constant StatusBlockedHost (line 54) | StatusBlockedHost         = 407
  constant StatusInternalServerError (line 56) | StatusInternalServerError = 500
  constant StatusServiceUnavailable (line 57) | StatusServiceUnavailable  = 501
  type Response (line 60) | type Response struct
  function ResponseHandler (line 66) | func ResponseHandler(f func(ResponseWriter, *rest.Request)) func(rest.Re...
  type ResponseWriter (line 73) | type ResponseWriter interface
  type logWriter (line 84) | type logWriter struct
    method Header (line 88) | func (r *logWriter) Header() http.Header {
    method Write (line 92) | func (r *logWriter) Write(resp Response) {
    method WriteHeader (line 107) | func (r *logWriter) WriteHeader(status int) {

FILE: api/server.go
  type Server (line 42) | type Server struct
    method validate (line 62) | func (r *Server) validate() error {
    method Serve (line 73) | func (r *Server) Serve(routes ...*rest.Route) error {
  type Observer (line 52) | type Observer interface
  type Controller (line 56) | type Controller interface

FILE: api/ui/api.go
  type API (line 46) | type API struct
    method Serve (line 220) | func (r *API) Serve() error {
    method announce (line 267) | func (r *API) announce(cidr, mac string) error {
  type Database (line 54) | type Database interface
  type LDAP (line 60) | type LDAP interface
  type Transaction (line 64) | type Transaction interface
  type Search (line 77) | type Search struct
    method Validate (line 82) | func (r *Search) Validate() error {
  function validateIP (line 103) | func validateIP(ip string) error {
  function validateMAC (line 137) | func validateMAC(mac string) error {
  type Sort (line 176) | type Sort struct
    method Validate (line 181) | func (r *Sort) Validate() error {
  type Column (line 192) | type Column
  constant ColumnInvalid (line 195) | ColumnInvalid Column = iota
  constant ColumnTime (line 196) | ColumnTime
  constant ColumnIP (line 197) | ColumnIP
  constant ColumnMAC (line 198) | ColumnMAC
  constant ColumnPort (line 199) | ColumnPort
  constant ColumnGroup (line 200) | ColumnGroup
  constant ColumnDescription (line 201) | ColumnDescription
  constant ColumnUser (line 202) | ColumnUser
  constant ColumnLogType (line 203) | ColumnLogType
  constant ColumnLogMethod (line 204) | ColumnLogMethod
  type Order (line 207) | type Order
  constant OrderInvalid (line 210) | OrderInvalid Order = iota
  constant OrderAscending (line 211) | OrderAscending
  constant OrderDescending (line 212) | OrderDescending
  type Pagination (line 215) | type Pagination struct

FILE: api/ui/category.go
  type CategoryTransaction (line 41) | type CategoryTransaction interface
  type Category (line 51) | type Category struct
    method MarshalJSON (line 57) | func (r *Category) MarshalJSON() ([]byte, error) {
  method listCategory (line 69) | func (r *API) listCategory(w api.ResponseWriter, req *rest.Request) {
  type listCategoryParam (line 96) | type listCategoryParam struct
    method UnmarshalJSON (line 101) | func (r *listCategoryParam) UnmarshalJSON(data []byte) error {
    method validate (line 114) | func (r *listCategoryParam) validate() error {
  method addCategory (line 122) | func (r *API) addCategory(w api.ResponseWriter, req *rest.Request) {
  type addCategoryParam (line 156) | type addCategoryParam struct
    method UnmarshalJSON (line 161) | func (r *addCategoryParam) UnmarshalJSON(data []byte) error {
    method validate (line 174) | func (r *addCategoryParam) validate() error {
  method updateCategory (line 185) | func (r *API) updateCategory(w api.ResponseWriter, req *rest.Request) {
  type updateCategoryParam (line 223) | type updateCategoryParam struct
    method UnmarshalJSON (line 229) | func (r *updateCategoryParam) UnmarshalJSON(data []byte) error {
    method validate (line 243) | func (r *updateCategoryParam) validate() error {
  method removeCategory (line 257) | func (r *API) removeCategory(w api.ResponseWriter, req *rest.Request) {
  type removeCategoryParam (line 290) | type removeCategoryParam struct
    method UnmarshalJSON (line 295) | func (r *removeCategoryParam) UnmarshalJSON(data []byte) error {
    method validate (line 308) | func (r *removeCategoryParam) validate() error {

FILE: api/ui/component.go
  type ComponentTransaction (line 41) | type ComponentTransaction interface
  type Component (line 51) | type Component struct
    method MarshalJSON (line 58) | func (r *Component) MarshalJSON() ([]byte, error) {
  method listComponent (line 72) | func (r *API) listComponent(w api.ResponseWriter, req *rest.Request) {
  type listComponentParam (line 99) | type listComponentParam struct
    method UnmarshalJSON (line 105) | func (r *listComponentParam) UnmarshalJSON(data []byte) error {
    method validate (line 119) | func (r *listComponentParam) validate() error {
  method addComponent (line 130) | func (r *API) addComponent(w api.ResponseWriter, req *rest.Request) {
  type addComponentParam (line 164) | type addComponentParam struct
    method UnmarshalJSON (line 170) | func (r *addComponentParam) UnmarshalJSON(data []byte) error {
    method validate (line 184) | func (r *addComponentParam) validate() error {
  method updateComponent (line 198) | func (r *API) updateComponent(w api.ResponseWriter, req *rest.Request) {
  type updateComponentParam (line 236) | type updateComponentParam struct
    method UnmarshalJSON (line 242) | func (r *updateComponentParam) UnmarshalJSON(data []byte) error {
    method validate (line 256) | func (r *updateComponentParam) validate() error {
  method removeComponent (line 270) | func (r *API) removeComponent(w api.ResponseWriter, req *rest.Request) {
  type removeComponentParam (line 303) | type removeComponentParam struct
    method UnmarshalJSON (line 308) | func (r *removeComponentParam) UnmarshalJSON(data []byte) error {
    method validate (line 321) | func (r *removeComponentParam) validate() error {

FILE: api/ui/group.go
  type GroupTransaction (line 41) | type GroupTransaction interface
  type Group (line 51) | type Group struct
    method MarshalJSON (line 57) | func (r *Group) MarshalJSON() ([]byte, error) {
  method listGroup (line 69) | func (r *API) listGroup(w api.ResponseWriter, req *rest.Request) {
  type listGroupParam (line 96) | type listGroupParam struct
    method UnmarshalJSON (line 101) | func (r *listGroupParam) UnmarshalJSON(data []byte) error {
    method validate (line 114) | func (r *listGroupParam) validate() error {
  method addGroup (line 122) | func (r *API) addGroup(w api.ResponseWriter, req *rest.Request) {
  type addGroupParam (line 156) | type addGroupParam struct
    method UnmarshalJSON (line 161) | func (r *addGroupParam) UnmarshalJSON(data []byte) error {
    method validate (line 174) | func (r *addGroupParam) validate() error {
  method updateGroup (line 185) | func (r *API) updateGroup(w api.ResponseWriter, req *rest.Request) {
  type updateGroupParam (line 223) | type updateGroupParam struct
    method UnmarshalJSON (line 229) | func (r *updateGroupParam) UnmarshalJSON(data []byte) error {
    method validate (line 243) | func (r *updateGroupParam) validate() error {
  method removeGroup (line 257) | func (r *API) removeGroup(w api.ResponseWriter, req *rest.Request) {
  type removeGroupParam (line 290) | type removeGroupParam struct
    method UnmarshalJSON (line 295) | func (r *removeGroupParam) UnmarshalJSON(data []byte) error {
    method validate (line 308) | func (r *removeGroupParam) validate() error {

FILE: api/ui/host.go
  type HostTransaction (line 49) | type HostTransaction interface
  type Host (line 65) | type Host struct
    method MarshalJSON (line 78) | func (r *Host) MarshalJSON() ([]byte, error) {
  type Spec (line 104) | type Spec struct
  method listHost (line 110) | func (r *API) listHost(w api.ResponseWriter, req *rest.Request) {
  type listHostParam (line 137) | type listHostParam struct
    method UnmarshalJSON (line 144) | func (r *listHostParam) UnmarshalJSON(data []byte) error {
    method validate (line 159) | func (r *listHostParam) validate() error {
  method getHost (line 179) | func (r *API) getHost(w api.ResponseWriter, req *rest.Request) {
  type getHostParam (line 211) | type getHostParam struct
    method UnmarshalJSON (line 216) | func (r *getHostParam) UnmarshalJSON(data []byte) error {
    method validate (line 229) | func (r *getHostParam) validate() error {
  method addHost (line 240) | func (r *API) addHost(w api.ResponseWriter, req *rest.Request) {
  type addHostParam (line 291) | type addHostParam struct
    method UnmarshalJSON (line 300) | func (r *addHostParam) UnmarshalJSON(data []byte) error {
  type SpecParam (line 350) | type SpecParam struct
    method Validate (line 355) | func (r *SpecParam) Validate() error {
  method updateHost (line 366) | func (r *API) updateHost(w api.ResponseWriter, req *rest.Request) {
  type updateHostParam (line 440) | type updateHostParam struct
    method UnmarshalJSON (line 450) | func (r *updateHostParam) UnmarshalJSON(data []byte) error {
  method activateHost (line 506) | func (r *API) activateHost(w api.ResponseWriter, req *rest.Request) {
  type activateHostParam (line 544) | type activateHostParam struct
    method UnmarshalJSON (line 549) | func (r *activateHostParam) UnmarshalJSON(data []byte) error {
    method validate (line 562) | func (r *activateHostParam) validate() error {
  method deactivateHost (line 573) | func (r *API) deactivateHost(w api.ResponseWriter, req *rest.Request) {
  type deactivateHostParam (line 619) | type deactivateHostParam struct
    method UnmarshalJSON (line 624) | func (r *deactivateHostParam) UnmarshalJSON(data []byte) error {
    method validate (line 637) | func (r *deactivateHostParam) validate() error {
  method removeHost (line 648) | func (r *API) removeHost(w api.ResponseWriter, req *rest.Request) {
  type removeHostParam (line 686) | type removeHostParam struct
    method UnmarshalJSON (line 691) | func (r *removeHostParam) UnmarshalJSON(data []byte) error {
    method validate (line 704) | func (r *removeHostParam) validate() error {

FILE: api/ui/ip.go
  type IPTransaction (line 39) | type IPTransaction interface
  type IP (line 43) | type IP struct
  method listIP (line 55) | func (r *API) listIP(w api.ResponseWriter, req *rest.Request) {
  type listIPParam (line 82) | type listIPParam struct
    method UnmarshalJSON (line 87) | func (r *listIPParam) UnmarshalJSON(data []byte) error {
    method validate (line 100) | func (r *listIPParam) validate() error {

FILE: api/ui/log.go
  type LogType (line 40) | type LogType
    method Validate (line 53) | func (r LogType) Validate() error {
  constant LogTypeUser (line 43) | LogTypeUser      LogType = "USER"
  constant LogTypeGroup (line 44) | LogTypeGroup     LogType = "GROUP"
  constant LogTypeSwitch (line 45) | LogTypeSwitch    LogType = "SWITCH"
  constant LogTypeNetwork (line 46) | LogTypeNetwork   LogType = "NETWORK"
  constant LogTypeHost (line 47) | LogTypeHost      LogType = "HOST"
  constant LogTypeVIP (line 48) | LogTypeVIP       LogType = "VIP"
  constant LogTypeCategory (line 49) | LogTypeCategory  LogType = "CATEGORY"
  constant LogTypeComponent (line 50) | LogTypeComponent LogType = "COMPONENT"
  type LogMethod (line 62) | type LogMethod
    method Validate (line 70) | func (r LogMethod) Validate() error {
  constant LogMethodAdd (line 65) | LogMethodAdd    LogMethod = "ADD"
  constant LogMethodUpdate (line 66) | LogMethodUpdate LogMethod = "UPDATE"
  constant LogMethodRemove (line 67) | LogMethodRemove LogMethod = "REMOVE"
  type LogTransaction (line 78) | type LogTransaction interface
  type Log (line 83) | type Log struct
    method MarshalJSON (line 92) | func (r *Log) MarshalJSON() ([]byte, error) {
  method listLog (line 110) | func (r *API) listLog(w api.ResponseWriter, req *rest.Request) {
  type listLogParam (line 137) | type listLogParam struct
    method UnmarshalJSON (line 143) | func (r *listLogParam) UnmarshalJSON(data []byte) error {
    method validate (line 157) | func (r *listLogParam) validate() error {

FILE: api/ui/network.go
  type NetworkTransaction (line 41) | type NetworkTransaction interface
  type Network (line 49) | type Network struct
  method listNetwork (line 56) | func (r *API) listNetwork(w api.ResponseWriter, req *rest.Request) {
  type listNetworkParam (line 83) | type listNetworkParam struct
    method UnmarshalJSON (line 89) | func (r *listNetworkParam) UnmarshalJSON(data []byte) error {
    method validate (line 103) | func (r *listNetworkParam) validate() error {
  method addNetwork (line 116) | func (r *API) addNetwork(w api.ResponseWriter, req *rest.Request) {
  type addNetworkParam (line 150) | type addNetworkParam struct
    method UnmarshalJSON (line 157) | func (r *addNetworkParam) UnmarshalJSON(data []byte) error {
  function validateGateway (line 194) | func validateGateway(n net.IPNet, g net.IP) error {
  method removeNetwork (line 216) | func (r *API) removeNetwork(w api.ResponseWriter, req *rest.Request) {
  type removeNetworkParam (line 257) | type removeNetworkParam struct
    method UnmarshalJSON (line 262) | func (r *removeNetworkParam) UnmarshalJSON(data []byte) error {
    method validate (line 275) | func (r *removeNetworkParam) validate() error {

FILE: api/ui/session.go
  type session (line 40) | type session struct
    method Add (line 57) | func (r *session) Add(v interface{}) (id string) {
    method Get (line 77) | func (r *session) Get(id string) (interface{}, bool) {
    method Remove (line 95) | func (r *session) Remove(id string) bool {
  function newSession (line 45) | func newSession(size int, timeout time.Duration) *session {
  type sessionEntry (line 65) | type sessionEntry struct
  function hash (line 70) | func hash(value string) string {

FILE: api/ui/switch.go
  type SwitchTransaction (line 43) | type SwitchTransaction interface
  type Switch (line 50) | type Switch struct
    method MarshalJSON (line 59) | func (r *Switch) MarshalJSON() ([]byte, error) {
  function hexDPID (line 83) | func hexDPID(dpid uint64) string {
  method listSwitch (line 89) | func (r *API) listSwitch(w api.ResponseWriter, req *rest.Request) {
  type listSwitchParam (line 116) | type listSwitchParam struct
    method UnmarshalJSON (line 121) | func (r *listSwitchParam) UnmarshalJSON(data []byte) error {
    method validate (line 134) | func (r *listSwitchParam) validate() error {
  method addSwitch (line 145) | func (r *API) addSwitch(w api.ResponseWriter, req *rest.Request) {
  type addSwitchParam (line 179) | type addSwitchParam struct
    method UnmarshalJSON (line 188) | func (r *addSwitchParam) UnmarshalJSON(data []byte) error {
  method removeSwitch (line 242) | func (r *API) removeSwitch(w api.ResponseWriter, req *rest.Request) {
  type removeSwitchParam (line 283) | type removeSwitchParam struct
    method UnmarshalJSON (line 288) | func (r *removeSwitchParam) UnmarshalJSON(data []byte) error {
    method validate (line 301) | func (r *removeSwitchParam) validate() error {

FILE: api/ui/user.go
  type UserTransaction (line 42) | type UserTransaction interface
  type User (line 51) | type User struct
    method MarshalJSON (line 60) | func (r *User) MarshalJSON() ([]byte, error) {
  method login (line 76) | func (r *API) login(w api.ResponseWriter, req *rest.Request) {
  type loginParam (line 141) | type loginParam struct
    method UnmarshalJSON (line 147) | func (r *loginParam) UnmarshalJSON(data []byte) error {
    method validate (line 161) | func (r *loginParam) validate() error {
  method logout (line 175) | func (r *API) logout(w api.ResponseWriter, req *rest.Request) {
  type logoutParam (line 192) | type logoutParam struct
    method UnmarshalJSON (line 196) | func (r *logoutParam) UnmarshalJSON(data []byte) error {
    method validate (line 208) | func (r *logoutParam) validate() error {
  method listUser (line 216) | func (r *API) listUser(w api.ResponseWriter, req *rest.Request) {
  type listUserParam (line 248) | type listUserParam struct
    method UnmarshalJSON (line 253) | func (r *listUserParam) UnmarshalJSON(data []byte) error {
    method validate (line 266) | func (r *listUserParam) validate() error {
  method addUser (line 277) | func (r *API) addUser(w api.ResponseWriter, req *rest.Request) {
  type addUserParam (line 330) | type addUserParam struct
    method UnmarshalJSON (line 335) | func (r *addUserParam) UnmarshalJSON(data []byte) error {
    method validate (line 348) | func (r *addUserParam) validate() error {
  function generateOTPKey (line 359) | func generateOTPKey(account string) (*otp.Key, error) {
  method updateUser (line 366) | func (r *API) updateUser(w api.ResponseWriter, req *rest.Request) {
  type updateUserParam (line 403) | type updateUserParam struct
    method UnmarshalJSON (line 410) | func (r *updateUserParam) UnmarshalJSON(data []byte) error {
    method validate (line 425) | func (r *updateUserParam) validate() error {
  method resetOTP (line 439) | func (r *API) resetOTP(w api.ResponseWriter, req *rest.Request) {
  type resetOTPParam (line 481) | type resetOTPParam struct
    method UnmarshalJSON (line 486) | func (r *resetOTPParam) UnmarshalJSON(data []byte) error {
    method validate (line 499) | func (r *resetOTPParam) validate() error {

FILE: api/ui/vip.go
  type VIPTransaction (line 41) | type VIPTransaction interface
  type VIP (line 50) | type VIP struct
  method listVIP (line 58) | func (r *API) listVIP(w api.ResponseWriter, req *rest.Request) {
  type listVIPParam (line 85) | type listVIPParam struct
    method UnmarshalJSON (line 90) | func (r *listVIPParam) UnmarshalJSON(data []byte) error {
    method validate (line 103) | func (r *listVIPParam) validate() error {
  method addVIP (line 114) | func (r *API) addVIP(w api.ResponseWriter, req *rest.Request) {
  type addVIPParam (line 153) | type addVIPParam struct
    method UnmarshalJSON (line 161) | func (r *addVIPParam) UnmarshalJSON(data []byte) error {
    method validate (line 177) | func (r *addVIPParam) validate() error {
  method removeVIP (line 197) | func (r *API) removeVIP(w api.ResponseWriter, req *rest.Request) {
  type removeVIPParam (line 235) | type removeVIPParam struct
    method UnmarshalJSON (line 240) | func (r *removeVIPParam) UnmarshalJSON(data []byte) error {
    method validate (line 253) | func (r *removeVIPParam) validate() error {
  method toggleVIP (line 264) | func (r *API) toggleVIP(w api.ResponseWriter, req *rest.Request) {
  type toggleVIPParam (line 302) | type toggleVIPParam struct
    method UnmarshalJSON (line 307) | func (r *toggleVIPParam) UnmarshalJSON(data []byte) error {
    method validate (line 320) | func (r *toggleVIPParam) validate() error {

FILE: cmd/cherry/main.go
  constant programName (line 52) | programName     = "cherry"
  constant programVersion (line 53) | programVersion  = cherry.Version
  constant defaultLogLevel (line 54) | defaultLogLevel = logging.INFO
  function main (line 64) | func main() {
  function initConfig (line 97) | func initConfig() {
  function validateConfig (line 121) | func validateConfig() error {
  function initElectionObserver (line 142) | func initElectionObserver(ctx context.Context, db *database.MySQL) *elec...
  function initAPIServer (line 154) | func initAPIServer(observer *election.Observer, controller *network.Cont...
  function initSignalHandler (line 172) | func initSignalHandler(controller *network.Controller, manager *northbou...
  function initLog (line 198) | func initLog(level logging.Level) error {
  function getLogLevel (line 213) | func getLogLevel(level string) logging.Level {
  function listen (line 224) | func listen(ctx context.Context, port int, controller *network.Controlle...
  function createAppManager (line 285) | func createAppManager(db *database.MySQL) (*northbound.Manager, error) {
  function parseApplications (line 304) | func parseApplications() ([]string, error) {

FILE: cmd/walnut/main.go
  constant programName (line 52) | programName     = "walnut"
  constant programVersion (line 53) | programVersion  = cherry.Version
  constant defaultLogLevel (line 54) | defaultLogLevel = logging.INFO
  function init (line 66) | func init() {
  function main (line 71) | func main() {
  function parseCmdLines (line 81) | func parseCmdLines() {
  function initConfig (line 93) | func initConfig() {
  function validateConfig (line 119) | func validateConfig() error {
  function initLog (line 124) | func initLog() {
  function getLogLevel (line 149) | func getLogLevel() logging.Level {
  function initDatabase (line 160) | func initDatabase() *database.MySQL {
  function initCoreSDK (line 169) | func initCoreSDK() *coreSDK {
  function initLDAPClient (line 178) | func initLDAPClient() *ldap.Client {
  function initAPIServer (line 182) | func initAPIServer() {
  function waitSignal (line 202) | func waitSignal() {

FILE: cmd/walnut/sdk.go
  type coreSDK (line 25) | type coreSDK struct
    method Announce (line 49) | func (r *coreSDK) Announce(ip net.IP, mac net.HardwareAddr) error {
    method RemoveFlows (line 61) | func (r *coreSDK) RemoveFlows() error {
    method RemoveFlowsByMAC (line 65) | func (r *coreSDK) RemoveFlowsByMAC(mac net.HardwareAddr) error {
    method IsMaster (line 73) | func (r *coreSDK) IsMaster() bool {
    method call (line 84) | func (r *coreSDK) call(method, command string, param interface{}, resu...
  function newCoreSDK (line 30) | func newCoreSDK(baseURL string) (*coreSDK, error) {

FILE: database/mysql.go
  constant maxDeadlockRetry (line 51) | maxDeadlockRetry = 5
  constant deadlockErrCode (line 53) | deadlockErrCode   uint16 = 1213
  constant duplicatedErrCode (line 54) | duplicatedErrCode uint16 = 1062
  constant foreignkeyErrCode (line 55) | foreignkeyErrCode uint16 = 1451
  constant clusterDialerNetwork (line 57) | clusterDialerNetwork = "cluster"
  type MySQL (line 67) | type MySQL struct
    method query (line 165) | func (r *MySQL) query(f func(*sql.Tx) error) error {
    method MAC (line 215) | func (r *MySQL) MAC(ip net.IP) (mac net.HardwareAddr, ok bool, err err...
    method Location (line 271) | func (r *MySQL) Location(mac net.HardwareAddr) (dpid string, port uint...
    method TogglePortVIP (line 316) | func (r *MySQL) TogglePortVIP(swDPID uint64, portNum uint16) (result [...
    method ToggleDeviceVIP (line 347) | func (r *MySQL) ToggleDeviceVIP(swDPID uint64) (result []virtualip.Add...
    method GetUndiscoveredHosts (line 511) | func (r *MySQL) GetUndiscoveredHosts(expiration time.Duration) (result...
    method UpdateHostLocation (line 562) | func (r *MySQL) UpdateHostLocation(mac net.HardwareAddr, ip net.IP, sw...
    method ResetHostLocationsByPort (line 642) | func (r *MySQL) ResetHostLocationsByPort(swDPID uint64, portNum uint16...
    method ResetHostLocationsByDevice (line 662) | func (r *MySQL) ResetHostLocationsByDevice(swDPID uint64) error {
    method Elect (line 684) | func (r *MySQL) Elect(uid string, expiration time.Duration) (elected b...
    method MACAddrs (line 703) | func (r *MySQL) MACAddrs() (result []net.HardwareAddr, err error) {
    method RenewARPTable (line 736) | func (r *MySQL) RenewARPTable() error {
    method GetARPTable (line 816) | func (r *MySQL) GetARPTable() (result []announcer.ARPTableEntry, err e...
    method DHCP (line 894) | func (r *MySQL) DHCP(mac net.HardwareAddr) (conf *dhcp.NetConfig, err ...
    method Exec (line 936) | func (r *MySQL) Exec(f func(ui.Transaction) error) error {
  function NewMySQL (line 72) | func NewMySQL() (*MySQL, error) {
  function validateClusterAddr (line 100) | func validateClusterAddr(addr string) error {
  function clusterDialer (line 121) | func clusterDialer(addr string) (net.Conn, error) {
  function isDeadlock (line 138) | func isDeadlock(err error) bool {
  function isDuplicated (line 147) | func isDuplicated(err error) bool {
  function isForeignkeyErr (line 156) | func isForeignkeyErr(err error) bool {
  function caller (line 201) | func caller() string {
  function portID (line 374) | func portID(tx *sql.Tx, swDPID uint64, portNum uint16) (uint64, error) {
  type vip (line 398) | type vip struct
  function getPortVIPs (line 405) | func getPortVIPs(tx *sql.Tx, portID uint64) (result []vip, err error) {
  function getDeviceVIPs (line 437) | func getDeviceVIPs(tx *sql.Tx, swDPID uint64) (result []vip, err error) {
  function swapVIPHosts (line 471) | func swapVIPHosts(tx *sql.Tx, v vip) error {
  function hostMAC (line 486) | func hostMAC(tx *sql.Tx, hostID uint64) (net.HardwareAddr, error) {
  function getHostID (line 593) | func getHostID(tx *sql.Tx, mac net.HardwareAddr, ip net.IP) (hostID uint...
  function updateLocation (line 618) | func updateLocation(tx *sql.Tx, hostID, portID uint64) (updated bool, er...
  type arpEntry (line 759) | type arpEntry struct
  function getHostARPEntries (line 764) | func getHostARPEntries(tx *sql.Tx) (result []arpEntry, err error) {
  function getVIPARPEntries (line 790) | func getVIPARPEntries(tx *sql.Tx) (result []arpEntry, err error) {
  function updateARPTableEntryByHost (line 851) | func updateARPTableEntryByHost(tx *sql.Tx, id uint64, invalidate bool) e...
  function updateARPTableEntryByVIP (line 867) | func updateARPTableEntryByVIP(tx *sql.Tx, id uint64, invalidate bool) er...
  function updateARPTableEntry (line 884) | func updateARPTableEntry(tx *sql.Tx, ip, mac string) error {
  type uiTx (line 972) | type uiTx struct
    method Groups (line 976) | func (r *uiTx) Groups(pagination ui.Pagination) (group []*ui.Group, er...
    method AddGroup (line 1005) | func (r *uiTx) AddGroup(requesterID uint64, name string) (group *ui.Gr...
    method UpdateGroup (line 1044) | func (r *uiTx) UpdateGroup(requesterID, groupID uint64, name string) (...
    method RemoveGroup (line 1074) | func (r *uiTx) RemoveGroup(requesterID, groupID uint64) (group *ui.Gro...
    method Hosts (line 1098) | func (r *uiTx) Hosts(search *ui.Search, sort ui.Sort, pagination ui.Pa...
    method Host (line 1253) | func (r *uiTx) Host(id uint64) (host *ui.Host, err error) {
    method AddHost (line 1347) | func (r *uiTx) AddHost(requesterID, ipID uint64, groupID *uint64, mac ...
    method UpdateHost (line 1438) | func (r *uiTx) UpdateHost(requesterID, hostID uint64, ipID, groupID *u...
    method ActivateHost (line 1499) | func (r *uiTx) ActivateHost(requesterID, hostID uint64) (host *ui.Host...
    method DeactivateHost (line 1530) | func (r *uiTx) DeactivateHost(requesterID, hostID uint64) (host *ui.Ho...
    method CountVIPByHostID (line 1561) | func (r *uiTx) CountVIPByHostID(id uint64) (count uint64, err error) {
    method RemoveHost (line 1570) | func (r *uiTx) RemoveHost(requesterID, hostID uint64) (host *ui.Host, ...
    method IPAddrs (line 1604) | func (r *uiTx) IPAddrs(networkID uint64) (address []*ui.IP, err error) {
    method Networks (line 1653) | func (r *uiTx) Networks(address *string, pagination ui.Pagination) (ne...
    method AddNetwork (line 1686) | func (r *uiTx) AddNetwork(requesterID uint64, addr net.IP, mask net.IP...
    method RemoveNetwork (line 1777) | func (r *uiTx) RemoveNetwork(requesterID, netID uint64) (network *ui.N...
    method Switches (line 1801) | func (r *uiTx) Switches(pagination ui.Pagination) (sw []*ui.Switch, er...
    method AddSwitch (line 1828) | func (r *uiTx) AddSwitch(requesterID, dpid uint64, nPorts, firstPort, ...
    method RemoveSwitch (line 1897) | func (r *uiTx) RemoveSwitch(requesterID, swID uint64) (sw *ui.Switch, ...
    method User (line 1921) | func (r *uiTx) User(name string) (user *ui.User, err error) {
    method Users (line 1937) | func (r *uiTx) Users(pagination ui.Pagination) (user []*ui.User, err e...
    method AddUser (line 1964) | func (r *uiTx) AddUser(requesterID uint64, name, key string) (user *ui...
    method UpdateUser (line 2005) | func (r *uiTx) UpdateUser(requesterID, userID uint64, enabled, admin *...
    method ResetOTPKey (line 2047) | func (r *uiTx) ResetOTPKey(name, key string) (ok bool, err error) {
    method VIPs (line 2064) | func (r *uiTx) VIPs(pagination ui.Pagination) (vip []*ui.VIP, err erro...
    method getVIPs (line 2108) | func (r *uiTx) getVIPs(pagination ui.Pagination) (vip []registeredVIP,...
    method AddVIP (line 2137) | func (r *uiTx) AddVIP(requesterID, ipID, activeID, standbyID uint64, d...
    method RemoveVIP (line 2242) | func (r *uiTx) RemoveVIP(requesterID, vipID uint64) (vip *ui.VIP, err ...
    method ToggleVIP (line 2266) | func (r *uiTx) ToggleVIP(requesterID, vipID uint64) (res *ui.VIP, err ...
    method QueryLog (line 2302) | func (r *uiTx) QueryLog(search *ui.Search, pagination ui.Pagination) (...
    method log (line 2396) | func (r *uiTx) log(userID uint64, t logType, m logMethod, data interfa...
    method Categories (line 2413) | func (r *uiTx) Categories(pagination ui.Pagination) (category []*ui.Ca...
    method AddCategory (line 2442) | func (r *uiTx) AddCategory(requesterID uint64, name string) (category ...
    method UpdateCategory (line 2481) | func (r *uiTx) UpdateCategory(requesterID, categoryID uint64, name str...
    method RemoveCategory (line 2512) | func (r *uiTx) RemoveCategory(requesterID, categoryID uint64) (categor...
    method Components (line 2536) | func (r *uiTx) Components(categoryID uint64, pagination ui.Pagination)...
    method AddComponent (line 2568) | func (r *uiTx) AddComponent(requesterID, categoryID uint64, name strin...
    method UpdateComponent (line 2608) | func (r *uiTx) UpdateComponent(requesterID, componentID uint64, name s...
    method RemoveComponent (line 2639) | func (r *uiTx) RemoveComponent(requesterID, componentID uint64) (compo...
  function getGroup (line 1031) | func getGroup(tx *sql.Tx, id uint64) (*ui.Group, error) {
  function buildHostsQuery (line 1142) | func buildHostsQuery(search *ui.Search, sort ui.Sort, pagination ui.Pagi...
  function rangeIP (line 1218) | func rangeIP(ip string) (start, end uint32) {
  function convertIPToInt (line 1231) | func convertIPToInt(ip net.IP) uint32 {
  function rangeMAC (line 1240) | func rangeMAC(mac string) (start, end string) {
  function getHost (line 1266) | func getHost(tx *sql.Tx, id uint64) (*host, error) {
  type host (line 1313) | type host struct
    method convert (line 1332) | func (r *host) convert() *ui.Host {
  function addNewHost (line 1363) | func addNewHost(tx *sql.Tx, ipID uint64, groupID *uint64, mac net.Hardwa...
  function isAvailableIP (line 1402) | func isAvailableIP(tx *sql.Tx, id uint64) (bool, error) {
  function encodeMAC (line 1421) | func encodeMAC(mac net.HardwareAddr) string {
  function decodeMAC (line 1426) | func decodeMAC(s string) (net.HardwareAddr, error) {
  function updateHost (line 1470) | func updateHost(tx *sql.Tx, old *host, ipID, groupID *uint64, mac net.Ha...
  function removeHost (line 1591) | func removeHost(tx *sql.Tx, id uint64) error {
  function addNetwork (line 1711) | func addNetwork(tx *sql.Tx, addr net.IP, mask net.IPMask, gateway net.IP...
  function addIPAddrs (line 1726) | func addIPAddrs(tx *sql.Tx, netID uint64, addr net.IP, mask net.IPMask) ...
  function calculateIP (line 1753) | func calculateIP(network net.IP, n uint32) net.IP {
  function getNetwork (line 1764) | func getNetwork(tx *sql.Tx, id uint64) (*ui.Network, error) {
  function addSwitch (line 1854) | func addSwitch(tx *sql.Tx, dpid uint64, nPorts, firstPort, firstPrintedP...
  function addPorts (line 1868) | func addPorts(tx *sql.Tx, swID uint64, firstPort, n_ports uint16) error {
  function getSwitch (line 1884) | func getSwitch(tx *sql.Tx, id uint64) (*ui.Switch, error) {
  function getUser (line 1992) | func getUser(tx *sql.Tx, id uint64) (*ui.User, error) {
  type registeredVIP (line 2100) | type registeredVIP struct
  function addNewVIP (line 2163) | func addNewVIP(tx *sql.Tx, ipID, activeID, standbyID uint64, desc string...
  function isEnabledHost (line 2197) | func isEnabledHost(tx *sql.Tx, id uint64) (enabled bool, err error) {
  function getVIP (line 2206) | func getVIP(tx *sql.Tx, id uint64) (vip *ui.VIP, err error) {
  function buildLogsQuery (line 2325) | func buildLogsQuery(search *ui.Search, pagination ui.Pagination) (qry st...
  type logType (line 2357) | type logType
    method validate (line 2371) | func (r logType) validate() error {
  constant logTypeInvalid (line 2360) | logTypeInvalid logType = iota
  constant logTypeUser (line 2361) | logTypeUser
  constant logTypeGroup (line 2362) | logTypeGroup
  constant logTypeSwitch (line 2363) | logTypeSwitch
  constant logTypeNetwork (line 2364) | logTypeNetwork
  constant logTypeHost (line 2365) | logTypeHost
  constant logTypeVIP (line 2366) | logTypeVIP
  constant logTypeCategory (line 2367) | logTypeCategory
  constant logTypeComponent (line 2368) | logTypeComponent
  type logMethod (line 2379) | type logMethod
    method validate (line 2388) | func (r logMethod) validate() error {
  constant logMethodInvalid (line 2382) | logMethodInvalid logMethod = iota
  constant logMethodAdd (line 2383) | logMethodAdd
  constant logMethodUpdate (line 2384) | logMethodUpdate
  constant logMethodRemove (line 2385) | logMethodRemove
  function getCategory (line 2468) | func getCategory(tx *sql.Tx, id uint64) (category *ui.Category, err erro...
  function getComponent (line 2594) | func getComponent(tx *sql.Tx, id uint64) (component *ui.Component, err e...
  function getSpec (line 2663) | func getSpec(tx *sql.Tx, hostID uint64) (spec []*ui.Spec, err error) {
  function addSpec (line 2694) | func addSpec(tx *sql.Tx, hostID, componentID uint64, count uint16) error {

FILE: database/mysql_schema.sql
  type `user` (line 24) | CREATE TABLE IF NOT EXISTS `user` (
  type `group` (line 42) | CREATE TABLE IF NOT EXISTS `group` (
  type `log` (line 57) | CREATE TABLE IF NOT EXISTS `log` (
  type `category` (line 77) | CREATE TABLE IF NOT EXISTS `category` (
  type `component` (line 92) | CREATE TABLE IF NOT EXISTS `component` (
  type `spec` (line 109) | CREATE TABLE IF NOT EXISTS `spec` (
  type `arp` (line 127) | CREATE TABLE IF NOT EXISTS `arp` (
  type `master_election` (line 142) | CREATE TABLE IF NOT EXISTS `master_election` (
  type `acl` (line 156) | CREATE TABLE IF NOT EXISTS `acl` (
  type `network` (line 171) | CREATE TABLE IF NOT EXISTS `network` (
  type `switch` (line 187) | CREATE TABLE IF NOT EXISTS `switch` (
  type `port` (line 206) | CREATE TABLE IF NOT EXISTS `port` (
  type `ip` (line 222) | CREATE TABLE IF NOT EXISTS `ip` (
  type `host` (line 241) | CREATE TABLE IF NOT EXISTS `host` (
  type `vip` (line 318) | CREATE TABLE IF NOT EXISTS `vip` (

FILE: database/random.go
  type randomSource (line 30) | type randomSource struct
    method Int63 (line 35) | func (r *randomSource) Int63() (n int64) {
    method Seed (line 42) | func (r *randomSource) Seed(seed int64) {

FILE: election/election.go
  constant interval (line 41) | interval = 1 * time.Second
  type Observer (line 44) | type Observer struct
    method Run (line 72) | func (r *Observer) Run(ctx context.Context) error {
    method IsMaster (line 107) | func (r *Observer) IsMaster() bool {
    method setMaster (line 111) | func (r *Observer) setMaster(value bool) {
    method getMaster (line 118) | func (r *Observer) getMaster() bool {
  type Database (line 52) | type Database interface
  function New (line 59) | func New(db Database) *Observer {
  function generateRandomUID (line 66) | func generateRandomUID() string {

FILE: graph/graph.go
  type Vertex (line 41) | type Vertex interface
  type Point (line 46) | type Point interface
  type Edge (line 52) | type Edge interface
  type edge (line 58) | type edge struct
  type vertex (line 64) | type vertex struct
  type Graph (line 69) | type Graph struct
    method String (line 84) | func (r *Graph) String() string {
    method AddVertex (line 98) | func (r *Graph) AddVertex(v Vertex) {
    method removeEdge (line 118) | func (r *Graph) removeEdge(e Edge) {
    method RemoveVertex (line 133) | func (r *Graph) RemoveVertex(v Vertex) {
    method AddEdge (line 152) | func (r *Graph) AddEdge(e Edge) (added bool, err error) {
    method RemoveEdge (line 190) | func (r *Graph) RemoveEdge(p Point) {
    method IsEdge (line 204) | func (r *Graph) IsEdge(p Point) bool {
    method IsEnabledPoint (line 218) | func (r *Graph) IsEnabledPoint(p Point) bool {
    method pickRootVertex (line 253) | func (r *Graph) pickRootVertex() Vertex {
    method resetEdges (line 265) | func (r *Graph) resetEdges() *list.List {
    method pickValidVertexies (line 282) | func (r *Graph) pickValidVertexies() []Vertex {
    method makeClusters (line 294) | func (r *Graph) makeClusters() map[string]*list.List {
    method calculateMST (line 318) | func (r *Graph) calculateMST() {
    method FindPath (line 388) | func (r *Graph) FindPath(src, dst Vertex) []Path {
    method RemoveStaleEdges (line 462) | func (r *Graph) RemoveStaleEdges(expiration time.Duration) (removed bo...
  function New (line 76) | func New() *Graph {
  type sortedEdge (line 235) | type sortedEdge
    method Len (line 237) | func (r sortedEdge) Len() int {
    method Less (line 241) | func (r sortedEdge) Less(i, j int) bool {
    method Swap (line 249) | func (r sortedEdge) Swap(i, j int) {
  function mergeCluster (line 305) | func mergeCluster(clusters map[string]*list.List, l1, l2 *list.List) {
  type queue (line 359) | type queue struct
    method enqueue (line 367) | func (r *queue) enqueue(v interface{}) {
    method dequeue (line 371) | func (r *queue) dequeue() interface{} {
    method length (line 379) | func (r *queue) length() int {
  function newQueue (line 363) | func newQueue() *queue {
  type Path (line 383) | type Path struct
  function reverse (line 448) | func reverse(data []Path) []Path {

FILE: graph/graph_test.go
  type node (line 29) | type node struct
    method ID (line 33) | func (r node) ID() string {
  type point (line 37) | type point struct
    method ID (line 42) | func (r point) ID() string {
    method Vertex (line 46) | func (r point) Vertex() Vertex {
  type link (line 50) | type link struct
    method ID (line 55) | func (r link) ID() string {
    method Points (line 59) | func (r link) Points() [2]Point {
    method Weight (line 63) | func (r link) Weight() float64 {
  function printEnabledEdges (line 67) | func printEnabledEdges(g *Graph) (int, float64) {
  function TestInvalidMST (line 82) | func TestInvalidMST(t *testing.T) {
  function TestRemoveVertex (line 100) | func TestRemoveVertex(t *testing.T) {
  function TestRemoveEdges (line 127) | func TestRemoveEdges(t *testing.T) {
  function TestDuplicatedEdges (line 172) | func TestDuplicatedEdges(t *testing.T) {
  function TestMST0 (line 194) | func TestMST0(t *testing.T) {
  function TestMST1 (line 256) | func TestMST1(t *testing.T) {
  function TestMST2 (line 306) | func TestMST2(t *testing.T) {
  function TestMST3 (line 391) | func TestMST3(t *testing.T) {
  function TestMST4 (line 486) | func TestMST4(t *testing.T) {

FILE: ldap/client.go
  type Client (line 37) | type Client struct
    method Auth (line 58) | func (r *Client) Auth(username, password string) (ok bool, err error) {
    method bindAdmin (line 91) | func (r *Client) bindAdmin(conn *ldap.Conn) error {
    method getDN (line 96) | func (r *Client) getDN(conn *ldap.Conn, username string) (dn string, e...
  function New (line 46) | func New(config *viper.Viper, maxConn int) *Client {

FILE: ldap/conn.go
  method acquireConn (line 34) | func (r *Client) acquireConn() (conn *ldap.Conn, err error) {
  method createConn (line 45) | func (r *Client) createConn() (*ldap.Conn, error) {
  method releaseConn (line 61) | func (r *Client) releaseConn(conn *ldap.Conn) {

FILE: log/syslog.go
  type syslog (line 33) | type syslog struct
    method Log (line 46) | func (r *syslog) Log(level logging.Level, calldepth int, record *loggi...
  function NewSyslog (line 37) | func NewSyslog(prefix string) (logging.Backend, error) {
  function getGoRoutineID (line 66) | func getGoRoutineID() string {

FILE: network/controller.go
  type database (line 38) | type database interface
  type LocationStatus (line 42) | type LocationStatus
  constant LocationUnregistered (line 46) | LocationUnregistered LocationStatus = iota
  constant LocationUndiscovered (line 48) | LocationUndiscovered
  constant LocationDiscovered (line 50) | LocationDiscovered
  type EventListener (line 53) | type EventListener interface
  type ControllerEventListener (line 58) | type ControllerEventListener interface
  type TopologyEventListener (line 67) | type TopologyEventListener interface
  type Controller (line 71) | type Controller struct
    method AddConnection (line 82) | func (r *Controller) AddConnection(ctx context.Context, c net.Conn) {
    method SetEventListener (line 93) | func (r *Controller) SetEventListener(l EventListener) {
    method String (line 98) | func (r *Controller) String() string {
    method Announce (line 102) | func (r *Controller) Announce(ip net.IP, mac net.HardwareAddr) error {
    method RemoveFlows (line 114) | func (r *Controller) RemoveFlows() error {
    method RemoveFlowsByMAC (line 126) | func (r *Controller) RemoveFlowsByMAC(mac net.HardwareAddr) error {
  function NewController (line 76) | func NewController(db database) *Controller {

FILE: network/device.go
  type Descriptions (line 39) | type Descriptions struct
  type Features (line 47) | type Features struct
  type Device (line 53) | type Device struct
    method String (line 90) | func (r *Device) String() string {
    method ID (line 103) | func (r *Device) ID() string {
    method setID (line 111) | func (r *Device) setID(id string) {
    method isReady (line 119) | func (r *Device) isReady() bool {
    method Factory (line 127) | func (r *Device) Factory() openflow.Factory {
    method setFactory (line 135) | func (r *Device) setFactory(f openflow.Factory) {
    method Writer (line 146) | func (r *Device) Writer() transceiver.Writer {
    method Descriptions (line 154) | func (r *Device) Descriptions() Descriptions {
    method setDescriptions (line 162) | func (r *Device) setDescriptions(d Descriptions) {
    method Features (line 170) | func (r *Device) Features() Features {
    method setFeatures (line 178) | func (r *Device) setFeatures(f Features) {
    method Port (line 187) | func (r *Device) Port(num uint32) *Port {
    method Ports (line 195) | func (r *Device) Ports() []*Port {
    method setPort (line 208) | func (r *Device) setPort(num uint32, p openflow.Port) {
    method FlowTableID (line 228) | func (r *Device) FlowTableID() uint8 {
    method setFlowTableID (line 236) | func (r *Device) setFlowTableID(id uint8) {
    method SendMessage (line 244) | func (r *Device) SendMessage(msg encoding.BinaryMarshaler) error {
    method IsClosed (line 259) | func (r *Device) IsClosed() bool {
    method SetFlow (line 268) | func (r *Device) SetFlow(match openflow.Match, port openflow.OutPort) ...
    method RemoveFlows (line 335) | func (r *Device) RemoveFlows() error {
    method RemoveFlow (line 375) | func (r *Device) RemoveFlow(match openflow.Match, port openflow.OutPor...
    method RemoveFlowByMAC (line 403) | func (r *Device) RemoveFlowByMAC(mac net.HardwareAddr) error {
    method SendARPAnnouncement (line 439) | func (r *Device) SendARPAnnouncement(ip net.IP, mac net.HardwareAddr) ...
    method SendARPDiscovery (line 456) | func (r *Device) SendARPDiscovery(sha net.HardwareAddr, spa, tpa net.I...
    method Flood (line 490) | func (r *Device) Flood(ingress *Port, packet []byte) error {
    method flood (line 503) | func (r *Device) flood(ingress *Port, packet []byte) error {
    method Close (line 532) | func (r *Device) Close() {
  function newDevice (line 71) | func newDevice(s *session) *Device {
  function newARPRequestFrame (line 473) | func newARPRequestFrame(sha net.HardwareAddr, spa, tpa net.IP) ([]byte, ...

FILE: network/error.go
  type networkErr (line 24) | type networkErr struct
    method Error (line 29) | func (r *networkErr) Error() string {
    method Temporary (line 33) | func (r *networkErr) Temporary() bool {

FILE: network/flow_cache.go
  type flowCache (line 33) | type flowCache struct
    method Add (line 50) | func (r *flowCache) Add(match openflow.Match, port openflow.OutPort) e...
    method key (line 64) | func (r *flowCache) key(match openflow.Match, port openflow.OutPort) (...
    method InProgress (line 73) | func (r *flowCache) InProgress(match openflow.Match, port openflow.Out...
    method RemoveAll (line 95) | func (r *flowCache) RemoveAll() {
  function newFlowCache (line 38) | func newFlowCache(expiration time.Duration) *flowCache {

FILE: network/link.go
  type link (line 31) | type link struct
    method ID (line 41) | func (r *link) ID() string {
    method Points (line 48) | func (r *link) Points() [2]graph.Point {
    method Weight (line 52) | func (r *link) Weight() float64 {
  function newLink (line 35) | func newLink(ports [2]*Port) *link {

FILE: network/node.go
  type Node (line 29) | type Node struct
    method String (line 41) | func (r *Node) String() string {
    method Port (line 45) | func (r *Node) Port() *Port {
    method MAC (line 49) | func (r *Node) MAC() net.HardwareAddr {
  function NewNode (line 34) | func NewNode(p *Port, mac net.HardwareAddr) *Node {

FILE: network/of10_session.go
  type of10Session (line 32) | type of10Session struct
    method OnHello (line 46) | func (r *of10Session) OnHello(f openflow.Factory, w transceiver.Writer...
    method OnBarrierReply (line 75) | func (r *of10Session) OnBarrierReply(f openflow.Factory, w transceiver...
    method OnError (line 93) | func (r *of10Session) OnError(f openflow.Factory, w transceiver.Writer...
    method OnFeaturesReply (line 97) | func (r *of10Session) OnFeaturesReply(f openflow.Factory, w transceive...
    method OnGetConfigReply (line 122) | func (r *of10Session) OnGetConfigReply(f openflow.Factory, w transceiv...
    method OnDescReply (line 126) | func (r *of10Session) OnDescReply(f openflow.Factory, w transceiver.Wr...
    method OnPortDescReply (line 130) | func (r *of10Session) OnPortDescReply(f openflow.Factory, w transceive...
    method OnPortStatus (line 135) | func (r *of10Session) OnPortStatus(f openflow.Factory, w transceiver.W...
    method OnFlowRemoved (line 139) | func (r *of10Session) OnFlowRemoved(f openflow.Factory, w transceiver....
    method OnPacketIn (line 143) | func (r *of10Session) OnPacketIn(f openflow.Factory, w transceiver.Wri...
  function newOF10Session (line 40) | func newOF10Session(d *Device) *of10Session {

FILE: network/of13_session.go
  type of13Session (line 34) | type of13Session struct
    method OnHello (line 48) | func (r *of13Session) OnHello(f openflow.Factory, w transceiver.Writer...
    method OnBarrierReply (line 77) | func (r *of13Session) OnBarrierReply(f openflow.Factory, w transceiver...
    method OnError (line 92) | func (r *of13Session) OnError(f openflow.Factory, w transceiver.Writer...
    method OnFeaturesReply (line 96) | func (r *of13Session) OnFeaturesReply(f openflow.Factory, w transceive...
    method OnGetConfigReply (line 104) | func (r *of13Session) OnGetConfigReply(f openflow.Factory, w transceiv...
    method setTableMiss (line 116) | func (r *of13Session) setTableMiss(f openflow.Factory, w transceiver.W...
    method setHP2920TableMiss (line 140) | func (r *of13Session) setHP2920TableMiss(f openflow.Factory, w transce...
    method setAS4600TableMiss (line 177) | func (r *of13Session) setAS4600TableMiss(f openflow.Factory, w transce...
    method setDefaultTableMiss (line 186) | func (r *of13Session) setDefaultTableMiss(f openflow.Factory, w transc...
    method OnDescReply (line 210) | func (r *of13Session) OnDescReply(f openflow.Factory, w transceiver.Wr...
    method OnPortDescReply (line 235) | func (r *of13Session) OnPortDescReply(f openflow.Factory, w transceive...
    method OnPortStatus (line 260) | func (r *of13Session) OnPortStatus(f openflow.Factory, w transceiver.W...
    method OnFlowRemoved (line 264) | func (r *of13Session) OnFlowRemoved(f openflow.Factory, w transceiver....
    method OnPacketIn (line 268) | func (r *of13Session) OnPacketIn(f openflow.Factory, w transceiver.Wri...
  function newOF13Session (line 42) | func newOF13Session(d *Device) *of13Session {
  function isHP2920_24G (line 108) | func isHP2920_24G(msg openflow.DescReply) bool {
  function isAS460054_T (line 112) | func isAS460054_T(msg openflow.DescReply) bool {

FILE: network/port.go
  type Port (line 33) | type Port struct
    method String (line 47) | func (r *Port) String() string {
    method ID (line 55) | func (r *Port) ID() string {
    method Vertex (line 59) | func (r *Port) Vertex() graph.Vertex {
    method Device (line 63) | func (r *Port) Device() *Device {
    method Number (line 67) | func (r *Port) Number() uint32 {
    method Value (line 71) | func (r *Port) Value() openflow.Port {
    method SetValue (line 79) | func (r *Port) SetValue(p openflow.Port) {
  function NewPort (line 40) | func NewPort(d *Device, num uint32) *Port {

FILE: network/reserve.go
  function ReservedIP (line 31) | func ReservedIP(n net.IPNet) (net.IP, error) {

FILE: network/reserve_test.go
  function TestReservedIP (line 29) | func TestReservedIP(t *testing.T) {

FILE: network/session.go
  constant deviceExplorerInterval (line 46) | deviceExplorerInterval = 1 * time.Minute
  type session (line 49) | type session struct
    method OnHello (line 95) | func (r *session) OnHello(f openflow.Factory, w transceiver.Writer, v ...
    method OnError (line 117) | func (r *session) OnError(f openflow.Factory, w transceiver.Writer, v ...
    method OnFeaturesReply (line 133) | func (r *session) OnFeaturesReply(f openflow.Factory, w transceiver.Wr...
    method OnGetConfigReply (line 174) | func (r *session) OnGetConfigReply(f openflow.Factory, w transceiver.W...
    method OnDescReply (line 184) | func (r *session) OnDescReply(f openflow.Factory, w transceiver.Writer...
    method OnPortDescReply (line 205) | func (r *session) OnPortDescReply(f openflow.Factory, w transceiver.Wr...
    method sendPortEvent (line 276) | func (r *session) sendPortEvent(portNum uint32, up bool) {
    method updatePort (line 295) | func (r *session) updatePort(v openflow.PortStatus) {
    method OnPortStatus (line 313) | func (r *session) OnPortStatus(f openflow.Factory, w transceiver.Write...
    method OnFlowRemoved (line 345) | func (r *session) OnFlowRemoved(f openflow.Factory, w transceiver.Writ...
    method findNeighborPort (line 414) | func (r *session) findNeighborPort(deviceID string, portNum uint32) (*...
    method handleLLDP (line 427) | func (r *session) handleLLDP(inPort *Port, ethernet *protocol.Ethernet...
    method OnPacketIn (line 449) | func (r *session) OnPacketIn(f openflow.Factory, w transceiver.Writer,...
    method OnBarrierReply (line 492) | func (r *session) OnBarrierReply(f openflow.Factory, w transceiver.Wri...
    method Run (line 501) | func (r *session) Run(ctx context.Context) {
    method runDeviceExplorer (line 521) | func (r *session) runDeviceExplorer(ctx context.Context) context.Cance...
    method Write (line 568) | func (r *session) Write(msg encoding.BinaryMarshaler) error {
  type sessionConfig (line 59) | type sessionConfig struct
  function checkParam (line 66) | func checkParam(c sessionConfig) {
  function newSession (line 81) | func newSession(c sessionConfig) *session {
  function newLLDPEtherFrame (line 215) | func newLLDPEtherFrame(deviceID string, port openflow.Port) ([]byte, err...
  function sendLLDP (line 248) | func sendLLDP(device *Device, p openflow.Port) error {
  function getEthernet (line 360) | func getEthernet(packet []byte) (*protocol.Ethernet, error) {
  function isLLDP (line 369) | func isLLDP(e *protocol.Ethernet) bool {
  function getLLDP (line 373) | func getLLDP(packet []byte) (*protocol.LLDP, error) {
  function isCherryLLDP (line 382) | func isCherryLLDP(p *protocol.LLDP) bool {
  function extractDeviceInfo (line 399) | func extractDeviceInfo(p *protocol.LLDP) (deviceID string, portNum uint3...
  function sendHello (line 572) | func sendHello(f openflow.Factory, w transceiver.Writer) error {
  function sendSetConfig (line 581) | func sendSetConfig(f openflow.Factory, w transceiver.Writer) error {
  function sendFeaturesRequest (line 592) | func sendFeaturesRequest(f openflow.Factory, w transceiver.Writer) error {
  function sendDescriptionRequest (line 601) | func sendDescriptionRequest(f openflow.Factory, w transceiver.Writer) er...
  function sendBarrierRequest (line 610) | func sendBarrierRequest(f openflow.Factory, w transceiver.Writer) error {
  function sendPortDescriptionRequest (line 619) | func sendPortDescriptionRequest(f openflow.Factory, w transceiver.Writer...
  function setARPSender (line 629) | func setARPSender(f openflow.Factory, w transceiver.Writer) error {
  function setLLDPSender (line 641) | func setLLDPSender(f openflow.Factory, w transceiver.Writer) error {
  function setTemporaryDrop (line 653) | func setTemporaryDrop(f openflow.Factory, w transceiver.Writer) error {
  function setDHCPSender (line 664) | func setDHCPSender(f openflow.Factory, w transceiver.Writer) error {
  function setSpecialFlow (line 678) | func setSpecialFlow(f openflow.Factory, w transceiver.Writer, match open...
  function sendRemoveAllFlows (line 711) | func sendRemoveAllFlows(f openflow.Factory, w transceiver.Writer) error {

FILE: network/topology.go
  type watcher (line 36) | type watcher interface
  type Finder (line 43) | type Finder interface
  type topology (line 54) | type topology struct
    method String (line 74) | func (r *topology) String() string {
    method setEventListener (line 85) | func (r *topology) setEventListener(l TopologyEventListener) {
    method sendEvent (line 91) | func (r *topology) sendEvent() {
    method Devices (line 102) | func (r *topology) Devices() []*Device {
    method Device (line 116) | func (r *topology) Device(id string) *Device {
    method DeviceAdded (line 124) | func (r *topology) DeviceAdded(d *Device) {
    method removeDevice (line 139) | func (r *topology) removeDevice(d *Device) {
    method DeviceRemoved (line 144) | func (r *topology) DeviceRemoved(d *Device) {
    method DeviceLinked (line 158) | func (r *topology) DeviceLinked(ports [2]*Port) {
    method Node (line 185) | func (r *topology) Node(mac net.HardwareAddr) (*Node, LocationStatus, ...
    method PortRemoved (line 210) | func (r *topology) PortRemoved(p *Port) {
    method Path (line 231) | func (r *topology) Path(srcDeviceID, dstDeviceID string) [][2]*Port {
    method IsEdge (line 264) | func (r *topology) IsEdge(p *Port) bool {
    method IsEnabledBySTP (line 268) | func (r *topology) IsEnabledBySTP(p *Port) bool {
    method staleEdgeRemover (line 273) | func (r *topology) staleEdgeRemover() {
  function newTopology (line 63) | func newTopology(db database) *topology {
  function pickPort (line 255) | func pickPort(d *Device, l *link) [2]*Port {

FILE: northbound/app/announcer/announcer.go
  type Announcer (line 46) | type Announcer struct
    method Init (line 68) | func (r *Announcer) Init() error {
    method Name (line 72) | func (r *Announcer) Name() string {
    method String (line 76) | func (r *Announcer) String() string {
    method OnDeviceUp (line 80) | func (r *Announcer) OnDeviceUp(finder network.Finder, device *network....
    method broadcaster (line 90) | func (r *Announcer) broadcaster(finder network.Finder) {
  type database (line 52) | type database interface
  type ARPTableEntry (line 57) | type ARPTableEntry struct
  function New (line 62) | func New(db database) *Announcer {

FILE: northbound/app/announcer/backoff.go
  type backoff (line 36) | type backoff struct
    method Broadcast (line 58) | func (r *backoff) Broadcast(ip net.IP, mac net.HardwareAddr) error {
    method getAnnouncer (line 65) | func (r *backoff) getAnnouncer(ip net.IP, mac net.HardwareAddr) *annou...
  function newBackoff (line 43) | func newBackoff(finder network.Finder) *backoff {
  type announcer (line 83) | type announcer struct
    method Broadcast (line 91) | func (r *announcer) Broadcast() error {
    method calculateDelay (line 117) | func (r *announcer) calculateDelay() time.Duration {
  constant maxDelay (line 115) | maxDelay = 1 * time.Hour

FILE: northbound/app/dhcp/dhcp.go
  type DHCP (line 47) | type DHCP struct
    method Init (line 69) | func (r *DHCP) Init() error {
    method Name (line 73) | func (r *DHCP) Name() string {
    method String (line 77) | func (r *DHCP) String() string {
    method OnPacketIn (line 81) | func (r *DHCP) OnPacketIn(finder network.Finder, ingress *network.Port...
    method processDHCPPacket (line 120) | func (r *DHCP) processDHCPPacket(ingress *network.Port, dhcp *protocol...
    method processDHCPDiscover (line 168) | func (r *DHCP) processDHCPDiscover(ingress *network.Port, disc *protoc...
    method processDHCPRequest (line 201) | func (r *DHCP) processDHCPRequest(ingress *network.Port, req *protocol...
  type Database (line 52) | type Database interface
  type NetConfig (line 57) | type NetConfig struct
  function New (line 63) | func New(db Database) *DHCP {
  function buildReply (line 242) | func buildReply(dstMAC net.HardwareAddr, dstIP net.IP, dhcp *protocol.DH...
  function sendReply (line 276) | func sendReply(ingress *network.Port, packet []byte) error {

FILE: northbound/app/discovery/discovery.go
  constant ProbeInterval (line 48) | ProbeInterval = 30 * time.Second
  type processor (line 51) | type processor struct
    method Name (line 85) | func (r *processor) Name() string {
    method String (line 89) | func (r *processor) String() string {
    method OnDeviceUp (line 93) | func (r *processor) OnDeviceUp(finder network.Finder, device *network....
    method runARPSender (line 102) | func (r *processor) runARPSender(device *network.Device) {
    method sendARPDiscovery (line 129) | func (r *processor) sendARPDiscovery(device *network.Device) error {
    method stopARPSender (line 155) | func (r *processor) stopARPSender(deviceID string) {
    method OnPacketIn (line 167) | func (r *processor) OnPacketIn(finder network.Finder, ingress *network...
    method processARPRequest (line 191) | func (r *processor) processARPRequest(finder network.Finder, ingress *...
    method processARPReply (line 203) | func (r *processor) processARPReply(finder network.Finder, ingress *ne...
    method macLearning (line 221) | func (r *processor) macLearning(finder network.Finder, ingress *networ...
    method OnPortDown (line 250) | func (r *processor) OnPortDown(finder network.Finder, port *network.Po...
    method OnDeviceDown (line 266) | func (r *processor) OnDeviceDown(finder network.Finder, device *networ...
    method OnTopologyChange (line 285) | func (r *processor) OnTopologyChange(finder network.Finder) error {
  type Database (line 59) | type Database interface
  function New (line 78) | func New(db Database) app.Processor {

FILE: northbound/app/l2switch/storm_controller.go
  type stormController (line 33) | type stormController struct
    method broadcast (line 60) | func (r *stormController) broadcast(ingress *network.Port, packet []by...
  type broadcaster (line 40) | type broadcaster interface
  function newStormController (line 45) | func newStormController(max uint, bcaster broadcaster) *stormController {

FILE: northbound/app/l2switch/storm_controller_test.go
  function TestStorm (line 32) | func TestStorm(t *testing.T) {
  function TestPeriodicBroadcast (line 60) | func TestPeriodicBroadcast(t *testing.T) {
  function TestPeriodicStorm (line 74) | func TestPeriodicStorm(t *testing.T) {
  type dummyFlooder (line 92) | type dummyFlooder struct
    method flood (line 96) | func (r *dummyFlooder) flood(ingress *network.Port, packet []byte) err...
    method getCounter (line 101) | func (r *dummyFlooder) getCounter() uint64 {

FILE: northbound/app/l2switch/switch.go
  type L2Switch (line 45) | type L2Switch struct
    method Init (line 71) | func (r *L2Switch) Init() error {
    method Name (line 75) | func (r *L2Switch) Name() string {
    method setFlow (line 93) | func (r *L2Switch) setFlow(p flowParam) error {
    method switching (line 120) | func (r *L2Switch) switching(p switchParam) error {
    method OnPacketIn (line 135) | func (r *L2Switch) OnPacketIn(finder network.Finder, ingress *network....
    method processPacket (line 144) | func (r *L2Switch) processPacket(finder network.Finder, ingress *netwo...
    method OnTopologyChange (line 220) | func (r *L2Switch) OnTopologyChange(finder network.Finder) error {
    method removeAllFlows (line 232) | func (r *L2Switch) removeAllFlows(devices []*network.Device) error {
    method String (line 248) | func (r *L2Switch) String() string {
    method OnPortDown (line 252) | func (r *L2Switch) OnPortDown(finder network.Finder, port *network.Por...
    method OnDeviceUp (line 273) | func (r *L2Switch) OnDeviceUp(finder network.Finder, device *network.D...
    method flowManager (line 283) | func (r *L2Switch) flowManager(finder network.Finder) {
    method modifyFlows (line 304) | func (r *L2Switch) modifyFlows(finder network.Finder, mac net.Hardware...
  type Database (line 52) | type Database interface
  function New (line 57) | func New(db Database) *L2Switch {
  type flooder (line 64) | type flooder struct
    method flood (line 67) | func (r *flooder) flood(ingress *network.Port, packet []byte) error {
  function isBroadcast (line 79) | func isBroadcast(eth *protocol.Ethernet) bool {
  type flowParam (line 83) | type flowParam struct
    method String (line 89) | func (r flowParam) String() string {
  type switchParam (line 112) | type switchParam struct

FILE: northbound/app/monitor/monitor.go
  type Monitor (line 40) | type Monitor struct
    method Init (line 49) | func (r *Monitor) Init() error {
    method Name (line 59) | func (r *Monitor) Name() string {
    method String (line 63) | func (r *Monitor) String() string {
    method OnDeviceUp (line 67) | func (r *Monitor) OnDeviceUp(finder network.Finder, device *network.De...
    method OnDeviceDown (line 80) | func (r *Monitor) OnDeviceDown(finder network.Finder, device *network....
    method sendAlarm (line 93) | func (r *Monitor) sendAlarm(subject, body string) error {
  function New (line 45) | func New() *Monitor {

FILE: northbound/app/monitor/sendmail.go
  function sendmail (line 14) | func sendmail(from string, to []string, msg []byte) error {
  function lookupMX (line 33) | func lookupMX(email string) ([]*net.MX, error) {

FILE: northbound/app/processor.go
  type Processor (line 33) | type Processor interface
  type BaseProcessor (line 44) | type BaseProcessor struct
    method Init (line 48) | func (r *BaseProcessor) Init() error {
    method Name (line 52) | func (r *BaseProcessor) Name() string {
    method Dependencies (line 56) | func (r *BaseProcessor) Dependencies() []string {
    method OnPacketIn (line 60) | func (r *BaseProcessor) OnPacketIn(finder network.Finder, ingress *net...
    method OnDeviceUp (line 69) | func (r *BaseProcessor) OnDeviceUp(finder network.Finder, device *netw...
    method OnDeviceDown (line 78) | func (r *BaseProcessor) OnDeviceDown(finder network.Finder, device *ne...
    method OnPortUp (line 87) | func (r *BaseProcessor) OnPortUp(finder network.Finder, port *network....
    method OnPortDown (line 96) | func (r *BaseProcessor) OnPortDown(finder network.Finder, port *networ...
    method OnTopologyChange (line 105) | func (r *BaseProcessor) OnTopologyChange(finder network.Finder) error {
    method OnFlowRemoved (line 114) | func (r *BaseProcessor) OnFlowRemoved(finder network.Finder, flow open...
    method Next (line 123) | func (r *BaseProcessor) Next() (next Processor, ok bool) {
    method SetNext (line 131) | func (r *BaseProcessor) SetNext(next Processor) {
    method PacketOut (line 135) | func (r *BaseProcessor) PacketOut(egress *network.Port, packet []byte)...

FILE: northbound/app/proxyarp/arp.go
  type ProxyARP (line 42) | type ProxyARP struct
    method Init (line 62) | func (r *ProxyARP) Init() error {
    method Name (line 66) | func (r *ProxyARP) Name() string {
    method OnPacketIn (line 70) | func (r *ProxyARP) OnPacketIn(finder network.Finder, ingress *network....
    method String (line 170) | func (r *ProxyARP) String() string {
  type database (line 47) | type database interface
  type Host (line 51) | type Host struct
  function New (line 56) | func New(db database) *ProxyARP {
  function sendARPReply (line 116) | func sendARPReply(ingress *network.Port, packet []byte) error {
  function isARPAnnouncement (line 142) | func isARPAnnouncement(request *protocol.ARP) bool {
  function makeARPReply (line 154) | func makeARPReply(request *protocol.ARP, mac net.HardwareAddr) ([]byte, ...

FILE: northbound/app/proxyarp/error.go
  type proxyarpErr (line 24) | type proxyarpErr struct
    method Error (line 29) | func (r *proxyarpErr) Error() string {
    method Temporary (line 33) | func (r *proxyarpErr) Temporary() bool {

FILE: northbound/app/virtualip/virtualip.go
  type VirtualIP (line 40) | type VirtualIP struct
    method Init (line 61) | func (r *VirtualIP) Init() error {
    method Name (line 65) | func (r *VirtualIP) Name() string {
    method String (line 69) | func (r *VirtualIP) String() string {
    method OnPortDown (line 73) | func (r *VirtualIP) OnPortDown(finder network.Finder, port *network.Po...
    method OnDeviceDown (line 91) | func (r *VirtualIP) OnDeviceDown(finder network.Finder, device *networ...
  type database (line 45) | type database interface
  type Address (line 50) | type Address struct
  function New (line 55) | func New(db database) *VirtualIP {
  function broadcastARPAnnouncement (line 109) | func broadcastARPAnnouncement(finder network.Finder, vips []Address) {

FILE: northbound/manager.go
  type EventSender (line 49) | type EventSender interface
  type application (line 53) | type application struct
  type Manager (line 58) | type Manager struct
    method register (line 82) | func (r *Manager) register(app app.Processor) {
    method checkDependencies (line 90) | func (r *Manager) checkDependencies(appNames []string) error {
    method Enable (line 107) | func (r *Manager) Enable(appName string) error {
    method AddEventSender (line 142) | func (r *Manager) AddEventSender(sender EventSender) {
    method String (line 152) | func (r *Manager) String() string {
  function NewManager (line 65) | func NewManager(db *database.MySQL) (*Manager, error) {

FILE: openflow/action.go
  type Action (line 31) | type Action interface
  type BaseAction (line 48) | type BaseAction struct
    method VLANID (line 64) | func (r *BaseAction) VLANID() (ok bool, vid uint16) {
    method SetVLANID (line 72) | func (r *BaseAction) SetVLANID(vid uint16) {
    method Queue (line 76) | func (r *BaseAction) Queue() (ok bool, queue uint32) {
    method SetQueue (line 84) | func (r *BaseAction) SetQueue(queue uint32) {
    method SetOutPort (line 88) | func (r *BaseAction) SetOutPort(port OutPort) {
    method OutPort (line 92) | func (r *BaseAction) OutPort() OutPort {
    method SetSrcMAC (line 96) | func (r *BaseAction) SetSrcMAC(mac net.HardwareAddr) {
    method SrcMAC (line 105) | func (r *BaseAction) SrcMAC() (ok bool, mac net.HardwareAddr) {
    method SetDstMAC (line 113) | func (r *BaseAction) SetDstMAC(mac net.HardwareAddr) {
    method DstMAC (line 122) | func (r *BaseAction) DstMAC() (ok bool, mac net.HardwareAddr) {
    method Error (line 130) | func (r *BaseAction) Error() error {
  function NewBaseAction (line 57) | func NewBaseAction() *BaseAction {

FILE: openflow/barrier.go
  type BarrierRequest (line 28) | type BarrierRequest interface
  type BarrierReply (line 33) | type BarrierReply interface

FILE: openflow/config.go
  type ConfigFlag (line 28) | type ConfigFlag
  constant FragNormal (line 31) | FragNormal ConfigFlag = iota
  constant FragDrop (line 32) | FragDrop
  constant FragReasm (line 33) | FragReasm
  constant FragMask (line 34) | FragMask
  type Config (line 37) | type Config interface
  type SetConfig (line 46) | type SetConfig interface
  type GetConfigRequest (line 52) | type GetConfigRequest interface
  type GetConfigReply (line 57) | type GetConfigReply interface

FILE: openflow/const.go
  constant OF10_VERSION (line 25) | OF10_VERSION = 0x01
  constant OF13_VERSION (line 26) | OF13_VERSION = 0x04

FILE: openflow/description.go
  type DescRequest (line 29) | type DescRequest interface
  type DescReply (line 35) | type DescReply interface

FILE: openflow/echo.go
  type Echo (line 28) | type Echo interface
  type EchoRequest (line 38) | type EchoRequest interface
  type EchoReply (line 42) | type EchoReply interface
  type BaseEcho (line 46) | type BaseEcho struct
    method Data (line 52) | func (r *BaseEcho) Data() []byte {
    method SetData (line 56) | func (r *BaseEcho) SetData(data []byte) {
    method Error (line 63) | func (r *BaseEcho) Error() error {
    method MarshalBinary (line 67) | func (r *BaseEcho) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 76) | func (r *BaseEcho) UnmarshalBinary(data []byte) error {

FILE: openflow/error.go
  type Error (line 29) | type Error interface
  type BaseError (line 37) | type BaseError struct
    method Class (line 44) | func (r *BaseError) Class() uint16 {
    method Code (line 48) | func (r *BaseError) Code() uint16 {
    method Data (line 52) | func (r *BaseError) Data() []byte {
    method UnmarshalBinary (line 56) | func (r *BaseError) UnmarshalBinary(data []byte) error {

FILE: openflow/factory.go
  type Factory (line 43) | type Factory interface

FILE: openflow/features.go
  type FeaturesRequest (line 28) | type FeaturesRequest interface
  type FeaturesReply (line 33) | type FeaturesReply interface

FILE: openflow/flow_mod.go
  type FlowModCmd (line 28) | type FlowModCmd
  constant FlowAdd (line 31) | FlowAdd FlowModCmd = iota
  constant FlowModify (line 32) | FlowModify
  constant FlowDelete (line 33) | FlowDelete
  type FlowMod (line 36) | type FlowMod interface

FILE: openflow/flow_removed.go
  type FlowRemoved (line 28) | type FlowRemoved interface

FILE: openflow/flow_stats.go
  type FlowStatsRequest (line 28) | type FlowStatsRequest interface

FILE: openflow/hello.go
  type Hello (line 28) | type Hello interface
  type BaseHello (line 34) | type BaseHello struct
    method MarshalBinary (line 38) | func (r *BaseHello) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 42) | func (r *BaseHello) UnmarshalBinary(data []byte) error {

FILE: openflow/instruction.go
  type Instruction (line 28) | type Instruction interface

FILE: openflow/match.go
  type Match (line 29) | type Match interface

FILE: openflow/message.go
  type Header (line 28) | type Header interface
  type Message (line 35) | type Message struct
    method Version (line 52) | func (r *Message) Version() uint8 {
    method Type (line 56) | func (r *Message) Type() uint8 {
    method TransactionID (line 60) | func (r *Message) TransactionID() uint32 {
    method SetTransactionID (line 64) | func (r *Message) SetTransactionID(xid uint32) {
    method Payload (line 68) | func (r *Message) Payload() []byte {
    method SetPayload (line 72) | func (r *Message) SetPayload(payload []byte) {
    method MarshalBinary (line 81) | func (r *Message) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 99) | func (r *Message) UnmarshalBinary(data []byte) error {
  function NewMessage (line 43) | func NewMessage(version uint8, msgType uint8, xid uint32) Message {

FILE: openflow/of10/action.go
  type Action (line 31) | type Action struct
    method MarshalBinary (line 120) | func (r *Action) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 168) | func (r *Action) UnmarshalBinary(data []byte) error {
  function NewAction (line 35) | func NewAction() openflow.Action {
  function marshalOutPort (line 41) | func marshalOutPort(p openflow.OutPort) ([]byte, error) {
  function marshalQueue (line 70) | func marshalQueue(p openflow.OutPort, queue uint32) ([]byte, error) {
  function marshalMAC (line 97) | func marshalMAC(t uint16, mac net.HardwareAddr) ([]byte, error) {
  function marshalVLANID (line 110) | func marshalVLANID(vid uint16) ([]byte, error) {

FILE: openflow/of10/barrier.go
  type BarrierRequest (line 28) | type BarrierRequest struct
    method MarshalBinary (line 38) | func (r *BarrierRequest) MarshalBinary() ([]byte, error) {
  function NewBarrierRequest (line 32) | func NewBarrierRequest(xid uint32) openflow.BarrierRequest {
  type BarrierReply (line 42) | type BarrierReply struct
    method UnmarshalBinary (line 46) | func (r *BarrierReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/config.go
  type Config (line 31) | type Config struct
    method Flags (line 37) | func (r *Config) Flags() openflow.ConfigFlag {
    method SetFlags (line 52) | func (r *Config) SetFlags(flags openflow.ConfigFlag) {
    method MissSendLength (line 67) | func (r *Config) MissSendLength() uint16 {
    method SetMissSendLength (line 71) | func (r *Config) SetMissSendLength(length uint16) {
    method Error (line 75) | func (r *Config) Error() error {
  type SetConfig (line 79) | type SetConfig struct
    method MarshalBinary (line 94) | func (r *SetConfig) MarshalBinary() ([]byte, error) {
  function NewSetConfig (line 84) | func NewSetConfig(xid uint32) openflow.SetConfig {
  type GetConfigRequest (line 107) | type GetConfigRequest struct
    method MarshalBinary (line 117) | func (r *GetConfigRequest) MarshalBinary() ([]byte, error) {
  function NewGetConfigRequest (line 111) | func NewGetConfigRequest(xid uint32) openflow.GetConfigRequest {
  type GetConfigReply (line 121) | type GetConfigReply struct
    method UnmarshalBinary (line 126) | func (r *GetConfigReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/const.go
  constant OFPT_HELLO (line 25) | OFPT_HELLO = iota
  constant OFPT_ERROR (line 26) | OFPT_ERROR
  constant OFPT_ECHO_REQUEST (line 27) | OFPT_ECHO_REQUEST
  constant OFPT_ECHO_REPLY (line 28) | OFPT_ECHO_REPLY
  constant OFPT_VENDOR (line 29) | OFPT_VENDOR
  constant OFPT_FEATURES_REQUEST (line 30) | OFPT_FEATURES_REQUEST
  constant OFPT_FEATURES_REPLY (line 31) | OFPT_FEATURES_REPLY
  constant OFPT_GET_CONFIG_REQUEST (line 32) | OFPT_GET_CONFIG_REQUEST
  constant OFPT_GET_CONFIG_REPLY (line 33) | OFPT_GET_CONFIG_REPLY
  constant OFPT_SET_CONFIG (line 34) | OFPT_SET_CONFIG
  constant OFPT_PACKET_IN (line 35) | OFPT_PACKET_IN
  constant OFPT_FLOW_REMOVED (line 36) | OFPT_FLOW_REMOVED
  constant OFPT_PORT_STATUS (line 37) | OFPT_PORT_STATUS
  constant OFPT_PACKET_OUT (line 38) | OFPT_PACKET_OUT
  constant OFPT_FLOW_MOD (line 39) | OFPT_FLOW_MOD
  constant OFPT_PORT_MOD (line 40) | OFPT_PORT_MOD
  constant OFPT_STATS_REQUEST (line 41) | OFPT_STATS_REQUEST
  constant OFPT_STATS_REPLY (line 42) | OFPT_STATS_REPLY
  constant OFPT_BARRIER_REQUEST (line 43) | OFPT_BARRIER_REQUEST
  constant OFPT_BARRIER_REPLY (line 44) | OFPT_BARRIER_REPLY
  constant OFPT_QUEUE_GET_CONFIG_REQUEST (line 45) | OFPT_QUEUE_GET_CONFIG_REQUEST
  constant OFPT_QUEUE_GET_CONFIG_REPLY (line 46) | OFPT_QUEUE_GET_CONFIG_REPLY
  constant OFPAT_OUTPUT (line 50) | OFPAT_OUTPUT       = iota
  constant OFPAT_SET_VLAN_VID (line 51) | OFPAT_SET_VLAN_VID
  constant OFPAT_SET_VLAN_PCP (line 52) | OFPAT_SET_VLAN_PCP
  constant OFPAT_STRIP_VLAN (line 53) | OFPAT_STRIP_VLAN
  constant OFPAT_SET_DL_SRC (line 54) | OFPAT_SET_DL_SRC
  constant OFPAT_SET_DL_DST (line 55) | OFPAT_SET_DL_DST
  constant OFPAT_SET_NW_SRC (line 56) | OFPAT_SET_NW_SRC
  constant OFPAT_SET_NW_DST (line 57) | OFPAT_SET_NW_DST
  constant OFPAT_SET_NW_TOS (line 58) | OFPAT_SET_NW_TOS
  constant OFPAT_SET_TP_SRC (line 59) | OFPAT_SET_TP_SRC
  constant OFPAT_SET_TP_DST (line 60) | OFPAT_SET_TP_DST
  constant OFPAT_ENQUEUE (line 61) | OFPAT_ENQUEUE
  constant OFPAT_VENDOR (line 62) | OFPAT_VENDOR       = 0xffff
  constant OFPP_MAX (line 66) | OFPP_MAX        = 0xff00
  constant OFPP_IN_PORT (line 67) | OFPP_IN_PORT    = 0xfff8
  constant OFPP_TABLE (line 68) | OFPP_TABLE      = 0xfff9
  constant OFPP_FLOOD (line 69) | OFPP_FLOOD      = 0xfffb
  constant OFPP_ALL (line 70) | OFPP_ALL        = 0xfffc
  constant OFPP_CONTROLLER (line 71) | OFPP_CONTROLLER = 0xfffd
  constant OFPP_NONE (line 72) | OFPP_NONE       = 0xffff
  constant OFPFW_IN_PORT (line 76) | OFPFW_IN_PORT     = 1 << 0
  constant OFPFW_DL_VLAN (line 77) | OFPFW_DL_VLAN     = 1 << 1
  constant OFPFW_DL_SRC (line 78) | OFPFW_DL_SRC      = 1 << 2
  constant OFPFW_DL_DST (line 79) | OFPFW_DL_DST      = 1 << 3
  constant OFPFW_DL_TYPE (line 80) | OFPFW_DL_TYPE     = 1 << 4
  constant OFPFW_NW_PROTO (line 81) | OFPFW_NW_PROTO    = 1 << 5
  constant OFPFW_TP_SRC (line 82) | OFPFW_TP_SRC      = 1 << 6
  constant OFPFW_TP_DST (line 83) | OFPFW_TP_DST      = 1 << 7
  constant OFPFW_DL_VLAN_PCP (line 84) | OFPFW_DL_VLAN_PCP = 1 << 20
  constant OFPFW_NW_TOS (line 85) | OFPFW_NW_TOS      = 1 << 21
  constant OFPPF_10MB_HD (line 89) | OFPPF_10MB_HD    = 1 << 0
  constant OFPPF_10MB_FD (line 90) | OFPPF_10MB_FD    = 1 << 1
  constant OFPPF_100MB_HD (line 91) | OFPPF_100MB_HD   = 1 << 2
  constant OFPPF_100MB_FD (line 92) | OFPPF_100MB_FD   = 1 << 3
  constant OFPPF_1GB_HD (line 93) | OFPPF_1GB_HD     = 1 << 4
  constant OFPPF_1GB_FD (line 94) | OFPPF_1GB_FD     = 1 << 5
  constant OFPPF_10GB_FD (line 95) | OFPPF_10GB_FD    = 1 << 6
  constant OFPPF_COPPER (line 96) | OFPPF_COPPER     = 1 << 7
  constant OFPPF_FIBER (line 97) | OFPPF_FIBER      = 1 << 8
  constant OFPPF_AUTONEG (line 98) | OFPPF_AUTONEG    = 1 << 9
  constant OFPPF_PAUSE (line 99) | OFPPF_PAUSE      = 1 << 10
  constant OFPPF_PAUSE_ASYM (line 100) | OFPPF_PAUSE_ASYM = 1 << 11
  constant OFPPC_PORT_DOWN (line 104) | OFPPC_PORT_DOWN    = 1 << 0
  constant OFPPC_NO_STP (line 105) | OFPPC_NO_STP       = 1 << 1
  constant OFPPC_NO_RECV (line 106) | OFPPC_NO_RECV      = 1 << 2
  constant OFPPC_NO_RECV_STP (line 107) | OFPPC_NO_RECV_STP  = 1 << 3
  constant OFPPC_NO_FLOOD (line 108) | OFPPC_NO_FLOOD     = 1 << 4
  constant OFPPC_NO_FWD (line 109) | OFPPC_NO_FWD       = 1 << 5
  constant OFPPC_NO_PACKET_IN (line 110) | OFPPC_NO_PACKET_IN = 1 << 6
  constant OFPPS_LINK_DOWN (line 114) | OFPPS_LINK_DOWN   = 1 << 0
  constant OFPPS_STP_LISTEN (line 115) | OFPPS_STP_LISTEN  = 0 << 8
  constant OFPPS_STP_LEARN (line 116) | OFPPS_STP_LEARN   = 1 << 8
  constant OFPPS_STP_FORWARD (line 117) | OFPPS_STP_FORWARD = 2 << 8
  constant OFPPS_STP_BLOCK (line 118) | OFPPS_STP_BLOCK   = 3 << 8
  constant OFPPS_STP_MASK (line 119) | OFPPS_STP_MASK    = 3 << 8
  constant OFPFF_SEND_FLOW_REM (line 123) | OFPFF_SEND_FLOW_REM = 1 << 0
  constant OFPFF_CHECK_OVERLAP (line 124) | OFPFF_CHECK_OVERLAP = 1 << 1
  constant OFPFF_EMERG (line 125) | OFPFF_EMERG         = 1 << 2
  constant OFP_NO_BUFFER (line 129) | OFP_NO_BUFFER = 0xffffffff
  constant OFPFC_ADD (line 133) | OFPFC_ADD           = 0
  constant OFPFC_MODIFY (line 134) | OFPFC_MODIFY        = 1
  constant OFPFC_MODIFY_STRICT (line 135) | OFPFC_MODIFY_STRICT = 2
  constant OFPFC_DELETE (line 136) | OFPFC_DELETE        = 3
  constant OFPFC_DELETE_STRICT (line 137) | OFPFC_DELETE_STRICT = 4
  constant OFPST_DESC (line 144) | OFPST_DESC = iota
  constant OFPST_FLOW (line 148) | OFPST_FLOW
  constant OFPST_AGGREGATE (line 152) | OFPST_AGGREGATE
  constant OFPST_TABLE (line 156) | OFPST_TABLE
  constant OFPST_PORT (line 160) | OFPST_PORT
  constant OFPST_QUEUE (line 164) | OFPST_QUEUE
  constant OFPST_VENDOR (line 169) | OFPST_VENDOR = 0xffff
  constant OFPC_FRAG_NORMAL (line 173) | OFPC_FRAG_NORMAL = iota
  constant OFPC_FRAG_DROP (line 174) | OFPC_FRAG_DROP
  constant OFPC_FRAG_REASM (line 175) | OFPC_FRAG_REASM
  constant OFPC_FRAG_MASK (line 176) | OFPC_FRAG_MASK
  constant OFPPR_ADD (line 180) | OFPPR_ADD    = 0
  constant OFPPR_DELETE (line 181) | OFPPR_DELETE = 1
  constant OFPPR_MODIFY (line 182) | OFPPR_MODIFY = 2

FILE: openflow/of10/description.go
  type DescRequest (line 31) | type DescRequest struct
    method MarshalBinary (line 41) | func (r *DescRequest) MarshalBinary() ([]byte, error) {
  function NewDescRequest (line 35) | func NewDescRequest(xid uint32) openflow.DescRequest {
  type DescReply (line 50) | type DescReply struct
    method Manufacturer (line 59) | func (r DescReply) Manufacturer() string {
    method Hardware (line 63) | func (r DescReply) Hardware() string {
    method Software (line 67) | func (r DescReply) Software() string {
    method Serial (line 71) | func (r DescReply) Serial() string {
    method Description (line 75) | func (r DescReply) Description() string {
    method UnmarshalBinary (line 79) | func (r *DescReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/echo.go
  function NewEchoRequest (line 28) | func NewEchoRequest(xid uint32) openflow.EchoRequest {
  function NewEchoReply (line 34) | func NewEchoReply(xid uint32) openflow.EchoReply {

FILE: openflow/of10/factory.go
  type Factory (line 33) | type Factory struct
    method ProtocolVersion (line 41) | func (r *Factory) ProtocolVersion() uint8 {
    method getTransactionID (line 45) | func (r *Factory) getTransactionID() uint32 {
    method NewHello (line 50) | func (r *Factory) NewHello() (openflow.Hello, error) {
    method NewEchoRequest (line 54) | func (r *Factory) NewEchoRequest() (openflow.EchoRequest, error) {
    method NewEchoReply (line 58) | func (r *Factory) NewEchoReply() (openflow.EchoReply, error) {
    method NewAction (line 62) | func (r *Factory) NewAction() (openflow.Action, error) {
    method NewMatch (line 66) | func (r *Factory) NewMatch() (openflow.Match, error) {
    method NewBarrierRequest (line 70) | func (r *Factory) NewBarrierRequest() (openflow.BarrierRequest, error) {
    method NewBarrierReply (line 74) | func (r *Factory) NewBarrierReply() (openflow.BarrierReply, error) {
    method NewSetConfig (line 78) | func (r *Factory) NewSetConfig() (openflow.SetConfig, error) {
    method NewGetConfigRequest (line 82) | func (r *Factory) NewGetConfigRequest() (openflow.GetConfigRequest, er...
    method NewGetConfigReply (line 86) | func (r *Factory) NewGetConfigReply() (openflow.GetConfigReply, error) {
    method NewFeaturesRequest (line 90) | func (r *Factory) NewFeaturesRequest() (openflow.FeaturesRequest, erro...
    method NewFeaturesReply (line 94) | func (r *Factory) NewFeaturesReply() (openflow.FeaturesReply, error) {
    method NewFlowMod (line 114) | func (r *Factory) NewFlowMod(cmd openflow.FlowModCmd) (openflow.FlowMo...
    method NewFlowRemoved (line 118) | func (r *Factory) NewFlowRemoved() (openflow.FlowRemoved, error) {
    method NewPacketIn (line 122) | func (r *Factory) NewPacketIn() (openflow.PacketIn, error) {
    method NewPacketOut (line 126) | func (r *Factory) NewPacketOut() (openflow.PacketOut, error) {
    method NewPortStatus (line 130) | func (r *Factory) NewPortStatus() (openflow.PortStatus, error) {
    method NewDescRequest (line 134) | func (r *Factory) NewDescRequest() (openflow.DescRequest, error) {
    method NewDescReply (line 138) | func (r *Factory) NewDescReply() (openflow.DescReply, error) {
    method NewFlowStatsRequest (line 142) | func (r *Factory) NewFlowStatsRequest() (openflow.FlowStatsRequest, er...
    method NewPortDescRequest (line 148) | func (r *Factory) NewPortDescRequest() (openflow.PortDescRequest, erro...
    method NewPortDescReply (line 152) | func (r *Factory) NewPortDescReply() (openflow.PortDescReply, error) {
    method NewTableFeaturesRequest (line 156) | func (r *Factory) NewTableFeaturesRequest() (openflow.TableFeaturesReq...
    method NewError (line 160) | func (r *Factory) NewError() (openflow.Error, error) {
    method NewInstruction (line 166) | func (r *Factory) NewInstruction() (openflow.Instruction, error) {
    method NewQueueGetConfigRequest (line 170) | func (r *Factory) NewQueueGetConfigRequest() (openflow.QueueGetConfigR...
  function NewFactory (line 37) | func NewFactory() openflow.Factory {
  function getFlowModCmd (line 98) | func getFlowModCmd(cmd openflow.FlowModCmd) uint16 {

FILE: openflow/of10/features.go
  type FeaturesRequest (line 30) | type FeaturesRequest struct
    method MarshalBinary (line 40) | func (r *FeaturesRequest) MarshalBinary() ([]byte, error) {
  function NewFeaturesRequest (line 34) | func NewFeaturesRequest(xid uint32) openflow.FeaturesRequest {
  type FeaturesReply (line 44) | type FeaturesReply struct
    method DPID (line 54) | func (r FeaturesReply) DPID() uint64 {
    method NumBuffers (line 58) | func (r FeaturesReply) NumBuffers() uint32 {
    method NumTables (line 62) | func (r FeaturesReply) NumTables() uint8 {
    method Capabilities (line 66) | func (r FeaturesReply) Capabilities() uint32 {
    method Actions (line 70) | func (r FeaturesReply) Actions() uint32 {
    method Ports (line 74) | func (r FeaturesReply) Ports() []openflow.Port {
    method AuxID (line 78) | func (r FeaturesReply) AuxID() uint8 {
    method UnmarshalBinary (line 83) | func (r *FeaturesReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/flow_mod.go
  type FlowMod (line 31) | type FlowMod struct
    method Error (line 56) | func (r *FlowMod) Error() error {
    method Cookie (line 60) | func (r *FlowMod) Cookie() uint64 {
    method SetCookie (line 64) | func (r *FlowMod) SetCookie(cookie uint64) {
    method CookieMask (line 68) | func (r *FlowMod) CookieMask() uint64 {
    method SetCookieMask (line 73) | func (r *FlowMod) SetCookieMask(mask uint64) {
    method TableID (line 77) | func (r *FlowMod) TableID() uint8 {
    method SetTableID (line 82) | func (r *FlowMod) SetTableID(id uint8) {
    method IdleTimeout (line 86) | func (r *FlowMod) IdleTimeout() uint16 {
    method SetIdleTimeout (line 90) | func (r *FlowMod) SetIdleTimeout(timeout uint16) {
    method HardTimeout (line 94) | func (r *FlowMod) HardTimeout() uint16 {
    method SetHardTimeout (line 98) | func (r *FlowMod) SetHardTimeout(timeout uint16) {
    method Priority (line 102) | func (r *FlowMod) Priority() uint16 {
    method SetPriority (line 106) | func (r *FlowMod) SetPriority(priority uint16) {
    method FlowMatch (line 110) | func (r *FlowMod) FlowMatch() openflow.Match {
    method SetFlowMatch (line 114) | func (r *FlowMod) SetFlowMatch(match openflow.Match) {
    method FlowInstruction (line 121) | func (r *FlowMod) FlowInstruction() openflow.Instruction {
    method SetFlowInstruction (line 125) | func (r *FlowMod) SetFlowInstruction(inst openflow.Instruction) {
    method OutPort (line 132) | func (r *FlowMod) OutPort() openflow.OutPort {
    method SetOutPort (line 136) | func (r *FlowMod) SetOutPort(p openflow.OutPort) {
    method MarshalBinary (line 140) | func (r *FlowMod) MarshalBinary() ([]byte, error) {
  function NewFlowMod (line 44) | func NewFlowMod(xid uint32, cmd uint16) openflow.FlowMod {

FILE: openflow/of10/flow_removed.go
  type FlowRemoved (line 30) | type FlowRemoved struct
    method Cookie (line 43) | func (r FlowRemoved) Cookie() uint64 {
    method Priority (line 47) | func (r FlowRemoved) Priority() uint16 {
    method Reason (line 51) | func (r FlowRemoved) Reason() uint8 {
    method TableID (line 55) | func (r FlowRemoved) TableID() uint8 {
    method DurationSec (line 60) | func (r FlowRemoved) DurationSec() uint32 {
    method DurationNanoSec (line 64) | func (r FlowRemoved) DurationNanoSec() uint32 {
    method IdleTimeout (line 68) | func (r FlowRemoved) IdleTimeout() uint16 {
    method HardTimeout (line 72) | func (r FlowRemoved) HardTimeout() uint16 {
    method PacketCount (line 77) | func (r FlowRemoved) PacketCount() uint64 {
    method ByteCount (line 81) | func (r FlowRemoved) ByteCount() uint64 {
    method Match (line 85) | func (r FlowRemoved) Match() openflow.Match {
    method UnmarshalBinary (line 89) | func (r *FlowRemoved) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/flow_stats.go
  type FlowStatsRequest (line 31) | type FlowStatsRequest struct
    method Error (line 44) | func (r *FlowStatsRequest) Error() error {
    method Cookie (line 48) | func (r *FlowStatsRequest) Cookie() uint64 {
    method SetCookie (line 53) | func (r *FlowStatsRequest) SetCookie(cookie uint64) {
    method CookieMask (line 57) | func (r *FlowStatsRequest) CookieMask() uint64 {
    method SetCookieMask (line 62) | func (r *FlowStatsRequest) SetCookieMask(mask uint64) {
    method Match (line 66) | func (r *FlowStatsRequest) Match() openflow.Match {
    method SetMatch (line 70) | func (r *FlowStatsRequest) SetMatch(match openflow.Match) {
    method TableID (line 77) | func (r *FlowStatsRequest) TableID() uint8 {
    method SetTableID (line 82) | func (r *FlowStatsRequest) SetTableID(id uint8) {
    method MarshalBinary (line 87) | func (r *FlowStatsRequest) MarshalBinary() ([]byte, error) {
  function NewFlowStatsRequest (line 38) | func NewFlowStatsRequest(xid uint32) openflow.FlowStatsRequest {

FILE: openflow/of10/hello.go
  function NewHello (line 28) | func NewHello(xid uint32) openflow.Hello {

FILE: openflow/of10/instruction.go
  type Instruction (line 30) | type Instruction struct
    method Error (line 35) | func (r *Instruction) Error() error {
    method GotoTable (line 39) | func (r *Instruction) GotoTable(tableID uint8) {
    method WriteAction (line 43) | func (r *Instruction) WriteAction(act openflow.Action) {
    method ApplyAction (line 50) | func (r *Instruction) ApplyAction(act openflow.Action) {
    method MarshalBinary (line 57) | func (r *Instruction) MarshalBinary() ([]byte, error) {

FILE: openflow/of10/match.go
  type Wildcard (line 33) | type Wildcard struct
    method MarshalBinary (line 66) | func (r *Wildcard) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 116) | func (r *Wildcard) UnmarshalBinary(data []byte) error {
  function newWildcardAll (line 50) | func newWildcardAll() *Wildcard {
  type Match (line 155) | type Match struct
    method Error (line 182) | func (r *Match) Error() error {
    method SetWildcardSrcPort (line 186) | func (r *Match) SetWildcardSrcPort() {
    method SetSrcPort (line 191) | func (r *Match) SetSrcPort(p uint16) {
    method SrcPort (line 207) | func (r *Match) SrcPort() (wildcard bool, port uint16) {
    method SetWildcardDstPort (line 211) | func (r *Match) SetWildcardDstPort() {
    method SetDstPort (line 216) | func (r *Match) SetDstPort(p uint16) {
    method DstPort (line 232) | func (r *Match) DstPort() (wildcard bool, port uint16) {
    method SetWildcardVLANID (line 236) | func (r *Match) SetWildcardVLANID() {
    method SetVLANID (line 241) | func (r *Match) SetVLANID(id uint16) {
    method VLANID (line 246) | func (r *Match) VLANID() (wildcard bool, vlanID uint16) {
    method SetWildcardVLANPriority (line 250) | func (r *Match) SetWildcardVLANPriority() {
    method SetVLANPriority (line 255) | func (r *Match) SetVLANPriority(p uint8) {
    method VLANPriority (line 260) | func (r *Match) VLANPriority() (wildcard bool, priority uint8) {
    method SetWildcardIPProtocol (line 264) | func (r *Match) SetWildcardIPProtocol() {
    method SetIPProtocol (line 269) | func (r *Match) SetIPProtocol(p uint8) {
    method IPProtocol (line 280) | func (r *Match) IPProtocol() (wildcard bool, protocol uint8) {
    method SetWildcardInPort (line 284) | func (r *Match) SetWildcardInPort() {
    method SetInPort (line 289) | func (r *Match) SetInPort(port openflow.InPort) {
    method InPort (line 294) | func (r *Match) InPort() (wildcard bool, inport openflow.InPort) {
    method SetWildcardSrcMAC (line 300) | func (r *Match) SetWildcardSrcMAC() {
    method SetSrcMAC (line 305) | func (r *Match) SetSrcMAC(mac net.HardwareAddr) {
    method SrcMAC (line 315) | func (r *Match) SrcMAC() (wildcard bool, mac net.HardwareAddr) {
    method SetWildcardDstMAC (line 319) | func (r *Match) SetWildcardDstMAC() {
    method SetDstMAC (line 324) | func (r *Match) SetDstMAC(mac net.HardwareAddr) {
    method DstMAC (line 334) | func (r *Match) DstMAC() (wildcard bool, mac net.HardwareAddr) {
    method SetSrcIP (line 338) | func (r *Match) SetSrcIP(ip *net.IPNet) {
    method SrcIP (line 363) | func (r *Match) SrcIP() *net.IPNet {
    method SetDstIP (line 373) | func (r *Match) SetDstIP(ip *net.IPNet) {
    method DstIP (line 398) | func (r *Match) DstIP() *net.IPNet {
    method SetWildcardEtherType (line 408) | func (r *Match) SetWildcardEtherType() {
    method SetEtherType (line 413) | func (r *Match) SetEtherType(t uint16) {
    method EtherType (line 418) | func (r *Match) EtherType() (wildcard bool, etherType uint16) {
    method MarshalBinary (line 422) | func (r *Match) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 472) | func (r *Match) UnmarshalBinary(data []byte) error {
  function NewMatch (line 172) | func NewMatch() openflow.Match {

FILE: openflow/of10/packet_in.go
  type PacketIn (line 30) | type PacketIn struct
    method BufferID (line 39) | func (r PacketIn) BufferID() uint32 {
    method InPort (line 43) | func (r PacketIn) InPort() uint32 {
    method Data (line 47) | func (r PacketIn) Data() []byte {
    method Length (line 51) | func (r PacketIn) Length() uint16 {
    method TableID (line 55) | func (r PacketIn) TableID() uint8 {
    method Reason (line 60) | func (r PacketIn) Reason() uint8 {
    method Cookie (line 64) | func (r PacketIn) Cookie() uint64 {
    method UnmarshalBinary (line 69) | func (r *PacketIn) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/packet_out.go
  type PacketOut (line 30) | type PacketOut struct
    method Error (line 44) | func (r *PacketOut) Error() error {
    method InPort (line 48) | func (r *PacketOut) InPort() openflow.InPort {
    method SetInPort (line 52) | func (r *PacketOut) SetInPort(port openflow.InPort) {
    method Action (line 56) | func (r *PacketOut) Action() openflow.Action {
    method SetAction (line 60) | func (r *PacketOut) SetAction(action openflow.Action) {
    method Data (line 67) | func (r *PacketOut) Data() []byte {
    method SetData (line 71) | func (r *PacketOut) SetData(data []byte) {
    method MarshalBinary (line 78) | func (r *PacketOut) MarshalBinary() ([]byte, error) {
  function NewPacketOut (line 38) | func NewPacketOut(xid uint32) openflow.PacketOut {

FILE: openflow/of10/port.go
  type Port (line 32) | type Port struct
    method Number (line 46) | func (r Port) Number() uint32 {
    method MAC (line 50) | func (r Port) MAC() net.HardwareAddr {
    method Name (line 54) | func (r Port) Name() string {
    method IsPortDown (line 58) | func (r Port) IsPortDown() bool {
    method IsLinkDown (line 66) | func (r Port) IsLinkDown() bool {
    method IsCopper (line 74) | func (r Port) IsCopper() bool {
    method IsFiber (line 78) | func (r Port) IsFiber() bool {
    method IsAutoNego (line 82) | func (r Port) IsAutoNego() bool {
    method Speed (line 86) | func (r Port) Speed() uint64 {
    method UnmarshalBinary (line 107) | func (r *Port) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/port_status.go
  type PortStatus (line 28) | type PortStatus struct
    method Reason (line 34) | func (r PortStatus) Reason() openflow.PortReason {
    method Port (line 47) | func (r PortStatus) Port() openflow.Port {
    method UnmarshalBinary (line 51) | func (r *PortStatus) UnmarshalBinary(data []byte) error {

FILE: openflow/of10/queue.go
  type QueueGetConfigRequest (line 30) | type QueueGetConfigRequest struct
    method Port (line 41) | func (r *QueueGetConfigRequest) Port() openflow.OutPort {
    method SetPort (line 45) | func (r *QueueGetConfigRequest) SetPort(p openflow.OutPort) {
    method MarshalBinary (line 49) | func (r *QueueGetConfigRequest) MarshalBinary() ([]byte, error) {
  function NewQueueGetConfigRequest (line 35) | func NewQueueGetConfigRequest(xid uint32) openflow.QueueGetConfigRequest {
  type QueueProperty (line 59) | type QueueProperty struct
    method Type (line 69) | func (r *QueueProperty) Type() openflow.PropertyType {
    method Length (line 73) | func (r *QueueProperty) Length() uint16 {
    method Rate (line 77) | func (r *QueueProperty) Rate() (uint16, error) {
    method Experimenter (line 85) | func (r *QueueProperty) Experimenter() (uint32, error) {
    method Data (line 90) | func (r *QueueProperty) Data() []byte {
    method UnmarshalBinary (line 94) | func (r *QueueProperty) UnmarshalBinary(data []byte) error {
  function NewQueueProperty (line 65) | func NewQueueProperty() openflow.QueueProperty {
  type Queue (line 112) | type Queue struct
    method ID (line 118) | func (r *Queue) ID() uint32 {
    method Port (line 122) | func (r *Queue) Port() uint32 {
    method Length (line 127) | func (r *Queue) Length() uint16 {
    method Property (line 131) | func (r *Queue) Property() []openflow.QueueProperty {
    method UnmarshalBinary (line 135) | func (r *Queue) UnmarshalBinary(data []byte) error {
  function NewQueue (line 156) | func NewQueue() openflow.Queue {
  type QueueGetConfigReply (line 160) | type QueueGetConfigReply struct
    method Port (line 166) | func (r *QueueGetConfigReply) Port() uint32 {
    method Queue (line 170) | func (r *QueueGetConfigReply) Queue() []openflow.Queue {
    method UnmarshalBinary (line 174) | func (r *QueueGetConfigReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/action.go
  type Action (line 33) | type Action struct
    method MarshalBinary (line 99) | func (r *Action) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 133) | func (r *Action) UnmarshalBinary(data []byte) error {
  function NewAction (line 37) | func NewAction() openflow.Action {
  function marshalOutput (line 43) | func marshalOutput(p openflow.OutPort) ([]byte, error) {
  function marshalMAC (line 72) | func marshalMAC(t uint8, mac net.HardwareAddr) ([]byte, error) {

FILE: openflow/of13/barrier.go
  type BarrierRequest (line 28) | type BarrierRequest struct
    method MarshalBinary (line 38) | func (r *BarrierRequest) MarshalBinary() ([]byte, error) {
  function NewBarrierRequest (line 32) | func NewBarrierRequest(xid uint32) openflow.BarrierRequest {
  type BarrierReply (line 42) | type BarrierReply struct
    method UnmarshalBinary (line 46) | func (r *BarrierReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/config.go
  type Config (line 31) | type Config struct
    method Flags (line 37) | func (r *Config) Flags() openflow.ConfigFlag {
    method SetFlags (line 52) | func (r *Config) SetFlags(flags openflow.ConfigFlag) {
    method MissSendLength (line 67) | func (r *Config) MissSendLength() uint16 {
    method SetMissSendLength (line 71) | func (r *Config) SetMissSendLength(length uint16) {
    method Error (line 75) | func (r *Config) Error() error {
  type SetConfig (line 79) | type SetConfig struct
    method MarshalBinary (line 94) | func (r *SetConfig) MarshalBinary() ([]byte, error) {
  function NewSetConfig (line 84) | func NewSetConfig(xid uint32) openflow.SetConfig {
  type GetConfigRequest (line 107) | type GetConfigRequest struct
    method MarshalBinary (line 117) | func (r *GetConfigRequest) MarshalBinary() ([]byte, error) {
  function NewGetConfigRequest (line 111) | func NewGetConfigRequest(xid uint32) openflow.GetConfigRequest {
  type GetConfigReply (line 121) | type GetConfigReply struct
    method UnmarshalBinary (line 126) | func (r *GetConfigReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/const.go
  constant OFPT_HELLO (line 26) | OFPT_HELLO        uint8 = iota
  constant OFPT_ERROR (line 27) | OFPT_ERROR
  constant OFPT_ECHO_REQUEST (line 28) | OFPT_ECHO_REQUEST
  constant OFPT_ECHO_REPLY (line 29) | OFPT_ECHO_REPLY
  constant OFPT_EXPERIMENTER (line 30) | OFPT_EXPERIMENTER
  constant OFPT_FEATURES_REQUEST (line 32) | OFPT_FEATURES_REQUEST
  constant OFPT_FEATURES_REPLY (line 33) | OFPT_FEATURES_REPLY
  constant OFPT_GET_CONFIG_REQUEST (line 34) | OFPT_GET_CONFIG_REQUEST
  constant OFPT_GET_CONFIG_REPLY (line 35) | OFPT_GET_CONFIG_REPLY
  constant OFPT_SET_CONFIG (line 36) | OFPT_SET_CONFIG
  constant OFPT_PACKET_IN (line 38) | OFPT_PACKET_IN
  constant OFPT_FLOW_REMOVED (line 39) | OFPT_FLOW_REMOVED
  constant OFPT_PORT_STATUS (line 40) | OFPT_PORT_STATUS
  constant OFPT_PACKET_OUT (line 42) | OFPT_PACKET_OUT
  constant OFPT_FLOW_MOD (line 43) | OFPT_FLOW_MOD
  constant OFPT_GROUP_MOD (line 44) | OFPT_GROUP_MOD
  constant OFPT_PORT_MOD (line 45) | OFPT_PORT_MOD
  constant OFPT_TABLE_MOD (line 46) | OFPT_TABLE_MOD
  constant OFPT_MULTIPART_REQUEST (line 48) | OFPT_MULTIPART_REQUEST
  constant OFPT_MULTIPART_REPLY (line 49) | OFPT_MULTIPART_REPLY
  constant OFPT_BARRIER_REQUEST (line 51) | OFPT_BARRIER_REQUEST
  constant OFPT_BARRIER_REPLY (line 52) | OFPT_BARRIER_REPLY
  constant OFPT_QUEUE_GET_CONFIG_REQUEST (line 54) | OFPT_QUEUE_GET_CONFIG_REQUEST
  constant OFPT_QUEUE_GET_CONFIG_REPLY (line 55) | OFPT_QUEUE_GET_CONFIG_REPLY
  constant OFPT_ROLE_REQUEST (line 57) | OFPT_ROLE_REQUEST
  constant OFPT_ROLE_REPLY (line 58) | OFPT_ROLE_REPLY
  constant OFPT_GET_ASYNC_REQUEST (line 60) | OFPT_GET_ASYNC_REQUEST
  constant OFPT_GET_ASYNC_REPLY (line 61) | OFPT_GET_ASYNC_REPLY
  constant OFPT_SET_ASYNC (line 62) | OFPT_SET_ASYNC
  constant OFPT_METER_MOD (line 64) | OFPT_METER_MOD
  constant OFPAT_OUTPUT (line 68) | OFPAT_OUTPUT    = 0
  constant OFPAT_SET_FIELD (line 69) | OFPAT_SET_FIELD = 25
  constant OFPP_MAX (line 74) | OFPP_MAX = 0xffffff00
  constant OFPP_IN_PORT (line 76) | OFPP_IN_PORT = 0xfffffff8
  constant OFPP_TABLE (line 77) | OFPP_TABLE   = 0xfffffff9
  constant OFPP_NORMAL (line 78) | OFPP_NORMAL  = 0xfffffffa
  constant OFPP_FLOOD (line 80) | OFPP_FLOOD      = 0xfffffffb
  constant OFPP_ALL (line 81) | OFPP_ALL        = 0xfffffffc
  constant OFPP_CONTROLLER (line 82) | OFPP_CONTROLLER = 0xfffffffd
  constant OFPP_LOCAL (line 83) | OFPP_LOCAL      = 0xfffffffe
  constant OFPP_ANY (line 84) | OFPP_ANY        = 0xffffffff
  constant OFPXMT_OFB_IN_PORT (line 88) | OFPXMT_OFB_IN_PORT = iota
  constant OFPXMT_OFB_IN_PHY_PORT (line 89) | OFPXMT_OFB_IN_PHY_PORT
  constant OFPXMT_OFB_METADATA (line 90) | OFPXMT_OFB_METADATA
  constant OFPXMT_OFB_ETH_DST (line 91) | OFPXMT_OFB_ETH_DST
  constant OFPXMT_OFB_ETH_SRC (line 92) | OFPXMT_OFB_ETH_SRC
  constant OFPXMT_OFB_ETH_TYPE (line 93) | OFPXMT_OFB_ETH_TYPE
  constant OFPXMT_OFB_VLAN_VID (line 94) | OFPXMT_OFB_VLAN_VID
  constant OFPXMT_OFB_VLAN_PCP (line 95) | OFPXMT_OFB_VLAN_PCP
  constant OFPXMT_OFB_IP_DSCP (line 96) | OFPXMT_OFB_IP_DSCP
  constant OFPXMT_OFB_IP_ECN (line 97) | OFPXMT_OFB_IP_ECN
  constant OFPXMT_OFB_IP_PROTO (line 98) | OFPXMT_OFB_IP_PROTO
  constant OFPXMT_OFB_IPV4_SRC (line 99) | OFPXMT_OFB_IPV4_SRC
  constant OFPXMT_OFB_IPV4_DST (line 100) | OFPXMT_OFB_IPV4_DST
  constant OFPXMT_OFB_TCP_SRC (line 101) | OFPXMT_OFB_TCP_SRC
  constant OFPXMT_OFB_TCP_DST (line 102) | OFPXMT_OFB_TCP_DST
  constant OFPXMT_OFB_UDP_SRC (line 103) | OFPXMT_OFB_UDP_SRC
  constant OFPXMT_OFB_UDP_DST (line 104) | OFPXMT_OFB_UDP_DST
  constant OFPXMT_OFB_SCTP_SRC (line 105) | OFPXMT_OFB_SCTP_SRC
  constant OFPXMT_OFB_SCTP_DST (line 106) | OFPXMT_OFB_SCTP_DST
  constant OFPXMT_OFB_ICMPV4_TYPE (line 107) | OFPXMT_OFB_ICMPV4_TYPE
  constant OFPXMT_OFB_ICMPV4_CODE (line 108) | OFPXMT_OFB_ICMPV4_CODE
  constant OFPXMT_OFB_ARP_OP (line 109) | OFPXMT_OFB_ARP_OP
  constant OFPXMT_OFB_ARP_SPA (line 110) | OFPXMT_OFB_ARP_SPA
  constant OFPXMT_OFB_ARP_TPA (line 111) | OFPXMT_OFB_ARP_TPA
  constant OFPXMT_OFB_ARP_SHA (line 112) | OFPXMT_OFB_ARP_SHA
  constant OFPXMT_OFB_ARP_THA (line 113) | OFPXMT_OFB_ARP_THA
  constant OFPXMT_OFB_IPV6_SRC (line 114) | OFPXMT_OFB_IPV6_SRC
  constant OFPXMT_OFB_IPV6_DST (line 115) | OFPXMT_OFB_IPV6_DST
  constant OFPXMT_OFB_IPV6_FLABEL (line 116) | OFPXMT_OFB_IPV6_FLABEL
  constant OFPXMT_OFB_ICMPV6_TYPE (line 117) | OFPXMT_OFB_ICMPV6_TYPE
  constant OFPXMT_OFB_ICMPV6_CODE (line 118) | OFPXMT_OFB_ICMPV6_CODE
  constant OFPXMT_OFB_IPV6_ND_TARGET (line 119) | OFPXMT_OFB_IPV6_ND_TARGET
  constant OFPXMT_OFB_IPV6_ND_SLL (line 120) | OFPXMT_OFB_IPV6_ND_SLL
  constant OFPXMT_OFB_IPV6_ND_TLL (line 121) | OFPXMT_OFB_IPV6_ND_TLL
  constant OFPXMT_OFB_MPLS_LABEL (line 122) | OFPXMT_OFB_MPLS_LABEL
  constant OFPXMT_OFB_MPLS_TC (line 123) | OFPXMT_OFB_MPLS_TC
  constant OFPXMT_OFP_MPLS_BOS (line 124) | OFPXMT_OFP_MPLS_BOS
  constant OFPXMT_OFB_PBB_ISID (line 125) | OFPXMT_OFB_PBB_ISID
  constant OFPXMT_OFB_TUNNEL_ID (line 126) | OFPXMT_OFB_TUNNEL_ID
  constant OFPXMT_OFB_IPV6_EXTHDR (line 127) | OFPXMT_OFB_IPV6_EXTHDR
  constant OFPMT_STANDARD (line 131) | OFPMT_STANDARD = 0
  constant OFPMT_OXM (line 132) | OFPMT_OXM      = 1
  constant OFPFC_ADD (line 136) | OFPFC_ADD           = 0
  constant OFPFC_MODIFY (line 137) | OFPFC_MODIFY        = 1
  constant OFPFC_MODIFY_STRICT (line 138) | OFPFC_MODIFY_STRICT = 2
  constant OFPFC_DELETE (line 139) | OFPFC_DELETE        = 3
  constant OFPFC_DELETE_STRICT (line 140) | OFPFC_DELETE_STRICT = 4
  constant OFP_NO_BUFFER (line 144) | OFP_NO_BUFFER = 0xffffffff
  constant OFPFF_SEND_FLOW_REM (line 148) | OFPFF_SEND_FLOW_REM = 1 << 0
  constant OFPFF_CHECK_OVERLAP (line 149) | OFPFF_CHECK_OVERLAP = 1 << 1
  constant OFPFF_RESET_COUNTS (line 150) | OFPFF_RESET_COUNTS  = 1 << 2
  constant OFPFF_NO_PKT_COUNTS (line 151) | OFPFF_NO_PKT_COUNTS = 1 << 3
  constant OFPFF_NO_BYT_COUNTS (line 152) | OFPFF_NO_BYT_COUNTS = 1 << 4
  constant OFPPC_PORT_DOWN (line 156) | OFPPC_PORT_DOWN    = 1 << 0
  constant OFPPC_NO_RECV (line 157) | OFPPC_NO_RECV      = 1 << 2
  constant OFPPC_NO_FWD (line 158) | OFPPC_NO_FWD       = 1 << 5
  constant OFPPC_NO_PACKET_IN (line 159) | OFPPC_NO_PACKET_IN = 1 << 6
  constant OFPPS_LINK_DOWN (line 163) | OFPPS_LINK_DOWN = 1 << 0
  constant OFPPS_BLOCKED (line 164) | OFPPS_BLOCKED   = 1 << 1
  constant OFPPS_LIVE (line 165) | OFPPS_LIVE      = 1 << 2
  constant OFPPF_10MB_HD (line 169) | OFPPF_10MB_HD    = 1 << 0
  constant OFPPF_10MB_FD (line 170) | OFPPF_10MB_FD    = 1 << 1
  constant OFPPF_100MB_HD (line 171) | OFPPF_100MB_HD   = 1 << 2
  constant OFPPF_100MB_FD (line 172) | OFPPF_100MB_FD   = 1 << 3
  constant OFPPF_1GB_HD (line 173) | OFPPF_1GB_HD     = 1 << 4
  constant OFPPF_1GB_FD (line 174) | OFPPF_1GB_FD     = 1 << 5
  constant OFPPF_10GB_FD (line 175) | OFPPF_10GB_FD    = 1 << 6
  constant OFPPF_40GB_FD (line 176) | OFPPF_40GB_FD    = 1 << 7
  constant OFPPF_100GB_FD (line 177) | OFPPF_100GB_FD   = 1 << 8
  constant OFPPF_1TB_FD (line 178) | OFPPF_1TB_FD     = 1 << 9
  constant OFPPF_OTHER (line 179) | OFPPF_OTHER      = 1 << 10
  constant OFPPF_COPPER (line 180) | OFPPF_COPPER     = 1 << 11
  constant OFPPF_FIBER (line 181) | OFPPF_FIBER      = 1 << 12
  constant OFPPF_AUTONEG (line 182) | OFPPF_AUTONEG    = 1 << 13
  constant OFPPF_PAUSE (line 183) | OFPPF_PAUSE      = 1 << 14
  constant OFPPF_PAUSE_ASYM (line 184) | OFPPF_PAUSE_ASYM = 1 << 15
  constant OFPMP_DESC (line 191) | OFPMP_DESC = 0
  constant OFPMP_FLOW (line 195) | OFPMP_FLOW = 1
  constant OFPMP_AGGREGATE (line 199) | OFPMP_AGGREGATE = 2
  constant OFPMP_TABLE (line 203) | OFPMP_TABLE = 3
  constant OFPMP_PORT_STATS (line 207) | OFPMP_PORT_STATS = 4
  constant OFPMP_QUEUE (line 211) | OFPMP_QUEUE = 5
  constant OFPMP_GROUP (line 215) | OFPMP_GROUP = 6
  constant OFPMP_GROUP_DESC (line 219) | OFPMP_GROUP_DESC = 7
  constant OFPMP_GROUP_FEATURES (line 223) | OFPMP_GROUP_FEATURES = 8
  constant OFPMP_METER (line 227) | OFPMP_METER = 9
  constant OFPMP_METER_CONFIG (line 231) | OFPMP_METER_CONFIG = 10
  constant OFPMP_METER_FEATURES (line 235) | OFPMP_METER_FEATURES = 11
  constant OFPMP_TABLE_FEATURES (line 242) | OFPMP_TABLE_FEATURES = 12
  constant OFPMP_PORT_DESC (line 246) | OFPMP_PORT_DESC = 13
  constant OFPMP_EXPERIMENTER (line 251) | OFPMP_EXPERIMENTER = 0xffff
  constant OFPG_ANY (line 255) | OFPG_ANY = 0xffffffff
  constant OFPC_FRAG_NORMAL (line 259) | OFPC_FRAG_NORMAL = 0
  constant OFPC_FRAG_DROP (line 260) | OFPC_FRAG_DROP   = 1 << 0
  constant OFPC_FRAG_REASM (line 261) | OFPC_FRAG_REASM  = 1 << 1
  constant OFPC_FRAG_MASK (line 262) | OFPC_FRAG_MASK   = 3
  constant OFPPR_ADD (line 266) | OFPPR_ADD    = 0
  constant OFPPR_DELETE (line 267) | OFPPR_DELETE = 1
  constant OFPPR_MODIFY (line 268) | OFPPR_MODIFY = 2
  constant OFPIT_GOTO_TABLE (line 272) | OFPIT_GOTO_TABLE     = 1
  constant OFPIT_WRITE_METADATA (line 273) | OFPIT_WRITE_METADATA = 2
  constant OFPIT_WRITE_ACTIONS (line 274) | OFPIT_WRITE_ACTIONS  = 3
  constant OFPIT_APPLY_ACTIONS (line 275) | OFPIT_APPLY_ACTIONS  = 4
  constant OFPIT_CLEAR_ACTIONS (line 276) | OFPIT_CLEAR_ACTIONS  = 5
  constant OFPIT_METER (line 277) | OFPIT_METER          = 6
  constant OFPIT_EXPERIMENTER (line 278) | OFPIT_EXPERIMENTER   = 0xFFFF

FILE: openflow/of13/echo.go
  function NewEchoRequest (line 28) | func NewEchoRequest(xid uint32) openflow.EchoRequest {
  function NewEchoReply (line 34) | func NewEchoReply(xid uint32) openflow.EchoReply {

FILE: openflow/of13/factory.go
  type Factory (line 32) | type Factory struct
    method ProtocolVersion (line 40) | func (r *Factory) ProtocolVersion() uint8 {
    method getTransactionID (line 44) | func (r *Factory) getTransactionID() uint32 {
    method NewHello (line 49) | func (r *Factory) NewHello() (openflow.Hello, error) {
    method NewEchoRequest (line 53) | func (r *Factory) NewEchoRequest() (openflow.EchoRequest, error) {
    method NewEchoReply (line 57) | func (r *Factory) NewEchoReply() (openflow.EchoReply, error) {
    method NewAction (line 61) | func (r *Factory) NewAction() (openflow.Action, error) {
    method NewMatch (line 65) | func (r *Factory) NewMatch() (openflow.Match, error) {
    method NewBarrierRequest (line 69) | func (r *Factory) NewBarrierRequest() (openflow.BarrierRequest, error) {
    method NewBarrierReply (line 73) | func (r *Factory) NewBarrierReply() (openflow.BarrierReply, error) {
    method NewSetConfig (line 77) | func (r *Factory) NewSetConfig() (openflow.SetConfig, error) {
    method NewGetConfigRequest (line 81) | func (r *Factory) NewGetConfigRequest() (openflow.GetConfigRequest, er...
    method NewGetConfigReply (line 85) | func (r *Factory) NewGetConfigReply() (openflow.GetConfigReply, error) {
    method NewFeaturesRequest (line 89) | func (r *Factory) NewFeaturesRequest() (openflow.FeaturesRequest, erro...
    method NewFeaturesReply (line 93) | func (r *Factory) NewFeaturesReply() (openflow.FeaturesReply, error) {
    method NewFlowMod (line 113) | func (r *Factory) NewFlowMod(cmd openflow.FlowModCmd) (openflow.FlowMo...
    method NewFlowRemoved (line 117) | func (r *Factory) NewFlowRemoved() (openflow.FlowRemoved, error) {
    method NewPacketIn (line 121) | func (r *Factory) NewPacketIn() (openflow.PacketIn, error) {
    method NewPacketOut (line 125) | func (r *Factory) NewPacketOut() (openflow.PacketOut, error) {
    method NewPortStatus (line 129) | func (r *Factory) NewPortStatus() (openflow.PortStatus, error) {
    method NewDescRequest (line 133) | func (r *Factory) NewDescRequest() (openflow.DescRequest, error) {
    method NewDescReply (line 137) | func (r *Factory) NewDescReply() (openflow.DescReply, error) {
    method NewFlowStatsRequest (line 141) | func (r *Factory) NewFlowStatsRequest() (openflow.FlowStatsRequest, er...
    method NewPortDescRequest (line 147) | func (r *Factory) NewPortDescRequest() (openflow.PortDescRequest, erro...
    method NewPortDescReply (line 151) | func (r *Factory) NewPortDescReply() (openflow.PortDescReply, error) {
    method NewTableFeaturesRequest (line 155) | func (r *Factory) NewTableFeaturesRequest() (openflow.TableFeaturesReq...
    method NewError (line 159) | func (r *Factory) NewError() (openflow.Error, error) {
    method NewInstruction (line 165) | func (r *Factory) NewInstruction() (openflow.Instruction, error) {
    method NewQueueGetConfigRequest (line 169) | func (r *Factory) NewQueueGetConfigRequest() (openflow.QueueGetConfigR...
  function NewFactory (line 36) | func NewFactory() openflow.Factory {
  function getFlowModCmd (line 97) | func getFlowModCmd(cmd openflow.FlowModCmd) uint8 {

FILE: openflow/of13/features.go
  type FeaturesRequest (line 30) | type FeaturesRequest struct
    method MarshalBinary (line 40) | func (r *FeaturesRequest) MarshalBinary() ([]byte, error) {
  function NewFeaturesRequest (line 34) | func NewFeaturesRequest(xid uint32) openflow.FeaturesRequest {
  type FeaturesReply (line 44) | type FeaturesReply struct
    method DPID (line 53) | func (r FeaturesReply) DPID() uint64 {
    method NumBuffers (line 57) | func (r FeaturesReply) NumBuffers() uint32 {
    method NumTables (line 61) | func (r FeaturesReply) NumTables() uint8 {
    method Capabilities (line 65) | func (r FeaturesReply) Capabilities() uint32 {
    method Actions (line 69) | func (r FeaturesReply) Actions() uint32 {
    method Ports (line 74) | func (r FeaturesReply) Ports() []openflow.Port {
    method AuxID (line 79) | func (r FeaturesReply) AuxID() uint8 {
    method UnmarshalBinary (line 83) | func (r *FeaturesReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/flow_mod.go
  type FlowMod (line 31) | type FlowMod struct
    method Error (line 58) | func (r *FlowMod) Error() error {
    method Cookie (line 62) | func (r *FlowMod) Cookie() uint64 {
    method SetCookie (line 66) | func (r *FlowMod) SetCookie(cookie uint64) {
    method CookieMask (line 70) | func (r *FlowMod) CookieMask() uint64 {
    method SetCookieMask (line 74) | func (r *FlowMod) SetCookieMask(mask uint64) {
    method TableID (line 78) | func (r *FlowMod) TableID() uint8 {
    method SetTableID (line 82) | func (r *FlowMod) SetTableID(id uint8) {
    method IdleTimeout (line 86) | func (r *FlowMod) IdleTimeout() uint16 {
    method SetIdleTimeout (line 90) | func (r *FlowMod) SetIdleTimeout(timeout uint16) {
    method HardTimeout (line 94) | func (r *FlowMod) HardTimeout() uint16 {
    method SetHardTimeout (line 98) | func (r *FlowMod) SetHardTimeout(timeout uint16) {
    method Priority (line 102) | func (r *FlowMod) Priority() uint16 {
    method SetPriority (line 106) | func (r *FlowMod) SetPriority(priority uint16) {
    method FlowMatch (line 110) | func (r *FlowMod) FlowMatch() openflow.Match {
    method SetFlowMatch (line 114) | func (r *FlowMod) SetFlowMatch(match openflow.Match) {
    method FlowInstruction (line 121) | func (r *FlowMod) FlowInstruction() openflow.Instruction {
    method SetFlowInstruction (line 125) | func (r *FlowMod) SetFlowInstruction(inst openflow.Instruction) {
    method OutPort (line 132) | func (r *FlowMod) OutPort() openflow.OutPort {
    method SetOutPort (line 136) | func (r *FlowMod) SetOutPort(p openflow.OutPort) {
    method MarshalBinary (line 140) | func (r *FlowMod) MarshalBinary() ([]byte, error) {
  function NewFlowMod (line 46) | func NewFlowMod(xid uint32, cmd uint8) openflow.FlowMod {

FILE: openflow/of13/flow_removed.go
  type FlowRemoved (line 30) | type FlowRemoved struct
    method Cookie (line 45) | func (r FlowRemoved) Cookie() uint64 {
    method Priority (line 49) | func (r FlowRemoved) Priority() uint16 {
    method Reason (line 53) | func (r FlowRemoved) Reason() uint8 {
    method TableID (line 57) | func (r FlowRemoved) TableID() uint8 {
    method DurationSec (line 61) | func (r FlowRemoved) DurationSec() uint32 {
    method DurationNanoSec (line 65) | func (r FlowRemoved) DurationNanoSec() uint32 {
    method IdleTimeout (line 69) | func (r FlowRemoved) IdleTimeout() uint16 {
    method HardTimeout (line 73) | func (r FlowRemoved) HardTimeout() uint16 {
    method PacketCount (line 77) | func (r FlowRemoved) PacketCount() uint64 {
    method ByteCount (line 81) | func (r FlowRemoved) ByteCount() uint64 {
    method Match (line 85) | func (r FlowRemoved) Match() openflow.Match {
    method UnmarshalBinary (line 89) | func (r *FlowRemoved) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/hello.go
  function NewHello (line 28) | func NewHello(xid uint32) openflow.Hello {

FILE: openflow/of13/instruction.go
  type Instruction (line 32) | type Instruction struct
    method Error (line 95) | func (r *Instruction) Error() error {
    method GotoTable (line 99) | func (r *Instruction) GotoTable(tableID uint8) {
    method WriteAction (line 103) | func (r *Instruction) WriteAction(act openflow.Action) {
    method ApplyAction (line 110) | func (r *Instruction) ApplyAction(act openflow.Action) {
    method MarshalBinary (line 117) | func (r *Instruction) MarshalBinary() ([]byte, error) {
  type gotoTable (line 37) | type gotoTable struct
    method MarshalBinary (line 41) | func (r *gotoTable) MarshalBinary() ([]byte, error) {
  type writeAction (line 51) | type writeAction struct
    method MarshalBinary (line 55) | func (r *writeAction) MarshalBinary() ([]byte, error) {
  type applyAction (line 73) | type applyAction struct
    method MarshalBinary (line 77) | func (r *applyAction) MarshalBinary() ([]byte, error) {

FILE: openflow/of13/match.go
  type Match (line 36) | type Match struct
    method Error (line 49) | func (r *Match) Error() error {
    method SetWildcardSrcPort (line 53) | func (r *Match) SetWildcardSrcPort() {
    method SetSrcPort (line 61) | func (r *Match) SetSrcPort(p uint16) {
    method SrcPort (line 97) | func (r *Match) SrcPort() (wildcard bool, port uint16) {
    method SetWildcardDstPort (line 114) | func (r *Match) SetWildcardDstPort() {
    method SetDstPort (line 122) | func (r *Match) SetDstPort(p uint16) {
    method DstPort (line 158) | func (r *Match) DstPort() (wildcard bool, port uint16) {
    method SetWildcardVLANID (line 175) | func (r *Match) SetWildcardVLANID() {
    method SetVLANID (line 182) | func (r *Match) SetVLANID(id uint16) {
    method VLANID (line 189) | func (r *Match) VLANID() (wildcard bool, vlanID uint16) {
    method SetWildcardVLANPriority (line 201) | func (r *Match) SetWildcardVLANPriority() {
    method SetVLANPriority (line 208) | func (r *Match) SetVLANPriority(p uint8) {
    method VLANPriority (line 215) | func (r *Match) VLANPriority() (wildcard bool, priority uint8) {
    method SetWildcardIPProtocol (line 227) | func (r *Match) SetWildcardIPProtocol() {
    method SetIPProtocol (line 234) | func (r *Match) SetIPProtocol(p uint8) {
    method IPProtocol (line 252) | func (r *Match) IPProtocol() (wildcard bool, protocol uint8) {
    method SetWildcardInPort (line 264) | func (r *Match) SetWildcardInPort() {
    method SetInPort (line 271) | func (r *Match) SetInPort(port openflow.InPort) {
    method InPort (line 278) | func (r *Match) InPort() (wildcard bool, inport openflow.InPort) {
    method SetWildcardSrcMAC (line 292) | func (r *Match) SetWildcardSrcMAC() {
    method SetSrcMAC (line 299) | func (r *Match) SetSrcMAC(mac net.HardwareAddr) {
    method SrcMAC (line 313) | func (r *Match) SrcMAC() (wildcard bool, mac net.HardwareAddr) {
    method SetWildcardDstMAC (line 325) | func (r *Match) SetWildcardDstMAC() {
    method SetDstMAC (line 332) | func (r *Match) SetDstMAC(mac net.HardwareAddr) {
    method DstMAC (line 346) | func (r *Match) DstMAC() (wildcard bool, mac net.HardwareAddr) {
    method SetSrcIP (line 358) | func (r *Match) SetSrcIP(ip *net.IPNet) {
    method SrcIP (line 384) | func (r *Match) SrcIP() *net.IPNet {
    method SetDstIP (line 399) | func (r *Match) SetDstIP(ip *net.IPNet) {
    method DstIP (line 425) | func (r *Match) DstIP() *net.IPNet {
    method SetWildcardEtherType (line 440) | func (r *Match) SetWildcardEtherType() {
    method SetEtherType (line 447) | func (r *Match) SetEtherType(t uint16) {
    method EtherType (line 454) | func (r *Match) EtherType() (wildcard bool, etherType uint16) {
    method MarshalBinary (line 562) | func (r *Match) MarshalBinary() ([]byte, error) {
    method unmarshalUint8TLV (line 590) | func (r *Match) unmarshalUint8TLV(field uint8, data []byte) error {
    method unmarshalUint16TLV (line 599) | func (r *Match) unmarshalUint16TLV(field uint8, data []byte) error {
    method unmarshalUint32TLV (line 609) | func (r *Match) unmarshalUint32TLV(field uint8, data []byte) error {
    method unmarshalHardwareAddrTLV (line 619) | func (r *Match) unmarshalHardwareAddrTLV(field uint8, data []byte) err...
    method unmarshalIPNetTLV (line 630) | func (r *Match) unmarshalIPNetTLV(field uint8, hasmask uint8, data []b...
    method unmarshalTLV (line 654) | func (r *Match) unmarshalTLV(data []byte) error {
    method UnmarshalBinary (line 734) | func (r *Match) UnmarshalBinary(data []byte) error {
  function NewMatch (line 43) | func NewMatch() openflow.Match {
  function marshalIPNetTLV (line 466) | func marshalIPNetTLV(field uint8, ip *net.IPNet) ([]byte, error) {
  function marshalHardwareAddrTLV (line 480) | func marshalHardwareAddrTLV(field uint8, mac net.HardwareAddr) ([]byte, ...
  function marshalUint8TLV (line 489) | func marshalUint8TLV(field uint8, v uint8) ([]byte, error) {
  function marshalUint16TLV (line 498) | func marshalUint16TLV(field uint8, v uint16) ([]byte, error) {
  function marshalUint32TLV (line 507) | func marshalUint32TLV(field uint8, v uint32) ([]byte, error) {
  function marshalTLV (line 516) | func marshalTLV(id uint, v interface{}) ([]byte, error) {

FILE: openflow/of13/multipart_description.go
  type DescRequest (line 31) | type DescRequest struct
    method MarshalBinary (line 41) | func (r *DescRequest) MarshalBinary() ([]byte, error) {
  function NewDescRequest (line 35) | func NewDescRequest(xid uint32) openflow.DescRequest {
  type DescReply (line 51) | type DescReply struct
    method Manufacturer (line 60) | func (r DescReply) Manufacturer() string {
    method Hardware (line 64) | func (r DescReply) Hardware() string {
    method Software (line 68) | func (r DescReply) Software() string {
    method Serial (line 72) | func (r DescReply) Serial() string {
    method Description (line 76) | func (r DescReply) Description() string {
    method UnmarshalBinary (line 80) | func (r *DescReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/multipart_flow_stats.go
  type FlowStatsRequest (line 31) | type FlowStatsRequest struct
    method Error (line 45) | func (r *FlowStatsRequest) Error() error {
    method Cookie (line 49) | func (r *FlowStatsRequest) Cookie() uint64 {
    method SetCookie (line 53) | func (r *FlowStatsRequest) SetCookie(cookie uint64) {
    method CookieMask (line 57) | func (r *FlowStatsRequest) CookieMask() uint64 {
    method SetCookieMask (line 61) | func (r *FlowStatsRequest) SetCookieMask(mask uint64) {
    method Match (line 65) | func (r *FlowStatsRequest) Match() openflow.Match {
    method SetMatch (line 69) | func (r *FlowStatsRequest) SetMatch(match openflow.Match) {
    method TableID (line 76) | func (r *FlowStatsRequest) TableID() uint8 {
    method SetTableID (line 81) | func (r *FlowStatsRequest) SetTableID(id uint8) {
    method MarshalBinary (line 85) | func (r *FlowStatsRequest) MarshalBinary() ([]byte, error) {
  function NewFlowStatsRequest (line 39) | func NewFlowStatsRequest(xid uint32) openflow.FlowStatsRequest {

FILE: openflow/of13/multipart_port_description.go
  type PortDescRequest (line 30) | type PortDescRequest struct
    method MarshalBinary (line 40) | func (r *PortDescRequest) MarshalBinary() ([]byte, error) {
  function NewPortDescRequest (line 34) | func NewPortDescRequest(xid uint32) openflow.PortDescRequest {
  type PortDescReply (line 50) | type PortDescReply struct
    method Ports (line 55) | func (r PortDescReply) Ports() []openflow.Port {
    method UnmarshalBinary (line 59) | func (r *PortDescReply) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/multipart_table_features.go
  type TableFeaturesRequest (line 30) | type TableFeaturesRequest struct
    method MarshalBinary (line 40) | func (r *TableFeaturesRequest) MarshalBinary() ([]byte, error) {
  function NewTableFeaturesRequest (line 34) | func NewTableFeaturesRequest(xid uint32) openflow.TableFeaturesRequest {

FILE: openflow/of13/packet_in.go
  type PacketIn (line 30) | type PacketIn struct
    method BufferID (line 41) | func (r PacketIn) BufferID() uint32 {
    method InPort (line 45) | func (r PacketIn) InPort() uint32 {
    method Data (line 49) | func (r PacketIn) Data() []byte {
    method Length (line 53) | func (r PacketIn) Length() uint16 {
    method TableID (line 57) | func (r PacketIn) TableID() uint8 {
    method Reason (line 61) | func (r PacketIn) Reason() uint8 {
    method Cookie (line 65) | func (r PacketIn) Cookie() uint64 {
    method UnmarshalBinary (line 69) | func (r *PacketIn) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/packet_out.go
  type PacketOut (line 30) | type PacketOut struct
    method Error (line 44) | func (r *PacketOut) Error() error {
    method InPort (line 48) | func (r *PacketOut) InPort() openflow.InPort {
    method SetInPort (line 52) | func (r *PacketOut) SetInPort(port openflow.InPort) {
    method Action (line 56) | func (r *PacketOut) Action() openflow.Action {
    method SetAction (line 60) | func (r *PacketOut) SetAction(action openflow.Action) {
    method Data (line 67) | func (r *PacketOut) Data() []byte {
    method SetData (line 71) | func (r *PacketOut) SetData(data []byte) {
    method MarshalBinary (line 78) | func (r *PacketOut) MarshalBinary() ([]byte, error) {
  function NewPacketOut (line 38) | func NewPacketOut(xid uint32) openflow.PacketOut {

FILE: openflow/of13/port.go
  type Port (line 32) | type Port struct
    method Number (line 47) | func (r Port) Number() uint32 {
    method MAC (line 51) | func (r Port) MAC() net.HardwareAddr {
    method Name (line 55) | func (r Port) Name() string {
    method IsPortDown (line 59) | func (r Port) IsPortDown() bool {
    method IsLinkDown (line 67) | func (r Port) IsLinkDown() bool {
    method IsCopper (line 75) | func (r Port) IsCopper() bool {
    method IsFiber (line 79) | func (r Port) IsFiber() bool {
    method IsAutoNego (line 83) | func (r Port) IsAutoNego() bool {
    method Speed (line 87) | func (r *Port) Speed() uint64 {
    method UnmarshalBinary (line 114) | func (r *Port) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/port_status.go
  type PortStatus (line 28) | type PortStatus struct
    method Reason (line 34) | func (r PortStatus) Reason() openflow.PortReason {
    method Port (line 47) | func (r PortStatus) Port() openflow.Port {
    method UnmarshalBinary (line 51) | func (r *PortStatus) UnmarshalBinary(data []byte) error {

FILE: openflow/of13/queue.go
  type QueueGetConfigRequest (line 30) | type QueueGetConfigRequest struct
    method Port (line 41) | func (r *QueueGetConfigRequest) Port() openflow.OutPort {
    method SetPort (line 45) | func (r *QueueGetConfigRequest) SetPort(p openflow.OutPort) {
    method MarshalBinary (line 49) | func (r *QueueGetConfigRequest) MarshalBinary() ([]byte, error) {
  function NewQueueGetConfigRequest (line 35) | func NewQueueGetConfigRequest(xid uint32) openflow.QueueGetConfigRequest {
  type QueueProperty (line 63) | type QueueProperty struct
    method Type (line 75) | func (r *QueueProperty) Type() openflow.PropertyType {
    method Length (line 79) | func (r *QueueProperty) Length() uint16 {
    method Rate (line 83) | func (r *QueueProperty) Rate() (uint16, error) {
    method Experimenter (line 90) | func (r *QueueProperty) Experimenter() (uint32, error) {
    method Data (line 97) | func (r *QueueProperty) Data() []byte {
    method UnmarshalBinary (line 101) | func (r *QueueProperty) UnmarshalBinary(data []byte) error {
  function NewQueueProperty (line 71) | func NewQueueProperty() openflow.QueueProperty {
  type Queue (line 125) | type Queue struct
    method ID (line 132) | func (r *Queue) ID() uint32 {
    method Port (line 136) | func (r *Queue) Port() uint32 {
    method Length (line 140) | func (r *Queue) Length() uint16 {
    method Property (line 144) | func (r *Queue) Property() []openflow.QueueProperty {
    method UnmarshalBinary (line 148) | func (r *Queue) UnmarshalBinary(data []byte) error {
  function NewQueue (line 170) | func NewQueue() openflow.Queue {
  type QueueGetConfigReply (line 174) | type QueueGetConfigReply struct
    method Port (line 180) | func (r *QueueGetConfigReply) Port() uint32 {
    method Queue (line 184) | func (r *QueueGetConfigReply) Queue() []openflow.Queue {
    method UnmarshalBinary (line 188) | func (r *QueueGetConfigReply) UnmarshalBinary(data []byte) error {

FILE: openflow/packet_in.go
  type PacketIn (line 28) | type PacketIn interface

FILE: openflow/packet_out.go
  type PacketOut (line 28) | type PacketOut interface

FILE: openflow/port.go
  constant table (line 31) | table = iota
  constant flood (line 32) | flood
  constant all (line 33) | all
  constant controller (line 34) | controller
  constant inport (line 35) | inport
  constant none (line 36) | none
  type OutPort (line 39) | type OutPort struct
    method SetTable (line 51) | func (r *OutPort) SetTable() {
    method IsTable (line 55) | func (r *OutPort) IsTable() bool {
    method SetFlood (line 59) | func (r *OutPort) SetFlood() {
    method IsFlood (line 63) | func (r *OutPort) IsFlood() bool {
    method SetAll (line 67) | func (r *OutPort) SetAll() {
    method IsAll (line 71) | func (r *OutPort) IsAll() bool {
    method SetController (line 75) | func (r *OutPort) SetController() {
    method IsController (line 79) | func (r *OutPort) IsController() bool {
    method SetInPort (line 83) | func (r *OutPort) SetInPort() {
    method IsInPort (line 87) | func (r *OutPort) IsInPort() bool {
    method SetNone (line 91) | func (r *OutPort) SetNone() {
    method IsNone (line 95) | func (r *OutPort) IsNone() bool {
    method SetValue (line 99) | func (r *OutPort) SetValue(port uint32) {
    method Value (line 104) | func (r *OutPort) Value() uint32 {
    method String (line 108) | func (r OutPort) String() string {
  function NewOutPort (line 45) | func NewOutPort() OutPort {
  type InPort (line 112) | type InPort struct
    method SetValue (line 123) | func (r *InPort) SetValue(port uint32) {
    method SetController (line 128) | func (r *InPort) SetController() {
    method IsController (line 133) | func (r *InPort) IsController() bool {
    method Value (line 137) | func (r *InPort) Value() uint32 {
  function NewInPort (line 117) | func NewInPort() InPort {
  type Port (line 141) | type Port interface

FILE: openflow/port_description.go
  type PortDescRequest (line 28) | type PortDescRequest interface
  type PortDescReply (line 33) | type PortDescReply interface

FILE: openflow/port_status.go
  type PortReason (line 28) | type PortReason
  constant PortAdded (line 31) | PortAdded PortReason = iota
  constant PortDeleted (line 32) | PortDeleted
  constant PortModified (line 33) | PortModified
  type PortStatus (line 36) | type PortStatus interface

FILE: openflow/queue.go
  type PropertyType (line 28) | type PropertyType
  constant OFPQT_NONE (line 31) | OFPQT_NONE PropertyType = iota
  constant OFPQT_MIN_RATE (line 32) | OFPQT_MIN_RATE
  constant OFPQT_MAX_RATE (line 33) | OFPQT_MAX_RATE
  constant OFPQT_EXPERIMENTER (line 34) | OFPQT_EXPERIMENTER = 0xffff
  type Queue (line 37) | type Queue interface
  type QueueProperty (line 45) | type QueueProperty interface
  type QueueGetConfigRequest (line 54) | type QueueGetConfigRequest interface
  type QueueGetConfigReply (line 61) | type QueueGetConfigReply interface

FILE: openflow/table_features.go
  type TableFeaturesRequest (line 28) | type TableFeaturesRequest interface

FILE: openflow/transceiver/stream.go
  type Stream (line 33) | type Stream struct
    method RemoteAddr (line 85) | func (r *Stream) RemoteAddr() net.Addr {
    method SetReadTimeout (line 99) | func (r *Stream) SetReadTimeout(t time.Duration) {
    method GetReadTimeout (line 107) | func (r *Stream) GetReadTimeout() time.Duration {
    method SetWriteTimeout (line 115) | func (r *Stream) SetWriteTimeout(t time.Duration) {
    method GetWriteTimeout (line 123) | func (r *Stream) GetWriteTimeout() time.Duration {
    method Read (line 131) | func (r *Stream) Read(p []byte) (n int, err error) {
    method setReadDeadline (line 146) | func (r *Stream) setReadDeadline() {
    method Peek (line 162) | func (r *Stream) Peek(n int) ([]byte, error) {
    method ReadN (line 186) | func (r *Stream) ReadN(n int) (p []byte, err error) {
    method LastRead (line 211) | func (r *Stream) LastRead() time.Time {
    method Write (line 219) | func (r *Stream) Write(p []byte) (n int, err error) {
    method setWriteDeadline (line 234) | func (r *Stream) setWriteDeadline() {
    method LastWrite (line 250) | func (r *Stream) LastWrite() time.Time {
    method Close (line 258) | func (r *Stream) Close() error {
  type deadline (line 60) | type deadline interface
  function NewStream (line 66) | func NewStream(channel io.ReadWriteCloser, bufSize int) *Stream {
  type dummyAddr (line 75) | type dummyAddr struct
    method Network (line 77) | func (r dummyAddr) Network() string {
    method String (line 81) | func (r dummyAddr) String() string {

FILE: openflow/transceiver/transceiver.go
  constant maxIdleTime (line 45) | maxIdleTime = 10 * time.Second
  constant readTimeout (line 47) | readTimeout  = 1 * time.Second
  constant writeTimeout (line 48) | writeTimeout = readTimeout * 2
  type Writer (line 51) | type Writer interface
  type WriteCloser (line 55) | type WriteCloser interface
  type Transceiver (line 60) | type Transceiver struct
    method Version (line 96) | func (r *Transceiver) Version() (negotiated bool, version uint8) {
    method sendEchoRequest (line 117) | func (r *Transceiver) sendEchoRequest() error {
    method Run (line 141) | func (r *Transceiver) Run(ctx context.Context) error {
    method negotiate (line 186) | func (r *Transceiver) negotiate(ctx context.Context, reader <-chan []b...
    method runReader (line 217) | func (r *Transceiver) runReader(ctx context.Context) <-chan []byte {
    method readPacket (line 284) | func (r *Transceiver) readPacket() ([]byte, error) {
    method Write (line 302) | func (r *Transceiver) Write(msg encoding.BinaryMarshaler) error {
    method handleEcho (line 315) | func (r *Transceiver) handleEcho(packet []byte) (ok bool, err error) {
    method handleOF10Echo (line 326) | func (r *Transceiver) handleOF10Echo(packet []byte) (ok bool, err erro...
    method handleOF13Echo (line 338) | func (r *Transceiver) handleOF13Echo(packet []byte) (handled bool, err...
    method dispatch (line 350) | func (r *Transceiver) dispatch(packet []byte) error {
    method handleOF10Message (line 365) | func (r *Transceiver) handleOF10Message(packet []byte) error {
    method handleOF13Message (line 397) | func (r *Transceiver) handleOF13Message(packet []byte) error {
    method handleEchoRequest (line 431) | func (r *Transceiver) handleEchoRequest(packet []byte) error {
    method handleEchoReply (line 458) | func (r *Transceiver) handleEchoReply(packet []byte) error {
    method handleHello (line 488) | func (r *Transceiver) handleHello(packet []byte) error {
    method handleError (line 500) | func (r *Transceiver) handleError(packet []byte) error {
    method handleFeaturesReply (line 512) | func (r *Transceiver) handleFeaturesReply(packet []byte) error {
    method handleGetConfigReply (line 524) | func (r *Transceiver) handleGetConfigReply(packet []byte) error {
    method handleDescReply (line 536) | func (r *Transceiver) handleDescReply(packet []byte) error {
    method handlePortDescReply (line 548) | func (r *Transceiver) handlePortDescReply(packet []byte) error {
    method handlePortStatus (line 560) | func (r *Transceiver) handlePortStatus(packet []byte) error {
    method handleFlowRemoved (line 572) | func (r *Transceiver) handleFlowRemoved(packet []byte) error {
    method handlePacketIn (line 584) | func (r *Transceiver) handlePacketIn(packet []byte) error {
    method handleBarrierReply (line 596) | func (r *Transceiver) handleBarrierReply(packet []byte) error {
    method Close (line 608) | func (r *Transceiver) Close() error {
  type Handler (line 69) | type Handler interface
  function NewTransceiver (line 82) | func NewTransceiver(stream *Stream, handler Handler) *Transceiver {
  function isTimeout (line 105) | func isTimeout(err error) bool {
  function isTemporaryErr (line 277) | func isTemporaryErr(err error) bool {

FILE: protocol/arp.go
  type ARP (line 31) | type ARP struct
    method String (line 71) | func (r ARP) String() string {
    method MarshalBinary (line 75) | func (r ARP) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 102) | func (r *ARP) UnmarshalBinary(data []byte) error {
  function NewARPRequest (line 43) | func NewARPRequest(sha, tha net.HardwareAddr, spa, tpa net.IP) *ARP {
  function NewARPReply (line 57) | func NewARPReply(sha, tha net.HardwareAddr, spa, tpa net.IP) *ARP {

FILE: protocol/checksum.go
  function aroundCarry (line 28) | func aroundCarry(sum uint32) uint32 {
  function calculateChecksum (line 42) | func calculateChecksum(header []byte) uint16 {

FILE: protocol/dhcp.go
  type DHCP (line 36) | type DHCP struct
    method MarshalBinary (line 61) | func (r *DHCP) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 115) | func (r *DHCP) UnmarshalBinary(data []byte) (err error) {
    method Option (line 179) | func (r *DHCP) Option(code uint8) (opt DHCPOption, ok bool) {
  type DHCPOpcode (line 54) | type DHCPOpcode
  constant DHCPOpcodeRequest (line 57) | DHCPOpcodeRequest DHCPOpcode = 1
  constant DHCPOpcodeReply (line 58) | DHCPOpcodeReply   DHCPOpcode = 2
  function unmarshalCString (line 188) | func unmarshalCString(data []byte) string {
  function marshalIP (line 202) | func marshalIP(v []byte, addr net.IP) error {
  function marshalMAC (line 220) | func marshalMAC(v []byte, mac net.HardwareAddr) error {
  function unmarshalMAC (line 237) | func unmarshalMAC(data []byte) (net.HardwareAddr, error) {
  type DHCPOption (line 249) | type DHCPOption struct
    method MarshalBinary (line 254) | func (r *DHCPOption) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 268) | func (r *DHCPOption) UnmarshalBinary(data []byte) error {

FILE: protocol/dhcp_test.go
  function TestCodec (line 36) | func TestCodec(t *testing.T) {

FILE: protocol/ethernet.go
  type Ethernet (line 30) | type Ethernet struct
    method MarshalBinary (line 36) | func (r Ethernet) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 55) | func (r *Ethernet) UnmarshalBinary(data []byte) error {

FILE: protocol/icmp.go
  type ICMP (line 29) | type ICMP struct
  type ICMPEcho (line 35) | type ICMPEcho struct
    method MarshalBinary (line 61) | func (r ICMPEcho) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 78) | func (r *ICMPEcho) UnmarshalBinary(data []byte) error {
  function NewICMPEchoRequest (line 42) | func NewICMPEchoRequest(id, seq uint16, payload []byte) *ICMPEcho {
  function NewICMPEchoReply (line 53) | func NewICMPEchoReply(id, seq uint16, payload []byte) *ICMPEcho {

FILE: protocol/ipv4.go
  type IPv4 (line 32) | type IPv4 struct
    method MarshalBinary (line 80) | func (r IPv4) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 114) | func (r *IPv4) UnmarshalBinary(data []byte) error {
  function NewIPv4 (line 49) | func NewIPv4(src, dst net.IP, protocol uint8, payload []byte) *IPv4 {

FILE: protocol/lldp.go
  type LLDPChassisID (line 29) | type LLDPChassisID struct
  type LLDPPortID (line 34) | type LLDPPortID struct
  type LLDP (line 39) | type LLDP struct
    method marshalChassisID (line 45) | func (r *LLDP) marshalChassisID() ([]byte, error) {
    method marshalPortID (line 65) | func (r *LLDP) marshalPortID() ([]byte, error) {
    method marshalTTL (line 85) | func (r *LLDP) marshalTTL() ([]byte, error) {
    method MarshalBinary (line 97) | func (r *LLDP) MarshalBinary() ([]byte, error) {
    method unmarshalChassisID (line 124) | func (r *LLDP) unmarshalChassisID(data []byte) (n int, err error) {
    method unmarshalPortID (line 147) | func (r *LLDP) unmarshalPortID(data []byte) (n int, err error) {
    method unmarshalTTL (line 170) | func (r *LLDP) unmarshalTTL(data []byte) (n int, err error) {
    method UnmarshalBinary (line 190) | func (r *LLDP) UnmarshalBinary(data []byte) error {

FILE: protocol/tcp.go
  type TCP (line 31) | type TCP struct
    method SetPseudoHeader (line 47) | func (r *TCP) SetPseudoHeader(src, dst net.IP) {
    method MarshalBinary (line 52) | func (r TCP) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 98) | func (r *TCP) UnmarshalBinary(data []byte) error {

FILE: protocol/udp.go
  type UDP (line 31) | type UDP struct
    method SetPseudoHeader (line 42) | func (r *UDP) SetPseudoHeader(src, dst net.IP) {
    method MarshalBinary (line 47) | func (r UDP) MarshalBinary() ([]byte, error) {
    method UnmarshalBinary (line 88) | func (r *UDP) UnmarshalBinary(data []byte) error {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/access_log_apache.go
  type AccessLogFormat (line 41) | type AccessLogFormat
  constant CommonLogFormat (line 45) | CommonLogFormat = "%h %l %u %t \"%r\" %s %b"
  constant CombinedLogFormat (line 48) | CombinedLogFormat = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-A...
  constant DefaultLogFormat (line 51) | DefaultLogFormat = "%t %S\033[0m \033[36;1m%Dμs\033[0m \"%r\" \033[1;30m...
  type AccessLogApacheMiddleware (line 57) | type AccessLogApacheMiddleware struct
    method MiddlewareFunc (line 71) | func (mw *AccessLogApacheMiddleware) MiddlewareFunc(h HandlerFunc) Han...
    method convertFormat (line 117) | func (mw *AccessLogApacheMiddleware) convertFormat() {
    method executeTextTemplate (line 158) | func (mw *AccessLogApacheMiddleware) executeTextTemplate(util *accessL...
  type accessLogUtil (line 169) | type accessLogUtil struct
    method RemoteUser (line 175) | func (u *accessLogUtil) RemoteUser() string {
    method ApacheQueryString (line 183) | func (u *accessLogUtil) ApacheQueryString() string {
    method StartTime (line 191) | func (u *accessLogUtil) StartTime() *time.Time {
    method ApacheRemoteAddr (line 199) | func (u *accessLogUtil) ApacheRemoteAddr() string {
    method StatusCode (line 210) | func (u *accessLogUtil) StatusCode() int {
    method ResponseTime (line 218) | func (u *accessLogUtil) ResponseTime() *time.Duration {
    method Pid (line 226) | func (u *accessLogUtil) Pid() int {
    method BytesWritten (line 231) | func (u *accessLogUtil) BytesWritten() int64 {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/access_log_json.go
  type AccessLogJsonMiddleware (line 13) | type AccessLogJsonMiddleware struct
    method MiddlewareFunc (line 21) | func (mw *AccessLogJsonMiddleware) MiddlewareFunc(h HandlerFunc) Handl...
  type AccessLogJsonRecord (line 39) | type AccessLogJsonRecord struct
    method asJson (line 82) | func (r *AccessLogJsonRecord) asJson() []byte {
  function makeAccessLogJsonRecord (line 49) | func makeAccessLogJsonRecord(r *Request) *AccessLogJsonRecord {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/api.go
  type Api (line 8) | type Api struct
    method Use (line 23) | func (api *Api) Use(middlewares ...Middleware) {
    method SetApp (line 28) | func (api *Api) SetApp(app App) {
    method MakeHandler (line 35) | func (api *Api) MakeHandler() http.Handler {
  function NewApi (line 14) | func NewApi() *Api {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/auth_basic.go
  type AuthBasicMiddleware (line 14) | type AuthBasicMiddleware struct
    method MiddlewareFunc (line 30) | func (mw *AuthBasicMiddleware) MiddlewareFunc(handler HandlerFunc) Han...
    method unauthorized (line 77) | func (mw *AuthBasicMiddleware) unauthorized(writer ResponseWriter) {
    method decodeBasicAuthHeader (line 82) | func (mw *AuthBasicMiddleware) decodeBasicAuthHeader(header string) (u...

FILE: vendor/github.com/ant0ine/go-json-rest/rest/content_type_checker.go
  type ContentTypeCheckerMiddleware (line 13) | type ContentTypeCheckerMiddleware struct
    method MiddlewareFunc (line 16) | func (mw *ContentTypeCheckerMiddleware) MiddlewareFunc(handler Handler...

FILE: vendor/github.com/ant0ine/go-json-rest/rest/cors.go
  type CorsMiddleware (line 16) | type CorsMiddleware struct
    method MiddlewareFunc (line 53) | func (mw *CorsMiddleware) MiddlewareFunc(handler HandlerFunc) HandlerF...

FILE: vendor/github.com/ant0ine/go-json-rest/rest/gzip.go
  type GzipMiddleware (line 15) | type GzipMiddleware struct
    method MiddlewareFunc (line 18) | func (mw *GzipMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
  type gzipResponseWriter (line 43) | type gzipResponseWriter struct
    method WriteHeader (line 51) | func (w *gzipResponseWriter) WriteHeader(code int) {
    method WriteJson (line 66) | func (w *gzipResponseWriter) WriteJson(v interface{}) error {
    method Flush (line 80) | func (w *gzipResponseWriter) Flush() {
    method CloseNotify (line 90) | func (w *gzipResponseWriter) CloseNotify() <-chan bool {
    method Hijack (line 96) | func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, er...
    method Write (line 103) | func (w *gzipResponseWriter) Write(b []byte) (int, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/if.go
  type IfMiddleware (line 9) | type IfMiddleware struct
    method MiddlewareFunc (line 24) | func (mw *IfMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/json_indent.go
  type JsonIndentMiddleware (line 15) | type JsonIndentMiddleware struct
    method MiddlewareFunc (line 25) | func (mw *JsonIndentMiddleware) MiddlewareFunc(handler HandlerFunc) Ha...
  type jsonIndentResponseWriter (line 46) | type jsonIndentResponseWriter struct
    method EncodeJson (line 54) | func (w *jsonIndentResponseWriter) EncodeJson(v interface{}) ([]byte, ...
    method WriteJson (line 64) | func (w *jsonIndentResponseWriter) WriteJson(v interface{}) error {
    method WriteHeader (line 77) | func (w *jsonIndentResponseWriter) WriteHeader(code int) {
    method Flush (line 84) | func (w *jsonIndentResponseWriter) Flush() {
    method CloseNotify (line 94) | func (w *jsonIndentResponseWriter) CloseNotify() <-chan bool {
    method Hijack (line 100) | func (w *jsonIndentResponseWriter) Hijack() (net.Conn, *bufio.ReadWrit...
    method Write (line 107) | func (w *jsonIndentResponseWriter) Write(b []byte) (int, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/jsonp.go
  type JsonpMiddleware (line 11) | type JsonpMiddleware struct
    method MiddlewareFunc (line 20) | func (mw *JsonpMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
  type jsonpResponseWriter (line 52) | type jsonpResponseWriter struct
    method WriteHeader (line 59) | func (w *jsonpResponseWriter) WriteHeader(code int) {
    method WriteJson (line 68) | func (w *jsonpResponseWriter) WriteJson(v interface{}) error {
    method Flush (line 84) | func (w *jsonpResponseWriter) Flush() {
    method CloseNotify (line 94) | func (w *jsonpResponseWriter) CloseNotify() <-chan bool {
    method Hijack (line 100) | func (w *jsonpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, e...
    method Write (line 107) | func (w *jsonpResponseWriter) Write(b []byte) (int, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/middleware.go
  type HandlerFunc (line 8) | type HandlerFunc
  type App (line 12) | type App interface
  type AppSimple (line 18) | type AppSimple
    method AppFunc (line 21) | func (as AppSimple) AppFunc() HandlerFunc {
  type Middleware (line 27) | type Middleware interface
  type MiddlewareSimple (line 33) | type MiddlewareSimple
    method MiddlewareFunc (line 36) | func (ms MiddlewareSimple) MiddlewareFunc(handler HandlerFunc) Handler...
  function WrapMiddlewares (line 43) | func WrapMiddlewares(middlewares []Middleware, handler HandlerFunc) Hand...
  function adapterFunc (line 53) | func adapterFunc(handler HandlerFunc) http.HandlerFunc {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/powered_by.go
  constant xPoweredByDefault (line 3) | xPoweredByDefault = "go-json-rest"
  type PoweredByMiddleware (line 6) | type PoweredByMiddleware struct
    method MiddlewareFunc (line 14) | func (mw *PoweredByMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFu...

FILE: vendor/github.com/ant0ine/go-json-rest/rest/recorder.go
  type RecorderMiddleware (line 13) | type RecorderMiddleware struct
    method MiddlewareFunc (line 16) | func (mw *RecorderMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
  type recorderResponseWriter (line 37) | type recorderResponseWriter struct
    method WriteHeader (line 45) | func (w *recorderResponseWriter) WriteHeader(code int) {
    method WriteJson (line 52) | func (w *recorderResponseWriter) WriteJson(v interface{}) error {
    method Flush (line 66) | func (w *recorderResponseWriter) Flush() {
    method CloseNotify (line 76) | func (w *recorderResponseWriter) CloseNotify() <-chan bool {
    method Hijack (line 82) | func (w *recorderResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter...
    method Write (line 89) | func (w *recorderResponseWriter) Write(b []byte) (int, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/recover.go
  type RecoverMiddleware (line 14) | type RecoverMiddleware struct
    method MiddlewareFunc (line 29) | func (mw *RecoverMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
    method logError (line 61) | func (mw *RecoverMiddleware) logError(message string) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/request.go
  type Request (line 18) | type Request struct
    method PathParam (line 29) | func (r *Request) PathParam(name string) string {
    method DecodeJsonPayload (line 34) | func (r *Request) DecodeJsonPayload(v interface{}) error {
    method BaseUrl (line 52) | func (r *Request) BaseUrl() *url.URL {
    method UrlFor (line 71) | func (r *Request) UrlFor(path string, queryParams map[string][]string)...
    method GetCorsInfo (line 101) | func (r *Request) GetCorsInfo() *CorsInfo {
  type CorsInfo (line 87) | type CorsInfo struct

FILE: vendor/github.com/ant0ine/go-json-rest/rest/response.go
  type ResponseWriter (line 13) | type ResponseWriter interface
  function Error (line 40) | func Error(w ResponseWriter, error string, code int) {
  function NotFound (line 51) | func NotFound(w ResponseWriter, r *Request) {
  type responseWriter (line 62) | type responseWriter struct
    method WriteHeader (line 67) | func (w *responseWriter) WriteHeader(code int) {
    method EncodeJson (line 79) | func (w *responseWriter) EncodeJson(v interface{}) ([]byte, error) {
    method WriteJson (line 88) | func (w *responseWriter) WriteJson(v interface{}) error {
    method Write (line 101) | func (w *responseWriter) Write(b []byte) (int, error) {
    method Flush (line 109) | func (w *responseWriter) Flush() {
    method CloseNotify (line 118) | func (w *responseWriter) CloseNotify() <-chan bool {
    method Hijack (line 124) | func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/route.go
  type Route (line 9) | type Route struct
    method MakePath (line 28) | func (route *Route) MakePath(pathParams map[string]string) string {
  function Head (line 42) | func Head(pathExp string, handlerFunc HandlerFunc) *Route {
  function Get (line 52) | func Get(pathExp string, handlerFunc HandlerFunc) *Route {
  function Post (line 62) | func Post(pathExp string, handlerFunc HandlerFunc) *Route {
  function Put (line 72) | func Put(pathExp string, handlerFunc HandlerFunc) *Route {
  function Patch (line 82) | func Patch(pathExp string, handlerFunc HandlerFunc) *Route {
  function Delete (line 91) | func Delete(pathExp string, handlerFunc HandlerFunc) *Route {
  function Options (line 101) | func Options(pathExp string, handlerFunc HandlerFunc) *Route {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/router.go
  type router (line 11) | type router struct
    method AppFunc (line 33) | func (rt *router) AppFunc() HandlerFunc {
    method start (line 107) | func (rt *router) start() error {
    method ofFirstDefinedRoute (line 142) | func (rt *router) ofFirstDefinedRoute(matches []*trie.Match) *trie.Mat...
    method findRouteFromURL (line 159) | func (rt *router) findRouteFromURL(httpMethod string, urlObj *url.URL)...
    method findRoute (line 184) | func (rt *router) findRoute(httpMethod, urlStr string) (*Route, map[st...
  function MakeRouter (line 21) | func MakeRouter(routes ...*Route) (App, error) {
  function escapedPath (line 61) | func escapedPath(urlObj *url.URL) string {
  function escapedPathExp (line 73) | func escapedPathExp(pathExp string) (string, error) {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/status.go
  type StatusMiddleware (line 14) | type StatusMiddleware struct
    method MiddlewareFunc (line 23) | func (mw *StatusMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {
    method GetStatus (line 91) | func (mw *StatusMiddleware) GetStatus() *Status {
  type Status (line 75) | type Status struct

FILE: vendor/github.com/ant0ine/go-json-rest/rest/timer.go
  type TimerMiddleware (line 10) | type TimerMiddleware struct
    method MiddlewareFunc (line 13) | func (mw *TimerMiddleware) MiddlewareFunc(h HandlerFunc) HandlerFunc {

FILE: vendor/github.com/ant0ine/go-json-rest/rest/trie/impl.go
  function splitParam (line 17) | func splitParam(remaining string) (string, string) {
  function splitRelaxed (line 25) | func splitRelaxed(remaining string) (string, string) {
  type node (line 33) | type node struct
    method addRoute (line 49) | func (n *node) addRoute(httpMethod, pathExp string, route interface{},...
    method compress (line 165) | func (n *node) compress() {
    method printDebug (line 217) | func (n *node) printDebug(level int) {
    method find (line 292) | func (n *node) find(httpMethod, path string, context *findContext) {
  function printFPadding (line 209) | func printFPadding(padding int, format string, a ...interface{}) {
  type paramMatch (line 243) | type paramMatch struct
  type findContext (line 248) | type findContext struct
    method pushParams (line 259) | func (fc *findContext) pushParams(name, value string) {
    method popParams (line 266) | func (fc *findContext) popParams() {
    method paramsAsMap (line 270) | func (fc *findContext) paramsAsMap() map[string]string {
  function newFindContext (line 253) | func newFindContext() *findContext {
  type Match (line 285) | type Match struct
  type Trie (line 337) | type Trie struct
    method AddRoute (line 349) | func (t *Trie) AddRoute(httpMethod, pathExp string, route interface{})...
    method Compress (line 354) | func (t *Trie) Compress() {
    method printDebug (line 359) | func (t *Trie) printDebug() {
    method FindRoutes (line 366) | func (t *Trie) FindRoutes(httpMethod, path string) []*Match {
    method FindRoutesAndPathMatched (line 387) | func (t *Trie) FindRoutesAndPathMatched(httpMethod, path string) ([]*M...
    method FindRoutesForPath (line 409) | func (t *Trie) FindRoutesForPath(path string) []*Match {
  function New (line 342) | func New() *Trie {

FILE: vendor/github.com/boombuler/barcode/barcode.go
  constant TypeAztec (line 6) | TypeAztec           = "Aztec"
  constant TypeCodabar (line 7) | TypeCodabar         = "Codabar"
  constant TypeCode128 (line 8) | TypeCode128         = "Code 128"
  constant TypeCode39 (line 9) | TypeCode39          = "Code 39"
  constant TypeCode93 (line 10) | TypeCode93          = "Code 93"
  constant TypeDataMatrix (line 11) | TypeDataMatrix      = "DataMatrix"
  constant TypeEAN8 (line 12) | TypeEAN8            = "EAN 8"
  constant TypeEAN13 (line 13) | TypeEAN13           = "EAN 13"
  constant TypePDF (line 14) | TypePDF             = "PDF417"
  constant TypeQR (line 15) | TypeQR              = "QR Code"
  constant Type2of5 (line 16) | Type2of5            = "2 of 5"
  constant Type2of5Interleaved (line 17) | Type2of5Interleaved = "2 of 5 (interleaved)"
  type Metadata (line 21) | type Metadata struct
  type Barcode (line 29) | type Barcode interface
  type BarcodeIntCS (line 39) | type BarcodeIntCS interface

FILE: vendor/github.com/boombuler/barcode/qr/alphanumeric.go
  constant charSet (line 11) | charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
  function stringToAlphaIdx (line 13) | func stringToAlphaIdx(content string) <-chan int {
  function encodeAlphaNumeric (line 29) | func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*util...

FILE: vendor/github.com/boombuler/barcode/qr/automatic.go
  function encodeAuto (line 9) | func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitLis...

FILE: vendor/github.com/boombuler/barcode/qr/blocks.go
  type block (line 3) | type block struct
  type blockList (line 7) | type blockList
    method interleave (line 35) | func (bl blockList) interleave(vi *versionInfo) []byte {
  function splitToBlocks (line 9) | func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {

FILE: vendor/github.com/boombuler/barcode/qr/encoder.go
  type encodeFn (line 11) | type encodeFn
  type Encoding (line 14) | type Encoding
    method getEncoder (line 29) | func (e Encoding) getEncoder() encodeFn {
    method String (line 43) | func (e Encoding) String() string {
  constant Auto (line 18) | Auto Encoding = iota
  constant Numeric (line 20) | Numeric
  constant AlphaNumeric (line 22) | AlphaNumeric
  constant Unicode (line 24) | Unicode
  constant unknownEncoding (line 26) | unknownEncoding
  function Encode (line 58) | func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (...
  function render (line 71) | func render(data []byte, vi *versionInfo) *qrcode {
  function setMasked (line 138) | func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) {
  function iterateModules (line 167) | func iterateModules(occupied *qrcode) <-chan image.Point {
  function drawFinderPatterns (line 222) | func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) {
  function drawAlignmentPatterns (line 240) | func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(i...
  function drawFormatInfo (line 304) | func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bo...
  function drawVersionInfo (line 386) | func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) {
  function addPaddingAndTerminator (line 400) | func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) {

FILE: vendor/github.com/boombuler/barcode/qr/errorcorrection.go
  type errorCorrection (line 7) | type errorCorrection struct
    method calcECC (line 18) | func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte {
  function newErrorCorrection (line 13) | func newErrorCorrection() *errorCorrection {

FILE: vendor/github.com/boombuler/barcode/qr/numeric.go
  function encodeNumeric (line 11) | func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.Bit...

FILE: vendor/github.com/boombuler/barcode/qr/qrcode.go
  type qrcode (line 12) | type qrcode struct
    method Content (line 18) | func (qr *qrcode) Content() string {
    method Metadata (line 22) | func (qr *qrcode) Metadata() barcode.Metadata {
    method ColorModel (line 26) | func (qr *qrcode) ColorModel() color.Model {
    method Bounds (line 30) | func (qr *qrcode) Bounds() image.Rectangle {
    method At (line 34) | func (qr *qrcode) At(x, y int) color.Color {
    method Get (line 41) | func (qr *qrcode) Get(x, y int) bool {
    method Set (line 45) | func (qr *qrcode) Set(x, y int, val bool) {
    method calcPenalty (line 49) | func (qr *qrcode) calcPenalty() uint {
    method calcPenaltyRule1 (line 53) | func (qr *qrcode) calcPenaltyRule1() uint {
    method calcPenaltyRule2 (line 94) | func (qr *qrcode) calcPenaltyRule2() uint {
    method calcPenaltyRule3 (line 107) | func (qr *qrcode) calcPenaltyRule3() uint {
    method calcPenaltyRule4 (line 147) | func (qr *qrcode) calcPenaltyRule4() uint {
  function newBarcode (line 161) | func newBarcode(dim int) *qrcode {

FILE: vendor/github.com/boombuler/barcode/qr/unicode.go
  function encodeUnicode (line 9) | func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.Bit...

FILE: vendor/github.com/boombuler/barcode/qr/versioninfo.go
  type ErrorCorrectionLevel (line 6) | type ErrorCorrectionLevel
    method String (line 19) | func (ecl ErrorCorrectionLevel) String() string {
  constant L (line 10) | L ErrorCorrectionLevel = iota
  constant M (line 12) | M
  constant Q (line 14) | Q
  constant H (line 16) | H
  type encodingMode (line 33) | type encodingMode
  constant numericMode (line 36) | numericMode      encodingMode = 1
  constant alphaNumericMode (line 37) | alphaNumericMode encodingMode = 2
  constant byteMode (line 38) | byteMode         encodingMode = 4
  constant kanjiMode (line 39) | kanjiMode        encodingMode = 8
  type versionInfo (line 42) | type versionInfo struct
    method totalDataBytes (line 215) | func (vi *versionInfo) totalDataBytes() int {
    method charCountBits (line 221) | func (vi *versionInfo) charCountBits(m encodingMode) byte {
    method modulWidth (line 257) | func (vi *versionInfo) modulWidth() int {
    method alignmentPatternPlacements (line 261) | func (vi *versionInfo) alignmentPatternPlacements() []int {
  function findSmallestVersionInfo (line 300) | func findSmallestVersionInfo(ecl ErrorCorrectionLevel, mode encodingMode...

FILE: vendor/github.com/boombuler/barcode/scaledbarcode.go
  type wrapFunc (line 11) | type wrapFunc
  type scaledBarcode (line 13) | type scaledBarcode struct
    method Content (line 23) | func (bc *scaledBarcode) Content() string {
    method Metadata (line 27) | func (bc *scaledBarcode) Metadata() Metadata {
    method ColorModel (line 31) | func (bc *scaledBarcode) ColorModel() color.Model {
    method Bounds (line 35) | func (bc *scaledBarcode) Bounds() image.Rectangle {
    method At (line 39) | func (bc *scaledBarcode) At(x, y int) color.Color {
  type intCSscaledBC (line 19) | type intCSscaledBC struct
    method CheckSum (line 43) | func (bc *intCSscaledBC) CheckSum() int {
  function Scale (line 51) | func Scale(bc Barcode, width, height int) (Barcode, error) {
  function newScaledBC (line 62) | func newScaledBC(wrapped Barcode, wrapperFunc wrapFunc, rect image.Recta...
  function scale2DCode (line 75) | func scale2DCode(bc Barcode, width, height int) (Barcode, error) {
  function scale1DCode (line 107) | func scale1DCode(bc Barcode, width, height int) (Barcode, error) {

FILE: vendor/github.com/boombuler/barcode/utils/base1dcode.go
  type base1DCode (line 11) | type base1DCode struct
    method Content (line 22) | func (c *base1DCode) Content() string {
    method Metadata (line 26) | func (c *base1DCode) Metadata() barcode.Metadata {
    method ColorModel (line 30) | func (c *base1DCode) ColorModel() color.Model {
    method Bounds (line 34) | func (c *base1DCode) Bounds() image.Rectangle {
    method At (line 38) | func (c *base1DCode) At(x, y int) color.Color {
  type base1DCodeIntCS (line 17) | type base1DCodeIntCS struct
    method CheckSum (line 45) | func (c *base1DCodeIntCS) CheckSum() int {
  function New1DCodeIntCheckSum (line 50) | func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, check...
  function New1DCode (line 55) | func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode {

FILE: vendor/github.com/boombuler/barcode/utils/bitlist.go
  type BitList (line 4) | type BitList struct
    method Len (line 23) | func (bl *BitList) Len() int {
    method grow (line 27) | func (bl *BitList) grow() {
    method AddBit (line 41) | func (bl *BitList) AddBit(bits ...bool) {
    method SetBit (line 53) | func (bl *BitList) SetBit(index int, value bool) {
    method GetBit (line 64) | func (bl *BitList) GetBit(index int) bool {
    method AddByte (line 71) | func (bl *BitList) AddByte(b byte) {
    method AddBits (line 78) | func (bl *BitList) AddBits(b int, count byte) {
    method GetBytes (line 85) | func (bl *BitList) GetBytes() []byte {
    method IterateBytes (line 99) | func (bl *BitList) IterateBytes() <-chan byte {
  function NewBitList (line 11) | func NewBitList(capacity int) *BitList {

FILE: vendor/github.com/boombuler/barcode/utils/galoisfield.go
  type GaloisField (line 4) | type GaloisField struct
    method Zero (line 36) | func (gf *GaloisField) Zero() *GFPoly {
    method AddOrSub (line 41) | func (gf *GaloisField) AddOrSub(a, b int) int {
    method Multiply (line 46) | func (gf *GaloisField) Multiply(a, b int) int {
    method Divide (line 54) | func (gf *GaloisField) Divide(a, b int) int {
    method Invers (line 63) | func (gf *GaloisField) Invers(num int) int {
  function NewGaloisField (line 12) | func NewGaloisField(pp, fieldSize, b int) *GaloisField {

FILE: vendor/github.com/boombuler/barcode/utils/gfpoly.go
  type GFPoly (line 3) | type GFPoly struct
    method Degree (line 8) | func (gp *GFPoly) Degree() int {
    method Zero (line 12) | func (gp *GFPoly) Zero() bool {
    method GetCoefficient (line 17) | func (gp *GFPoly) GetCoefficient(degree int) int {
    method AddOrSubstract (line 21) | func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly {
    method MultByMonominal (line 41) | func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly {
    method Multiply (line 53) | func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly {
    method Divide (line 72) | func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *...
  function NewMonominalPoly (line 89) | func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly {
  function NewGFPoly (line 98) | func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly {

FILE: vendor/github.com/boombuler/barcode/utils/reedsolomon.go
  type ReedSolomonEncoder (line 7) | type ReedSolomonEncoder struct
    method getPolynomial (line 19) | func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly {
    method Encode (line 34) | func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int {
  function NewReedSolomonEncoder (line 13) | func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder {

FILE: vendor/github.com/boombuler/barcode/utils/runeint.go
  function RuneToInt (line 5) | func RuneToInt(r rune) int {
  function IntToRune (line 14) | func IntToRune(i int) rune {

FILE: vendor/github.com/davecgh/go-spew/spew/bypass.go
  constant UnsafeDisabled (line 33) | UnsafeDisabled = false
  constant ptrSize (line 36) | ptrSize = unsafe.Sizeof((*byte)(nil))
  type flag (line 39) | type flag
  constant flagKindMask (line 54) | flagKindMask = flag(0x1f)
  function flagField (line 80) | func flagField(v *reflect.Value) *flag {
  function unsafeReflectValue (line 93) | func unsafeReflectValue(v reflect.Value) reflect.Value {
  function init (line 105) | func init() {

FILE: vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
  constant UnsafeDisabled (line 28) | UnsafeDisabled = true
  function unsafeReflectValue (line 36) | func unsafeReflectValue(v reflect.Value) reflect.Value {

FILE: vendor/github.com/davecgh/go-spew/spew/common.go
  function catchPanic (line 72) | func catchPanic(w io.Writer, v reflect.Value) {
  function handleMethods (line 85) | func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handl...
  function printBool (line 144) | func printBool(w io.Writer, val bool) {
  function printInt (line 153) | func printInt(w io.Writer, val int64, base int) {
  function printUint (line 158) | func printUint(w io.Writer, val uint64, base int) {
  function printFloat (line 164) | func printFloat(w io.Writer, val float64, precision int) {
  function printComplex (line 170) | func printComplex(w io.Writer, c complex128, floatPrecision int) {
  function printHexPtr (line 185) | func printHexPtr(w io.Writer, p uintptr) {
  type valuesSorter (line 219) | type valuesSorter struct
    method Len (line 279) | func (s *valuesSorter) Len() int {
    method Swap (line 285) | func (s *valuesSorter) Swap(i, j int) {
    method Less (line 326) | func (s *valuesSorter) Less(i, j int) bool {
  function newValuesSorter (line 228) | func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Inter...
  function canSortSimply (line 256) | func canSortSimply(kind reflect.Kind) bool {
  function valueSortLess (line 295) | func valueSortLess(a, b reflect.Value) bool {
  function sortValues (line 336) | func sortValues(values []reflect.Value, cs *ConfigState) {

FILE: vendor/github.com/davecgh/go-spew/spew/config.go
  type ConfigState (line 37) | type ConfigState struct
    method Errorf (line 115) | func (c *ConfigState) Errorf(format string, a ...interface{}) (err err...
    method Fprint (line 127) | func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, er...
    method Fprintf (line 139) | func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interfa...
    method Fprintln (line 150) | func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, ...
    method Print (line 162) | func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
    method Printf (line 174) | func (c *ConfigState) Printf(format string, a ...interface{}) (n int, ...
    method Println (line 186) | func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
    method Sprint (line 197) | func (c *ConfigState) Sprint(a ...interface{}) string {
    method Sprintf (line 208) | func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
    method Sprintln (line 219) | func (c *ConfigState) Sprintln(a ...interface{}) string {
    method NewFormatter (line 240) | func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
    method Fdump (line 246) | func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
    method Dump (line 273) | func (c *ConfigState) Dump(a ...interface{}) {
    method Sdump (line 279) | func (c *ConfigState) Sdump(a ...interface{}) string {
    method convertArgs (line 288) | func (c *ConfigState) convertArgs(args []interface{}) (formatters []in...
  function NewDefaultConfig (line 304) | func NewDefaultConfig() *ConfigState {

FILE: vendor/github.com/davecgh/go-spew/spew/dump.go
  type dumpState (line 51) | type dumpState struct
    method indent (line 62) | func (d *dumpState) indent() {
    method unpackValue (line 73) | func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
    method dumpPtr (line 81) | func (d *dumpState) dumpPtr(v reflect.Value) {
    method dumpSlice (line 161) | func (d *dumpState) dumpSlice(v reflect.Value) {
    method dump (line 251) | func (d *dumpState) dump(v reflect.Value) {
  function fdump (line 453) | func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
  function Fdump (line 472) | func Fdump(w io.Writer, a ...interface{}) {
  function Sdump (line 478) | func Sdump(a ...interface{}) string {
  function Dump (line 507) | func Dump(a ...interface{}) {

FILE: vendor/github.com/davecgh/go-spew/spew/format.go
  constant supportedFlags (line 28) | supportedFlags = "0-+# "
  type formatState (line 34) | type formatState struct
    method buildDefaultFormat (line 47) | func (f *formatState) buildDefaultFormat() (format string) {
    method constructOrigFormat (line 65) | func (f *formatState) constructOrigFormat(verb rune) (format string) {
    method unpackValue (line 94) | func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
    method formatPtr (line 105) | func (f *formatState) formatPtr(v reflect.Value) {
    method format (line 201) | func (f *formatState) format(v reflect.Value) {
    method Format (line 371) | func (f *formatState) Format(fs fmt.State, verb rune) {
  function newFormatter (line 394) | func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
  function NewFormatter (line 417) | func NewFormatter(v interface{}) fmt.Formatter {

FILE: vendor/github.com/davecgh/go-spew/spew/spew.go
  function Errorf (line 32) | func Errorf(format string, a ...interface{}) (err error) {
  function Fprint (line 44) | func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
  function Fprintf (line 56) | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err e...
  function Fprintln (line 67) | func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
  function Print (line 79) | func Print(a ...interface{}) (n int, err error) {
  function Printf (line 91) | func Printf(format string, a ...interface{}) (n int, err error) {
  function Println (line 103) | func Println(a ...interface{}) (n int, err error) {
  function Sprint (line 114) | func Sprint(a ...interface{}) string {
  function Sprintf (line 125) | func Sprintf(format string, a ...interface{}) string {
  function Sprintln (line 136) | func Sprintln(a ...interface{}) string {
  function convertArgs (line 142) | func convertArgs(args []interface{}) (formatters []interface{}) {

FILE: vendor/github.com/fsnotify/fsnotify/fen.go
  type Watcher (line 14) | type Watcher struct
    method Close (line 25) | func (w *Watcher) Close() error {
    method Add (line 30) | func (w *Watcher) Add(name string) error {
    method Remove (line 35) | func (w *Watcher) Remove(name string) error {
  function NewWatcher (line 20) | func NewWatcher() (*Watcher, error) {

FILE: vendor/github.com/fsnotify/fsnotify/fsnotify.go
  type Event (line 16) | type Event struct
    method String (line 35) | func (e Event) String() string {
  type Op (line 22) | type Op
  constant Create (line 26) | Create Op = 1 << iota
  constant Write (line 27) | Write
  constant Remove (line 28) | Remove
  constant Rename (line 29) | Rename
  constant Chmod (line 30) | Chmod

FILE: vendor/github.com/fsnotify/fsnotify/inotify.go
  type Watcher (line 23) | type Watcher struct
    method isClosed (line 65) | func (w *Watcher) isClosed() bool {
    method Close (line 75) | func (w *Watcher) Close() error {
    method Add (line 93) | func (w *Watcher) Add(name string) error {
    method Remove (line 126) | func (w *Watcher) Remove(name string) error {
    method readEvents (line 172) | func (w *Watcher) readEvents() {
  function NewWatcher (line 37) | func NewWatcher() (*Watcher, error) {
  type watch (line 165) | type watch struct
  method ignoreLinux (line 282) | func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool {
  function newEvent (line 307) | func newEvent(name string, mask uint32) Event {

FILE: vendor/github.com/fsnotify/fsnotify/inotify_poller.go
  type fdPoller (line 15) | type fdPoller struct
    method wait (line 79) | func (poller *fdPoller) wait() (bool, error) {
    method wake (line 149) | func (poller *fdPoller) wake() error {
    method clearWake (line 162) | func (poller *fdPoller) clearWake() error {
    method close (line 177) | func (poller *fdPoller) close() {
  function emptyPoller (line 21) | func emptyPoller(fd int) *fdPoller {
  function newFdPoller (line 32) | func newFdPoller(fd int) (*fdPoller, error) {

FILE: vendor/github.com/fsnotify/fsnotify/kqueue.go
  type Watcher (line 22) | type Watcher struct
    method Close (line 67) | func (w *Watcher) Close() error {
    method Add (line 99) | func (w *Watcher) Add(name string) error {
    method Remove (line 108) | func (w *Watcher) Remove(name string) error {
    method addWatch (line 164) | func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
    method readEvents (line 266) | func (w *Watcher) readEvents() {
    method watchDirectoryFiles (line 380) | func (w *Watcher) watchDirectoryFiles(dirPath string) error {
    method sendDirectoryChangeEvents (line 406) | func (w *Watcher) sendDirectoryChangeEvents(dirPath string) {
    method sendFileCreatedEventIfNew (line 425) | func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo ...
    method internalWatch (line 447) | func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (st...
  type pathInfo (line 38) | type pathInfo struct
  function NewWatcher (line 44) | func NewWatcher() (*Watcher, error) {
  constant noteAllEvents (line 156) | noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | ...
  function newEvent (line 358) | func newEvent(name string, mask uint32) Event {
  function newCreateEvent (line 375) | func newCreateEvent(name string) Event {
  function kqueue (line 464) | func kqueue() (kq int, err error) {
  function register (line 473) | func register(kq int, fds []int, flags int, fflags uint32) error {
  function read (line 492) | func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]uni...
  function durationToTimespec (line 501) | func durationToTimespec(d time.Duration) unix.Timespec {

FILE: vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
  constant openMode (line 11) | openMode = unix.O_NONBLOCK | unix.O_RDONLY

FILE: vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
  constant openMode (line 12) | openMode = unix.O_EVTONLY

FILE: vendor/github.com/fsnotify/fsnotify/windows.go
  type Watcher (line 21) | type Watcher struct
    method Close (line 51) | func (w *Watcher) Close() error {
    method Add (line 67) | func (w *Watcher) Add(name string) error {
    method Remove (line 85) | func (w *Watcher) Remove(name string) error {
    method wakeupReader (line 177) | func (w *Watcher) wakeupReader() error {
    method addWatch (line 240) | func (w *Watcher) addWatch(pathname string, flags uint64) error {
    method remWatch (line 289) | func (w *Watcher) remWatch(pathname string) error {
    method deleteWatch (line 316) | func (w *Watcher) deleteWatch(watch *watch) {
    method startRead (line 332) | func (w *Watcher) startRead(watch *watch) error {
    method readEvents (line 373) | func (w *Watcher) readEvents() {
    method sendEvent (line 517) | func (w *Watcher) sendEvent(name string, mask uint64) bool {
  function NewWatcher (line 33) | func NewWatcher() (*Watcher, error) {
  constant sysFSONESHOT (line 100) | sysFSONESHOT = 0x80000000
  constant sysFSONLYDIR (line 101) | sysFSONLYDIR = 0x1000000
  constant sysFSACCESS (line 104) | sysFSACCESS     = 0x1
  constant sysFSALLEVENTS (line 105) | sysFSALLEVENTS  = 0xfff
  constant sysFSATTRIB (line 106) | sysFSATTRIB     = 0x4
  constant sysFSCLOSE (line 107) | sysFSCLOSE      = 0x18
  constant sysFSCREATE (line 108) | sysFSCREATE     = 0x100
  constant sysFSDELETE (line 109) | sysFSDELETE     = 0x200
  constant sysFSDELETESELF (line 110) | sysFSDELETESELF = 0x400
  constant sysFSMODIFY (line 111) | sysFSMODIFY     = 0x2
  constant sysFSMOVE (line 112) | sysFSMOVE       = 0xc0
  constant sysFSMOVEDFROM (line 113) | sysFSMOVEDFROM  = 0x40
  constant sysFSMOVEDTO (line 114) | sysFSMOVEDTO    = 0x80
  constant sysFSMOVESELF (line 115) | sysFSMOVESELF   = 0x800
  constant sysFSIGNORED (line 118) | sysFSIGNORED   = 0x8000
  constant sysFSQOVERFLOW (line 119) | sysFSQOVERFLOW = 0x4000
  function newEvent (line 122) | func newEvent(name string, mask uint32) Event {
  constant opAddWatch (line 143) | opAddWatch = iota
  constant opRemoveWatch (line 144) | opRemoveWatch
  constant provisional (line 148) | provisional uint64 = 1 << (32 + iota)
  type input (line 151) | type input struct
  type inode (line 158) | type inode struct
  type watch (line 164) | type watch struct
  type indexMap (line 174) | type indexMap
  type watchMap (line 175) | type watchMap
    method get (line 222) | func (m watchMap) get(ino *inode) *watch {
    method set (line 230) | func (m watchMap) set(ino *inode, watch *watch) {
  function getDir (line 185) | func getDir(pathname string) (dir string, err error) {
  function getIno (line 199) | func getIno(path string) (ino *inode, err error) {
  function toWindowsFlags (line 530) | func toWindowsFlags(mask uint64) uint32 {
  function toFSnotifyFlags (line 547) | func toFSnotifyFlags(action uint32) uint64 {

FILE: vendor/github.com/go-sql-driver/mysql/appengine.go
  function init (line 17) | func init() {

FILE: vendor/github.com/go-sql-driver/mysql/buffer.go
  constant defaultBufSize (line 17) | defaultBufSize = 4096
  type buffer (line 24) | type buffer struct
    method fill (line 41) | func (b *buffer) fill(need int) error {
    method readNext (line 94) | func (b *buffer) readNext(need int) ([]byte, error) {
    method takeBuffer (line 112) | func (b *buffer) takeBuffer(length int) []byte {
    method takeSmallBuffer (line 132) | func (b *buffer) takeSmallBuffer(length int) []byte {
    method takeCompleteBuffer (line 142) | func (b *buffer) takeCompleteBuffer() []byte {
  function newBuffer (line 32) | func newBuffer(nc net.Conn) buffer {

FILE: vendor/github.com/go-sql-driver/mysql/collations.go
  constant defaultCollation (line 11) | defaultCollation = "utf8_general_ci"
  constant binaryCollation (line 12) | binaryCollation = "binary"

FILE: vendor/github.com/go-sql-driver/mysql/connection.go
  type mysqlContext (line 21) | type mysqlContext interface
  type mysqlConn (line 30) | type mysqlConn struct
    method handleParams (line 54) | func (mc *mysqlConn) handleParams() (err error) {
    method markBadConn (line 83) | func (mc *mysqlConn) markBadConn(err error) error {
    method Begin (line 93) | func (mc *mysqlConn) Begin() (driver.Tx, error) {
    method begin (line 97) | func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) {
    method Close (line 115) | func (mc *mysqlConn) Close() (err error) {
    method cleanup (line 130) | func (mc *mysqlConn) cleanup() {
    method error (line 145) | func (mc *mysqlConn) error() error {
    method Prepare (line 155) | func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
    method interpolateParams (line 187) | func (mc *mysqlConn) interpolateParams(query string, args []driver.Val...
    method Exec (line 309) | func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.R...
    method exec (line 339) | func (mc *mysqlConn) exec(query string) error {
    method Query (line 366) | func (mc *mysqlConn) Query(query string, args []driver.Value) (driver....
    method query (line 370) | func (mc *mysqlConn) query(query string, args []driver.Value) (*textRo...
    method getSystemVar (line 417) | func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
    method cancel (line 446) | func (mc *mysqlConn) cancel(err error) {
    method finish (line 452) | func (mc *mysqlConn) finish() {

FILE: vendor/github.com/go-sql-driver/mysql/connection_go18.go
  method Ping (line 20) | func (mc *mysqlConn) Ping(ctx context.Context) error {
  method BeginTx (line 42) | func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions)...
  method QueryContext (line 62) | func (mc *mysqlConn) QueryContext(ctx context.Context, query string, arg...
  method ExecContext (line 81) | func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args...
  method PrepareContext (line 95) | func (mc *mysqlConn) PrepareContext(ctx context.Context, query string) (...
  method QueryContext (line 115) | func (stmt *mysqlStmt) QueryContext(ctx context.Context, args []driver.N...
  method ExecContext (line 134) | func (stmt *mysqlStmt) ExecContext(ctx context.Context, args []driver.Na...
  method watchCancel (line 148) | func (mc *mysqlConn) watchCancel(ctx context.Context) error {
  method startWatcher (line 174) | func (mc *mysqlConn) startWatcher() {
  method CheckNamedValue (line 199) | func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {

FILE: vendor/github.com/go-sql-driver/mysql/const.go
  constant defaultMaxAllowedPacket (line 12) | defaultMaxAllowedPacket = 4 << 20
  constant minProtocolVersion (line 13) | minProtocolVersion      = 10
  constant maxPacketSize (line 14) | maxPacketSize           = 1<<24 - 1
  constant timeFormat (line 15) | timeFormat              = "2006-01-02 15:04:05.999999"
  constant iOK (line 22) | iOK          byte = 0x00
  constant iLocalInFile (line 23) | iLocalInFile byte = 0xfb
  constant iEOF (line 24) | iEOF         byte = 0xfe
  constant iERR (line 25) | iERR         byte = 0xff
  type clientFlag (line 29) | type clientFlag
  constant clientLongPassword (line 32) | clientLongPassword clientFlag = 1 << iota
  constant clientFoundRows (line 33) | clientFoundRows
  constant clientLongFlag (line 34) | clientLongFlag
  constant clientConnectWithDB (line 35) | clientConnectWithDB
  constant clientNoSchema (line 36) | clientNoSchema
  constant clientCompress (line 37) | clientCompress
  constant clientODBC (line 38) | clientODBC
  constant clientLocalFiles (line 39) | clientLocalFiles
  constant clientIgnoreSpace (line 40) | clientIgnoreSpace
  constant clientProtocol41 (line 41) | clientProtocol41
  constant clientInteractive (line 42) | clientInteractive
  constant clientSSL (line 43) | clientSSL
  constant clientIgnoreSIGPIPE (line 44) | clientIgnoreSIGPIPE
  constant clientTransactions (line 45) | clientTransactions
  constant clientReserved (line 46) | clientReserved
  constant clientSecureConn (line 47) | clientSecureConn
  constant clientMultiStatements (line 48) | clientMultiStatements
  constant clientMultiResults (line 49) | clientMultiResults
  constant clientPSMultiResults (line 50) | clientPSMultiResults
  constant clientPluginAuth (line 51) | clientPluginAuth
  constant clientConnectAttrs (line 52) | clientConnectAttrs
  constant clientPluginAuthLenEncClientData (line 53) | clientPluginAuthLenEncClientData
  constant clientCanHandleExpiredPasswords (line 54) | clientCanHandleExpiredPasswords
  constant clientSessionTrack (line 55) | clientSessionTrack
  constant clientDeprecateEOF (line 56) | clientDeprecateEOF
  constant comQuit (line 60) | comQuit byte = iota + 1
  constant comInitDB (line 61) | comInitDB
  constant comQuery (line 62) | comQuery
  constant comFieldList (line 63) | comFieldList
  constant comCreateDB (line 64) | comCreateDB
  constant comDropDB (line 65) | comDropDB
  constant comRefresh (line 66) | comRefresh
  constant comShutdown (line 67) | comShutdown
  constant comStatistics (line 68) | comStatistics
  constant comProcessInfo (line 69) | comProcessInfo
  constant comConnect (line 70) | comConnect
  constant comProcessKill (line 71) | comProcessKill
  constant comDebug (line 72) | comDebug
  constant comPing (line 73) | comPing
  constant comTime (line 74) | comTime
  constant comDelayedInsert (line 75) | comDelayedInsert
  constant comChangeUser (line 76) | comChangeUser
  constant comBinlogDump (line 77) | comBinlogDump
  constant comTableDump (line 78) | comTableDump
  constant comConnectOut (line 79) | comConnectOut
  constant comRegisterSlave (line 80) | comRegisterSlave
  constant comStmtPrepare (line 81) | comStmtPrepare
  constant comStmtExecute (line 82) | comStmtExecute
  constant comStmtSendLongData (line 83) | comStmtSendLongData
  constant comStmtClose (line 84) | comStmtClose
  constant comStmtReset (line 85) | comStmtReset
  constant comSetOption (line 86) | comSetOption
  constant comStmtFetch (line 87) | comStmtFetch
  type fieldType (line 91) | type fieldType
  constant fieldTypeDecimal (line 94) | fieldTypeDecimal fieldType = iota
  constant fieldTypeTiny (line 95) | fieldTypeTiny
  constant fieldTypeShort (line 96) | fieldTypeShort
  constant fieldTypeLong (line 97) | fieldTypeLong
  constant fieldTypeFloat (line 98) | fieldTypeFloat
  constant fieldTypeDouble (line 99) | fieldTypeDouble
  constant fieldTypeNULL (line 100) | fieldTypeNULL
  constant fieldTypeTimestamp (line 101) | fieldTypeTimestamp
  constant fieldTypeLongLong (line 102) | fieldTypeLongLong
  constant fieldTypeInt24 (line 103) | fieldTypeInt24
  constant fieldTypeDate (line 104) | fieldTypeDate
  constant fieldTypeTime (line 105) | fieldTypeTime
  constant fieldTypeDateTime (line 106) | fieldTypeDateTime
  constant fieldTypeYear (line 107) | fieldTypeYear
  constant fieldTypeNewDate (line 108) | fieldTypeNewDate
  constant fieldTypeVarChar (line 109) | fieldTypeVarChar
  constant fieldTypeBit (line 110) | fieldTypeBit
  constant fieldTypeJSON (line 113) | fieldTypeJSON fieldType = iota + 0xf5
  constant fieldTypeNewDecimal (line 114) | fieldTypeNewDecimal
  constant fieldTypeEnum (line 115) | fieldTypeEnum
  constant fieldTypeSet (line 116) | fieldTypeSet
  constant fieldTypeTinyBLOB (line 117) | fieldTypeTinyBLOB
  constant fieldTypeMediumBLOB (line 118) | fieldTypeMediumBLOB
  constant fieldTypeLongBLOB (line 119) | fieldTypeLongBLOB
  constant fieldTypeBLOB (line 120) | fieldTypeBLOB
  constant fieldTypeVarString (line 121) | fieldTypeVarString
  constant fieldTypeString (line 122) | fieldTypeString
  constant fieldTypeGeometry (line 123) | fieldTypeGeometry
  type fieldFlag (line 126) | type fieldFlag
  constant flagNotNULL (line 129) | flagNotNULL fieldFlag = 1 << iota
  constant flagPriKey (line 130) | flagPriKey
  constant flagUniqueKey (line 131) | flagUniqueKey
  constant flagMultipleKey (line 132) | flagMultipleKey
  constant flagBLOB (line 133) | flagBLOB
  constant flagUnsigned (line 134) | flagUnsigned
  constant flagZeroFill (line 135) | flagZeroFill
  constant flagBinary (line 136) | flagBinary
  constant flagEnum (line 137) | flagEnum
  constant flagAutoIncrement (line 138) | flagAutoIncrement
  constant flagTimestamp (line 139) | flagTimestamp
  constant flagSet (line 140) | flagSet
  constant flagUnknown1 (line 141) | flagUnknown1
  constant flagUnknown2 (line 142) | flagUnknown2
  constant flagUnknown3 (line 143) | flagUnknown3
  constant flagUnknown4 (line 144) | flagUnknown4
  type statusFlag (line 148) | type statusFlag
  constant statusInTrans (line 151) | statusInTrans statusFlag = 1 << iota
  constant statusInAutocommit (line 152) | statusInAutocommit
  constant statusReserved (line 153) | statusReserved
  constant statusMoreResultsExists (line 154) | statusMoreResultsExists
  constant statusNoGoodIndexUsed (line 155) | statusNoGoodIndexUsed
  constant statusNoIndexUsed (line 156) | statusNoIndexUsed
  constant statusCursorExists (line 157) | statusCursorExists
  constant statusLastRowSent (line 158) | statusLastRowSent
  constant statusDbDropped (line 159) | statusDbDropped
  constant statusNoBackslashEscapes (line 160) | statusNoBackslashEscapes
  constant statusMetadataChanged (line 161) | statusMetadataChanged
  constant statusQueryWasSlow (line 162) | statusQueryWasSlow
  constant statusPsOutParams (line 163) | statusPsOutParams
  constant statusInTransReadonly (line 164) | statusInTransReadonly
  constant statusSessionStateChanged (line 165) | statusSessionStateChanged

FILE: vendor/github.com/go-sql-driver/mysql/driver.go
  type watcher (line 26) | type watcher interface
  type MySQLDriver (line 32) | type MySQLDriver struct
    method Open (line 53) | func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
  type DialFunc (line 36) | type DialFunc
  function RegisterDial (line 43) | func RegisterDial(net string, dial DialFunc) {
  function handleAuthResult (line 147) | func handleAuthResult(mc *mysqlConn, oldCipher []byte) error {
  function init (line 191) | func init() {

FILE: vendor/github.com/go-sql-driver/mysql/dsn.go
  type Config (line 34) | type Config struct
    method normalize (line 72) | func (cfg *Config) normalize() error {
    method FormatDSN (line 111) | func (cfg *Config) FormatDSN() string {
  function NewConfig (line 63) | func NewConfig() *Config {
  function ParseDSN (line 323) | func ParseDSN(dsn string) (cfg *Config, err error) {
  function parseDSNParams (line 401) | func parseDSNParams(cfg *Config, params string) (err error) {
  function ensureHavePort (line 579) | func ensureHavePort(addr string) string {

FILE: vendor/github.com/go-sql-driver/mysql/errors.go
  type Logger (line 43) | type Logger interface
  function SetLogger (line 49) | func SetLogger(logger Logger) error {
  type MySQLError (line 58) | type MySQLError struct
    method Error (line 63) | func (me *MySQLError) Error() string {

FILE: vendor/github.com/go-sql-driver/mysql/fields.go
  type mysqlField (line 118) | type mysqlField struct
    method typeDatabaseName (line 16) | func (mf *mysqlField) typeDatabaseName() string {
    method scanType (line 128) | func (mf *mysqlField) scanType() reflect.Type {

FILE: vendor/github.com/go-sql-driver/mysql/infile.go
  function RegisterLocalFile (line 37) | func RegisterLocalFile(filePath string) {
  function DeregisterLocalFile (line 49) | func DeregisterLocalFile(filePath string) {
  function RegisterReaderHandler (line 70) | func RegisterReaderHandler(name string, handler func() io.Reader) {
  function DeregisterReaderHandler (line 83) | func DeregisterReaderHandler(name string) {
  function deferredClose (line 89) | func deferredClose(err *error, closer io.Closer) {
  method handleInFileRequest (line 96) | func (mc *mysqlConn) handleInFileRequest(name string) (err error) {

FILE: vendor/github.com/go-sql-driver/mysql/packets.go
  method readPacket (line 27) | func (mc *mysqlConn) readPacket() ([]byte, error) {
  method writePacket (line 92) | func (mc *mysqlConn) writePacket(data []byte) error {
  method readInitPacket (line 157) | func (mc *mysqlConn) readInitPacket() ([]byte, error) {
  method writeAuthPacket (line 246) | func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
  method writeOldAuthPacket (line 362) | func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error {
  method writeClearAuthPacket (line 386) | func (mc *mysqlConn) writeClearAuthPacket() error {
  method writeNativeAuthPacket (line 405) | func (mc *mysqlConn) writeNativeAuthPacket(cipher []byte) error {
  method writeCommandPacket (line 429) | func (mc *mysqlConn) writeCommandPacket(command byte) error {
  method writeCommandPacketStr (line 447) | func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) err...
  method writeCommandPacketUint32 (line 469) | func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) ...
  method readResultOK (line 498) | func (mc *mysqlConn) readResultOK() ([]byte, error) {
  method readResultSetHeaderPacket (line 540) | func (mc *mysqlConn) readResultSetHeaderPacket() (int, error) {
  method handleErrorPacket (line 568) | func (mc *mysqlConn) handleErrorPacket(data []byte) error {
  function readStatus (line 609) | func readStatus(b []byte) statusFlag {
  method handleOkPacket (line 615) | func (mc *mysqlConn) handleOkPacket(data []byte) error {
  method readColumns (line 639) | func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {
  method readRow (line 739) | func (rows *textRows) readRow(dest []driver.Value) error {
  method readUntilEOF (line 807) | func (mc *mysqlConn) readUntilEOF() error {
  method readPrepareResultPacket (line 832) | func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {
  method writeCommandLongData (line 859) | func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) err...
  method writeExecutePacket (line 912) | func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
  method discardResults (line 1127) | func (mc *mysqlConn) discardResults() error {
  method readRow (line 1148) | func (rows *binaryRows) readRow(dest []driver.Value) error {

FILE: vendor/github.com/go-sql-driver/mysql/result.go
  type mysqlResult (line 11) | type mysqlResult struct
    method LastInsertId (line 16) | func (res *mysqlResult) LastInsertId() (int64, error) {
    method RowsAffected (line 20) | func (res *mysqlResult) RowsAffected() (int64, error) {

FILE: vendor/github.com/go-sql-driver/mysql/rows.go
  type resultSet (line 18) | type resultSet struct
  type mysqlRows (line 24) | type mysqlRows struct
    method Columns (line 38) | func (rows *mysqlRows) Columns() []string {
    method ColumnTypeDatabaseTypeName (line 62) | func (rows *mysqlRows) ColumnTypeDatabaseTypeName(i int) string {
    method ColumnTypeNullable (line 70) | func (rows *mysqlRows) ColumnTypeNullable(i int) (nullable, ok bool) {
    method ColumnTypePrecisionScale (line 74) | func (rows *mysqlRows) ColumnTypePrecisionScale(i int) (int64, int64, ...
    method ColumnTypeScanType (line 96) | func (rows *mysqlRows) ColumnTypeScanType(i int) reflect.Type {
    method Close (line 100) | func (rows *mysqlRows) Close() (err error) {
    method HasNextResultSet (line 128) | func (rows *mysqlRows) HasNextResultSet() (b bool) {
    method nextResultSet (line 135) | func (rows *mysqlRows) nextResultSet() (int, error) {
    method nextNotEmptyResultSet (line 159) | func (rows *mysqlRows) nextNotEmptyResultSet() (int, error) {
  type binaryRows (line 30) | type binaryRows struct
    method NextResultSet (line 174) | func (rows *binaryRows) NextResultSet() error {
    method Next (line 184) | func (rows *binaryRows) Next(dest []driver.Value) error {
  type textRows (line 34) | type textRows struct
    method NextResultSet (line 196) | func (rows *textRows) NextResultSet() (err error) {
    method Next (line 206) | func (rows *textRows) Next(dest []driver.Value) error {

FILE: vendor/github.com/go-sql-driver/mysql/statement.go
  type mysqlStmt (line 19) | type mysqlStmt struct
    method Close (line 25) | func (stmt *mysqlStmt) Close() error {
    method NumInput (line 39) | func (stmt *mysqlStmt) NumInput() int {
    method ColumnConverter (line 43) | func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
    method Exec (line 47) | func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
    method Query (line 91) | func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
    method query (line 95) | func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
  type converter (line 133) | type converter struct
    method ConvertValue (line 140) | func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
  function callValuerValue (line 204) | func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {

FILE: vendor/github.com/go-sql-driver/mysql/transaction.go
  type mysqlTx (line 11) | type mysqlTx struct
    method Commit (line 15) | func (tx *mysqlTx) Commit() (err error) {
    method Rollback (line 24) | fu
Condensed preview — 698 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,829K chars).
[
  {
    "path": ".gitlab-ci.yml",
    "chars": 431,
    "preview": "image: golang:1.12\n\nbefore_script:\n  - mkdir -p /go/src/github.com/superkkt\n  - cp -rp /builds/superkkt/cherry /go/src/g"
  },
  {
    "path": "Changelog",
    "chars": 19327,
    "preview": "* v0.14.2 (2019-09-20)\n\n3faead4 Fix the unexpected master change (See #44)\n\n* v0.14.1 (2019-09-03)\n\nb321987 Remove passw"
  },
  {
    "path": "Dockerfile",
    "chars": 529,
    "preview": "# Start from a Debian image with the latest version of Go installed\n# and a workspace (GOPATH) configured at /go.\nFROM g"
  },
  {
    "path": "Godeps/Godeps.json",
    "chars": 3889,
    "preview": "{\n\t\"ImportPath\": \"github.com/superkkt/cherry\",\n\t\"GoVersion\": \"go1.10\",\n\t\"GodepVersion\": \"v79\",\n\t\"Packages\": [\n\t\t\"./...\"\n"
  },
  {
    "path": "Godeps/Readme",
    "chars": 136,
    "preview": "This directory tree is generated automatically by godep.\n\nPlease do not edit.\n\nSee https://github.com/tools/godep for mo"
  },
  {
    "path": "Gopkg.toml",
    "chars": 1025,
    "preview": "# Gopkg.toml example\n#\n# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html\n# for detailed Gopkg.toml documentat"
  },
  {
    "path": "LICENSE",
    "chars": 15225,
    "preview": "       GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software F"
  },
  {
    "path": "README.md",
    "chars": 2910,
    "preview": "# Cherry\n\nCherry is an OpenFlow controller written in Go that supports OpenFlow 1.0 and 1.3 protocols. This project is n"
  },
  {
    "path": "api/core/api.go",
    "chars": 4106,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/response.go",
    "chars": 2938,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/server.go",
    "chars": 2938,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/api.go",
    "chars": 8048,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/category.go",
    "chars": 9427,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/component.go",
    "chars": 9978,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/group.go",
    "chars": 9180,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/host.go",
    "chars": 19761,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/ip.go",
    "chars": 3035,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/log.go",
    "chars": 4688,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/network.go",
    "chars": 8374,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/session.go",
    "chars": 2315,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/switch.go",
    "chars": 8926,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/user.go",
    "chars": 14081,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "api/ui/vip.go",
    "chars": 9463,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "cmd/cherry/cherry.yaml",
    "chars": 954,
    "preview": "default:\n    port: 6633\n    # The logger will only write log messages whose level is equal to or higher than log_level.\n"
  },
  {
    "path": "cmd/cherry/main.go",
    "chars": 8725,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "cmd/walnut/main.go",
    "chars": 5743,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "cmd/walnut/sdk.go",
    "chars": 2729,
    "preview": "/*\n * Copyright 2019 Samjung Data Service, Inc. All Rights Reserved.\n *\n * Authors:\n * \tKitae Kim <superkkt@sds.co.kr>\n "
  },
  {
    "path": "cmd/walnut/walnut.yaml",
    "chars": 925,
    "preview": "# NOTE:\n#\n# Parameters marked as a DYNAMIC can be dynamically updated without restarting the daemon.\n\nlog:\n    # (DYNAMI"
  },
  {
    "path": "database/mysql.go",
    "chars": 69735,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "database/mysql_schema.sql",
    "chars": 16373,
    "preview": "-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for debian-linux-gnu (x86_64)\n--\n-- Host: localhost    Database: cherry\n-- "
  },
  {
    "path": "database/random.go",
    "chars": 1219,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "election/election.go",
    "chars": 2921,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "graph/graph.go",
    "chars": 9454,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "graph/graph_test.go",
    "chars": 13125,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved. \n * Kitae"
  },
  {
    "path": "ldap/client.go",
    "chars": 2741,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "ldap/conn.go",
    "chars": 1628,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "log/syslog.go",
    "chars": 1891,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/controller.go",
    "chars": 3566,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/device.go",
    "chars": 11813,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/error.go",
    "chars": 1056,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/flow_cache.go",
    "chars": 2347,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/link.go",
    "chars": 1408,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/node.go",
    "chars": 1251,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/of10_session.go",
    "chars": 4561,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/of13_session.go",
    "chars": 7646,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/port.go",
    "chars": 1962,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/reserve.go",
    "chars": 1707,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *  "
  },
  {
    "path": "network/reserve_test.go",
    "chars": 2941,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *  "
  },
  {
    "path": "network/session.go",
    "chars": 19434,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "network/topology.go",
    "chars": 7162,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/announcer/announcer.go",
    "chars": 2942,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *\n "
  },
  {
    "path": "northbound/app/announcer/backoff.go",
    "chars": 2858,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/dhcp/dhcp.go",
    "chars": 8176,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n *  "
  },
  {
    "path": "northbound/app/discovery/discovery.go",
    "chars": 9870,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/l2switch/storm_controller.go",
    "chars": 2357,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/l2switch/storm_controller_test.go",
    "chars": 2968,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/l2switch/switch.go",
    "chars": 10000,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/monitor/monitor.go",
    "chars": 2827,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/monitor/sendmail.go",
    "chars": 806,
    "preview": "package monitor\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"net/smtp\"\n\t\"strings\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// msg is a RFC 822-style em"
  },
  {
    "path": "northbound/app/processor.go",
    "chars": 3952,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/proxyarp/arp.go",
    "chars": 4407,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/proxyarp/error.go",
    "chars": 1060,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/app/virtualip/virtualip.go",
    "chars": 3351,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "northbound/manager.go",
    "chars": 4005,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/action.go",
    "chars": 2893,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/barrier.go",
    "chars": 1032,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/config.go",
    "chars": 1400,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/const.go",
    "chars": 923,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/description.go",
    "chars": 1170,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/echo.go",
    "chars": 1736,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/error.go",
    "chars": 1670,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/factory.go",
    "chars": 2857,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/features.go",
    "chars": 1161,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/flow_mod.go",
    "chars": 1506,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/flow_removed.go",
    "chars": 1180,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/flow_stats.go",
    "chars": 1209,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/hello.go",
    "chars": 1209,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/instruction.go",
    "chars": 1043,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/match.go",
    "chars": 2480,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/message.go",
    "chars": 2468,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/action.go",
    "chars": 5308,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/barrier.go",
    "chars": 1388,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/config.go",
    "chars": 3291,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/const.go",
    "chars": 6134,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/description.go",
    "chars": 2491,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/echo.go",
    "chars": 1247,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/factory.go",
    "chars": 4716,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/features.go",
    "chars": 2719,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/flow_mod.go",
    "chars": 4060,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/flow_removed.go",
    "chars": 2863,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/flow_stats.go",
    "chars": 2617,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/hello.go",
    "chars": 1067,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/instruction.go",
    "chars": 1602,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/match.go",
    "chars": 11336,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/packet_in.go",
    "chars": 2091,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/packet_out.go",
    "chars": 2552,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/port.go",
    "chars": 2857,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/port_status.go",
    "chars": 1737,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of10/queue.go",
    "chars": 4572,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/action.go",
    "chars": 4284,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/barrier.go",
    "chars": 1388,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/config.go",
    "chars": 3291,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/const.go",
    "chars": 9321,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/echo.go",
    "chars": 1247,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/factory.go",
    "chars": 4651,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/features.go",
    "chars": 2404,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/flow_mod.go",
    "chars": 4044,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/flow_removed.go",
    "chars": 2833,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/hello.go",
    "chars": 1067,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/instruction.go",
    "chars": 2810,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/match.go",
    "chars": 16301,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/multipart_description.go",
    "chars": 2457,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/multipart_flow_stats.go",
    "chars": 2711,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/multipart_port_description.go",
    "chars": 2090,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/multipart_table_features.go",
    "chars": 1475,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/packet_in.go",
    "chars": 2434,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/packet_out.go",
    "chars": 2448,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/port.go",
    "chars": 3159,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/port_status.go",
    "chars": 1709,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/of13/queue.go",
    "chars": 4989,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/packet_in.go",
    "chars": 1077,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/packet_out.go",
    "chars": 1094,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/port.go",
    "chars": 2952,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/port_description.go",
    "chars": 1050,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/port_status.go",
    "chars": 1085,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/queue.go",
    "chars": 1540,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/table_features.go",
    "chars": 1008,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/transceiver/stream.go",
    "chars": 6293,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "openflow/transceiver/transceiver.go",
    "chars": 15036,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "protocol/arp.go",
    "chars": 3412,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "protocol/checksum.go",
    "chars": 1349,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved. \n * Kitae"
  },
  {
    "path": "protocol/dhcp.go",
    "chars": 7192,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n * K"
  },
  {
    "path": "protocol/dhcp_test.go",
    "chars": 12459,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015-2019 Samjung Data Service, Inc. All rights reserved.\n * K"
  },
  {
    "path": "protocol/ethernet.go",
    "chars": 1884,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved. \n * Kitae"
  },
  {
    "path": "protocol/icmp.go",
    "chars": 2227,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved. \n * Kitae"
  },
  {
    "path": "protocol/ipv4.go",
    "chars": 3510,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "protocol/lldp.go",
    "chars": 5107,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved. \n * Kitae"
  },
  {
    "path": "protocol/tcp.go",
    "chars": 3355,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "protocol/udp.go",
    "chars": 2711,
    "preview": "/*\n * Cherry - An OpenFlow Controller\n *\n * Copyright (C) 2015 Samjung Data Service, Inc. All rights reserved.\n * Kitae "
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/LICENSE",
    "chars": 1080,
    "preview": "Copyright (c) 2013-2016 Antoine Imbert\n\nThe MIT License\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/access_log_apache.go",
    "chars": 6426,
    "preview": "package rest\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\t\"text/template\"\n\t\"time\"\n)\n\n// TODO Future improve"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/access_log_json.go",
    "chars": 2143,
    "preview": "package rest\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n)\n\n// AccessLogJsonMiddleware produces the access log with "
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/api.go",
    "chars": 2166,
    "preview": "package rest\n\nimport (\n\t\"net/http\"\n)\n\n// Api defines a stack of Middlewares and an App.\ntype Api struct {\n\tstack []Middl"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/auth_basic.go",
    "chars": 2703,
    "preview": "package rest\n\nimport (\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// AuthBasicMiddleware provides a s"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/content_type_checker.go",
    "chars": 1133,
    "preview": "package rest\n\nimport (\n\t\"mime\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// ContentTypeCheckerMiddleware verifies the request Content-Ty"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/cors.go",
    "chars": 4470,
    "preview": "package rest\n\nimport (\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Possible improvements:\n// If AllowedMethods[\"*\"] then Acc"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/doc.go",
    "chars": 1392,
    "preview": "// A quick and easy way to setup a RESTful JSON API\n//\n// http://ant0ine.github.io/go-json-rest/\n//\n// Go-Json-Rest is a"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/gzip.go",
    "chars": 3579,
    "preview": "package rest\n\nimport (\n\t\"bufio\"\n\t\"compress/gzip\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// GzipMiddleware is responsible for c"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/if.go",
    "chars": 1328,
    "preview": "package rest\n\nimport (\n\t\"log\"\n)\n\n// IfMiddleware evaluates at runtime a condition based on the current request, and deci"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/json_indent.go",
    "chars": 3059,
    "preview": "package rest\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// JsonIndentMiddleware provides JSON encoding wi"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/jsonp.go",
    "chars": 3112,
    "preview": "package rest\n\nimport (\n\t\"bufio\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// JsonpMiddleware provides JSONP responses on demand, based on th"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/middleware.go",
    "chars": 2327,
    "preview": "package rest\n\nimport (\n\t\"net/http\"\n)\n\n// HandlerFunc defines the handler function. It is the go-json-rest equivalent of "
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/powered_by.go",
    "chars": 672,
    "preview": "package rest\n\nconst xPoweredByDefault = \"go-json-rest\"\n\n// PoweredByMiddleware adds the \"X-Powered-By\" header to the HTT"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/recorder.go",
    "chars": 2668,
    "preview": "package rest\n\nimport (\n\t\"bufio\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// RecorderMiddleware keeps a record of the HTTP status code of th"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/recover.go",
    "chars": 1701,
    "preview": "package rest\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"runtime/debug\"\n)\n\n// RecoverMiddleware catches"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/request.go",
    "chars": 3439,
    "preview": "package rest\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\nvar (\n\t// ErrJsonPay"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/response.go",
    "chars": 3885,
    "preview": "package rest\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// A ResponseWriter interface dedicated to JSON H"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/route.go",
    "chars": 3491,
    "preview": "package rest\n\nimport (\n\t\"strings\"\n)\n\n// Route defines a route as consumed by the router. It can be instantiated directly"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/router.go",
    "chars": 4842,
    "preview": "package rest\n\nimport (\n\t\"errors\"\n\t\"github.com/ant0ine/go-json-rest/rest/trie\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype "
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/status.go",
    "chars": 3660,
    "preview": "package rest\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n)\n\n// StatusMiddleware keeps track of various stats about the"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/timer.go",
    "chars": 679,
    "preview": "package rest\n\nimport (\n\t\"time\"\n)\n\n// TimerMiddleware computes the elapsed time spent during the execution of the wrapped"
  },
  {
    "path": "vendor/github.com/ant0ine/go-json-rest/rest/trie/impl.go",
    "chars": 9621,
    "preview": "// Special Trie implementation for HTTP routing.\n//\n// This Trie implementation is designed to support strings that incl"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/.gitignore",
    "chars": 9,
    "preview": ".vscode/\n"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/LICENSE",
    "chars": 1085,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Florian Sundermann\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/README.md",
    "chars": 1166,
    "preview": "[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/barcode.go",
    "chars": 1014,
    "preview": "package barcode\n\nimport \"image\"\n\nconst (\n\tTypeAztec           = \"Aztec\"\n\tTypeCodabar         = \"Codabar\"\n\tTypeCode128   "
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/alphanumeric.go",
    "chars": 1426,
    "preview": "package qr\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/boombuler/barcode/utils\"\n)\n\nconst charSet string = \"01234"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/automatic.go",
    "chars": 573,
    "preview": "package qr\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/boombuler/barcode/utils\"\n)\n\nfunc encodeAuto(content string, ecl ErrorCorrectio"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/blocks.go",
    "chars": 1784,
    "preview": "package qr\n\ntype block struct {\n\tdata []byte\n\tecc  []byte\n}\ntype blockList []*block\n\nfunc splitToBlocks(data <-chan byte"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/encoder.go",
    "chars": 15495,
    "preview": "// Package qr can be used to create QR barcodes.\npackage qr\n\nimport (\n\t\"image\"\n\n\t\"github.com/boombuler/barcode\"\n\t\"github"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/errorcorrection.go",
    "chars": 639,
    "preview": "package qr\n\nimport (\n\t\"github.com/boombuler/barcode/utils\"\n)\n\ntype errorCorrection struct {\n\trs *utils.ReedSolomonEncode"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/numeric.go",
    "chars": 1136,
    "preview": "package qr\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/boombuler/barcode/utils\"\n)\n\nfunc encodeNumeric(content st"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/qrcode.go",
    "chars": 3309,
    "preview": "package qr\n\nimport (\n\t\"image\"\n\t\"image/color\"\n\t\"math\"\n\n\t\"github.com/boombuler/barcode\"\n\t\"github.com/boombuler/barcode/uti"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/unicode.go",
    "chars": 681,
    "preview": "package qr\n\nimport (\n\t\"errors\"\n\n\t\"github.com/boombuler/barcode/utils\"\n)\n\nfunc encodeUnicode(content string, ecl ErrorCor"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/qr/versioninfo.go",
    "chars": 9417,
    "preview": "package qr\n\nimport \"math\"\n\n// ErrorCorrectionLevel indicates the amount of \"backup data\" stored in the QR code\ntype Erro"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/scaledbarcode.go",
    "chars": 2850,
    "preview": "package barcode\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"image\"\n\t\"image/color\"\n\t\"math\"\n)\n\ntype wrapFunc func(x, y int) color.Color\n\n"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/base1dcode.go",
    "chars": 1285,
    "preview": "// Package utils contain some utilities which are needed to create barcodes\npackage utils\n\nimport (\n\t\"image\"\n\t\"image/col"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/bitlist.go",
    "chars": 2552,
    "preview": "package utils\n\n// BitList is a list that contains bits\ntype BitList struct {\n\tcount int\n\tdata  []int32\n}\n\n// NewBitList "
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/galoisfield.go",
    "chars": 1319,
    "preview": "package utils\n\n// GaloisField encapsulates galois field arithmetics\ntype GaloisField struct {\n\tSize    int\n\tBase    int\n"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/gfpoly.go",
    "chars": 2817,
    "preview": "package utils\n\ntype GFPoly struct {\n\tgf           *GaloisField\n\tCoefficients []int\n}\n\nfunc (gp *GFPoly) Degree() int {\n\t"
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/reedsolomon.go",
    "chars": 1091,
    "preview": "package utils\n\nimport (\n\t\"sync\"\n)\n\ntype ReedSolomonEncoder struct {\n\tgf        *GaloisField\n\tpolynomes []*GFPoly\n\tm     "
  },
  {
    "path": "vendor/github.com/boombuler/barcode/utils/runeint.go",
    "chars": 458,
    "preview": "package utils\n\n// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9\n// If the rune is outside "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/LICENSE",
    "chars": 766,
    "preview": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins <dave@davec.name>\n\nPermission to use, copy, modify, and/or distribute "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/bypass.go",
    "chars": 4715,
    "preview": "// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>\n//\n// Permission to use, copy, modify, and distribute this sof"
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/bypasssafe.go",
    "chars": 1741,
    "preview": "// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>\n//\n// Permission to use, copy, modify, and distribute this sof"
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/common.go",
    "chars": 10364,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/config.go",
    "chars": 12842,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/doc.go",
    "chars": 8527,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/dump.go",
    "chars": 13794,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/format.go",
    "chars": 11314,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/davecgh/go-spew/spew/spew.go",
    "chars": 5969,
    "preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/.gitignore",
    "chars": 201,
    "preview": "# Setup a Global .gitignore for OS and editor generated files:\n# https://help.github.com/articles/ignoring-files\n# git c"
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/.travis.yml",
    "chars": 386,
    "preview": "sudo: false\nlanguage: go\n\ngo:\n  - 1.5.4\n  - 1.6.1\n  - tip\n\nmatrix:\n  allow_failures:\n    - go: tip\n\nbefore_script:\n  - g"
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/AUTHORS",
    "chars": 1479,
    "preview": "# Names should be added to this file as\n#\tName or Organization <email address>\n# The email address is not required for o"
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/CHANGELOG.md",
    "chars": 10615,
    "preview": "# Changelog\n\n## v1.3.0 / 2016-04-19\n\n* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) "
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md",
    "chars": 3973,
    "preview": "# Contributing\n\n## Issues\n\n* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnoti"
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/LICENSE",
    "chars": 1537,
    "preview": "Copyright (c) 2012 The Go Authors. All rights reserved.\nCopyright (c) 2012 fsnotify Authors. All rights reserved.\n\nRedis"
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/README.md",
    "chars": 3005,
    "preview": "# File system notifications for Go\n\n[![GoDoc](https://godoc.org/github.com/fsnotify/fsnotify?status.svg)](https://godoc."
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/fen.go",
    "chars": 935,
    "preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/fsnotify/fsnotify/fsnotify.go",
    "chars": 1472,
    "preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  }
]

// ... and 498 more files (download for full content)

About this extraction

This page contains the full source code of the superkkt/cherry GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 698 files (6.1 MB), approximately 1.6M tokens, and a symbol index with 55883 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!