From 8b4aeeaa8dc507964bbd093bb57f89d2ccaed441 Mon Sep 17 00:00:00 2001 From: Sean DuBois Date: Mon, 25 Mar 2019 15:58:29 -0700 Subject: [PATCH] Docs: Add readme and CI Added the readme and CI using the common style. --- .github/assert-contributors.sh | 45 ++++++++++++++ .github/lint-commit-message.sh | 60 +++++++++++++++++++ .../lint-disallowed-functions-in-library.sh | 16 +++++ .gitignore | 20 +++++++ .golangci.yml | 17 ++++++ .travis.yml | 20 +++++++ LICENSE | 21 +++++++ README.md | 41 +++++++++++++ agent.go | 15 +++-- go.mod | 3 + go.sum | 0 util.go | 32 ++++++++++ util_test.go | 17 ++++++ 13 files changed, 299 insertions(+), 8 deletions(-) create mode 100644 .github/assert-contributors.sh create mode 100644 .github/lint-commit-message.sh create mode 100644 .github/lint-disallowed-functions-in-library.sh create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 util_test.go diff --git a/.github/assert-contributors.sh b/.github/assert-contributors.sh new file mode 100644 index 0000000..b3baa57 --- /dev/null +++ b/.github/assert-contributors.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -e + +# Unshallow the repo, this check doesn't work with this enabled +# https://github.com/travis-ci/travis-ci/issues/3412 +if [ -f $(git rev-parse --git-dir)/shallow ]; then + git fetch --unshallow || true +fi + +SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) + +CONTRIBUTORS=() +EXCLUDED_CONTIBUTORS=('John R. Bradley') +MISSING_CONTIBUTORS=() + +shouldBeIncluded () { + for i in "${EXCLUDED_CONTIBUTORS[@]}" + do + if [ "$i" == "$1" ] ; then + return 1 + fi + done + return 0 +} + + +IFS=$'\n' #Only split on newline +for contributor in $(git log --format='%aN' | sort -u) +do + if shouldBeIncluded $contributor; then + if ! grep -q "$contributor" "$SCRIPT_PATH/../README.md"; then + MISSING_CONTIBUTORS+=("$contributor") + fi + fi +done +unset IFS + +if [ ${#MISSING_CONTIBUTORS[@]} -ne 0 ]; then + echo "Please add the following contributors to the README" + for i in "${MISSING_CONTIBUTORS[@]}" + do + echo "$i" + done + exit 1 +fi diff --git a/.github/lint-commit-message.sh b/.github/lint-commit-message.sh new file mode 100644 index 0000000..df2ea30 --- /dev/null +++ b/.github/lint-commit-message.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -e + +display_commit_message_error() { +cat << EndOfMessage +$1 + +------------------------------------------------- +The preceding commit message is invalid +it failed '$2' of the following checks + +* Separate subject from body with a blank line +* Limit the subject line to 50 characters +* Capitalize the subject line +* Do not end the subject line with a period +* Wrap the body at 72 characters +EndOfMessage + + exit 1 +} + +lint_commit_message() { + if [[ "$(echo "$1" | awk 'NR == 2 {print $1;}' | wc -c)" -ne 1 ]]; then + display_commit_message_error "$1" 'Separate subject from body with a blank line' + fi + + if [[ "$(echo "$1" | head -n1 | wc -m)" -gt 50 ]]; then + display_commit_message_error "$1" 'Limit the subject line to 50 characters' + fi + + if [[ ! $1 =~ ^[A-Z] ]]; then + display_commit_message_error "$1" 'Capitalize the subject line' + fi + + if [[ "$(echo "$1" | awk 'NR == 1 {print substr($0,length($0),1)}')" == "." ]]; then + display_commit_message_error "$1" 'Do not end the subject line with a period' + fi + + if [[ "$(echo "$1" | awk '{print length}' | sort -nr | head -1)" -gt 72 ]]; then + display_commit_message_error "$1" 'Wrap the body at 72 characters' + fi +} + +if [ "$#" -eq 1 ]; then + if [ ! -f "$1" ]; then + echo "$0 was passed one argument, but was not a valid file" + exit 1 + fi + lint_commit_message "$(sed -n '/# Please enter the commit message for your changes. Lines starting/q;p' "$1")" +else + # TRAVIS_COMMIT_RANGE is empty for initial branch commit + if [[ "${TRAVIS_COMMIT_RANGE}" != *"..."* ]]; then + parent=$(git log -n 1 --format="%P" ${TRAVIS_COMMIT_RANGE}) + TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE}...$parent" + fi + + for commit in $(git rev-list ${TRAVIS_COMMIT_RANGE}); do + lint_commit_message "$(git log --format="%B" -n 1 $commit)" + done +fi diff --git a/.github/lint-disallowed-functions-in-library.sh b/.github/lint-disallowed-functions-in-library.sh new file mode 100644 index 0000000..f316c18 --- /dev/null +++ b/.github/lint-disallowed-functions-in-library.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +# Disallow usages of functions that cause the program to exit in the library code +SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +EXCLUDE_DIRECTORIES="--exclude-dir=examples --exclude-dir=.git --exclude-dir=.github " +DISALLOWED_FUNCTIONS=('os.Exit(' 'panic(' 'Fatal(' 'Fatalf(' 'Fatalln(') + + +for disallowedFunction in "${DISALLOWED_FUNCTIONS[@]}" +do + if grep -R $EXCLUDE_DIRECTORIES -e "$disallowedFunction" "$SCRIPT_PATH/.." | grep -v -e '_test.go' -e 'nolint'; then + echo "$disallowedFunction may only be used in example code" + exit 1 + fi +done diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7dd424e --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +### JetBrains IDE ### +##################### +.idea/ + +### Emacs Temporary Files ### +############################# +*~ + +### Folders ### +############### +bin/ +vendor/ +node_modules/ + +### Files ### +############# +tags +cover.out +*.sw[poe] +*.wasm diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..afb7ff5 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,17 @@ +linters-settings: + govet: + check-shadowing: true + misspell: + locale: US + +linters: + enable-all: true + disable: + - lll + - maligned + - gochecknoglobals + +issues: + exclude-use-default: false + max-per-linter: 0 + max-same-issues: 50 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..515a03c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: go + +go: + - "1.x" # use the latest Go release + +env: + - GO111MODULE=on + +before_script: + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0 + - go get github.com/mattn/goveralls + +script: + - golangci-lint run ./... +# - rm -rf examples # Remove examples, no test coverage for them + - go test -coverpkg=$(go list ./... | tr '\n' ',') -coverprofile=cover.out -v -race -covermode=atomic ./... + - goveralls -coverprofile=cover.out -service=travis-ci + - bash .github/assert-contributors.sh + - bash .github/lint-disallowed-functions-in-library.sh + - bash .github/lint-commit-message.sh diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ab60297 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c67e8e --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +

+
+ Pion ICE +
+

+

A Go implementation of ICE

+

+ Pion transport + Slack Widget + Waffle board +
+ Build Status + GoDoc + Coverage Status + Go Report Card + License: MIT +

+
+ +### Roadmap +The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pions/webrtc/issues/9) to track our major milestones. + +### Community +Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). + +We are always looking to support **your projects**. Please reach out if you have something to build! + +If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) + +### Contributing +Check out the **[contributing wiki](https://github.com/pions/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: + +* [John Bradley](https://github.com/kc5nra) - *Original Author* +* [Sean DuBois](https://github.com/Sean-Der) - *Original Author* +* [Michael MacDonald](https://github.com/mjmac) - *Original Author* +* [Michiel De Backker](https://github.com/backkem) - *Original Author* +* [Konstantin Itskov](https://github.com/trivigy) - *Original Author* +* [Luke Curley](https://github.com/kixelated) + +### License +MIT License - see [LICENSE](LICENSE) for full text diff --git a/agent.go b/agent.go index 0139b15..efc4b34 100644 --- a/agent.go +++ b/agent.go @@ -15,7 +15,6 @@ import ( "github.com/pions/logging" "github.com/pions/stun" "github.com/pions/transport/packetio" - "github.com/pions/webrtc/internal/util" ) const ( @@ -139,8 +138,8 @@ func NewAgent(config *AgentConfig) (*Agent, error) { localCandidates: make(map[NetworkType][]*Candidate), remoteCandidates: make(map[NetworkType][]*Candidate), - localUfrag: util.RandSeq(16), - localPwd: util.RandSeq(32), + localUfrag: randSeq(16), + localPwd: randSeq(32), taskChan: make(chan task), onConnected: make(chan struct{}), buffer: packetio.NewBuffer(), @@ -294,7 +293,7 @@ func allocateUDP(network string, url *URL) (*net.UDPAddr, *stun.XorAddress, erro // TODO Do we want the timeout to be configurable? client, err := stun.NewClient(network, fmt.Sprintf("%s:%d", url.Host, url.Port), time.Second*5) if err != nil { - return nil, nil, util.FlattenErrs([]error{errors.New("failed to create STUN client"), err}) + return nil, nil, flattenErrs([]error{errors.New("failed to create STUN client"), err}) } localAddr, ok := client.LocalAddr().(*net.UDPAddr) if !ok { @@ -303,11 +302,11 @@ func allocateUDP(network string, url *URL) (*net.UDPAddr, *stun.XorAddress, erro resp, err := client.Request() if err != nil { - return nil, nil, util.FlattenErrs([]error{errors.New("failed to make STUN request"), err}) + return nil, nil, flattenErrs([]error{errors.New("failed to make STUN request"), err}) } if err = client.Close(); err != nil { - return nil, nil, util.FlattenErrs([]error{errors.New("failed to close STUN client"), err}) + return nil, nil, flattenErrs([]error{errors.New("failed to close STUN client"), err}) } attr, ok := resp.GetOneAttribute(stun.AttrXORMappedAddress) @@ -317,7 +316,7 @@ func allocateUDP(network string, url *URL) (*net.UDPAddr, *stun.XorAddress, erro var addr stun.XorAddress if err = addr.Unpack(resp, attr); err != nil { - return nil, nil, util.FlattenErrs([]error{errors.New("failed to unpack STUN XorAddress response"), err}) + return nil, nil, flattenErrs([]error{errors.New("failed to unpack STUN XorAddress response"), err}) } return localAddr, &addr, nil @@ -732,7 +731,7 @@ func (a *Agent) handleNewPeerReflexiveCandidate(local *Candidate, remote net.Add ) if err != nil { - return util.FlattenErrs([]error{fmt.Errorf("failed to create peer-reflexive candidate: %v", remote), err}) + return flattenErrs([]error{fmt.Errorf("failed to create peer-reflexive candidate: %v", remote), err}) } // Add pflxCandidate to the remote candidate list diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..35cdfca --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/pions/ice + +go 1.12 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/util.go b/util.go index 9de782a..0d565f2 100644 --- a/util.go +++ b/util.go @@ -1,8 +1,12 @@ package ice import ( + "fmt" + "math/rand" "net" + "strings" "sync/atomic" + "time" ) func localInterfaces(networkTypes []NetworkType) (ips []net.IP) { @@ -95,3 +99,31 @@ func isZeros(ip net.IP) bool { } return true } + +// RandSeq generates a random alpha numeric sequence of the requested length +func randSeq(n int) string { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + b := make([]rune, n) + for i := range b { + b[i] = letters[r.Intn(len(letters))] + } + return string(b) +} + +// flattenErrs flattens multiple errors into one +func flattenErrs(errs []error) error { + var errstrings []string + + for _, err := range errs { + if err != nil { + errstrings = append(errstrings, err.Error()) + } + } + + if len(errstrings) == 0 { + return nil + } + + return fmt.Errorf(strings.Join(errstrings, "\n")) +} diff --git a/util_test.go b/util_test.go new file mode 100644 index 0000000..83f1ca9 --- /dev/null +++ b/util_test.go @@ -0,0 +1,17 @@ +package ice + +import ( + "regexp" + "testing" +) + +func TestRandSeq(t *testing.T) { + if len(randSeq(10)) != 10 { + t.Errorf("randSeq return invalid length") + } + + var isLetter = regexp.MustCompile(`^[a-zA-Z]+$`).MatchString + if !isLetter(randSeq(10)) { + t.Errorf("randSeq should be AlphaNumeric only") + } +}