pax_global_header00006660000000000000000000000064137030706630014517gustar00rootroot0000000000000052 comment=3e7aefb6fd280d89fca72f1596348f1939525187 randutil-0.1.0/000077500000000000000000000000001370307066300133375ustar00rootroot00000000000000randutil-0.1.0/.github/000077500000000000000000000000001370307066300146775ustar00rootroot00000000000000randutil-0.1.0/.github/assert-contributors.sh000077500000000000000000000030471370307066300212760ustar00rootroot00000000000000#!/usr/bin/env bash # # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # 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 ) if [ -f ${SCRIPT_PATH}/.ci.conf ] then . ${SCRIPT_PATH}/.ci.conf fi # # DO NOT EDIT THIS # EXCLUDED_CONTRIBUTORS+=('John R. Bradley' 'renovate[bot]' 'Renovate Bot' 'Pion Bot') # If you want to exclude a name from all repositories, send a PR to # https://github.com/pion/.goassets instead of this repository. # If you want to exclude a name only from this repository, # add EXCLUDED_CONTRIBUTORS=('name') to .github/.ci.conf MISSING_CONTRIBUTORS=() shouldBeIncluded () { for i in "${EXCLUDED_CONTRIBUTORS[@]}" 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_CONTRIBUTORS+=("$contributor") fi fi done unset IFS if [ ${#MISSING_CONTRIBUTORS[@]} -ne 0 ]; then echo "Please add the following contributors to the README" for i in "${MISSING_CONTRIBUTORS[@]}" do echo "$i" done exit 1 fi randutil-0.1.0/.github/hooks/000077500000000000000000000000001370307066300160225ustar00rootroot00000000000000randutil-0.1.0/.github/hooks/commit-msg.sh000077500000000000000000000002671370307066300204420ustar00rootroot00000000000000#!/usr/bin/env bash # # DO NOT EDIT THIS FILE DIRECTLY # # It is automatically copied from https://github.com/pion/.goassets repository. # set -e .github/lint-commit-message.sh $1 randutil-0.1.0/.github/hooks/pre-commit.sh000077500000000000000000000003331370307066300204340ustar00rootroot00000000000000#!/bin/sh # # DO NOT EDIT THIS FILE DIRECTLY # # It is automatically copied from https://github.com/pion/.goassets repository. # # Redirect output to stderr. exec 1>&2 .github/lint-disallowed-functions-in-library.sh randutil-0.1.0/.github/hooks/pre-push.sh000077500000000000000000000002621370307066300201240ustar00rootroot00000000000000#!/bin/sh # # DO NOT EDIT THIS FILE DIRECTLY # # It is automatically copied from https://github.com/pion/.goassets repository. # set -e .github/assert-contributors.sh exit 0 randutil-0.1.0/.github/install-hooks.sh000077500000000000000000000010361370307066300200250ustar00rootroot00000000000000#!/bin/bash # # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) cp "$SCRIPT_PATH/hooks/commit-msg.sh" "$SCRIPT_PATH/../.git/hooks/commit-msg" cp "$SCRIPT_PATH/hooks/pre-commit.sh" "$SCRIPT_PATH/../.git/hooks/pre-commit" cp "$SCRIPT_PATH/hooks/pre-push.sh" "$SCRIPT_PATH/../.git/hooks/pre-push" randutil-0.1.0/.github/lint-commit-message.sh000077500000000000000000000041561370307066300211220ustar00rootroot00000000000000#!/usr/bin/env bash # # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # 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 | awk '{print length}')" -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 randutil-0.1.0/.github/lint-disallowed-functions-in-library.sh000077500000000000000000000023311370307066300244040ustar00rootroot00000000000000#!/usr/bin/env bash # # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # 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 ) if [ -f ${SCRIPT_PATH}/.ci.conf ] then . ${SCRIPT_PATH}/.ci.conf fi EXCLUDE_DIRECTORIES=${DISALLOWED_FUNCTIONS_EXCLUDED_DIRECTORIES:-"examples"} DISALLOWED_FUNCTIONS=('os.Exit(' 'panic(' 'Fatal(' 'Fatalf(' 'Fatalln(' 'fmt.Println(' 'fmt.Printf(' 'log.Print(' 'log.Println(' 'log.Printf(') files=$( find "$SCRIPT_PATH/.." -name "*.go" \ | grep -v -e '^.*_test.go$' \ | while read file do excluded=false for ex in $EXCLUDE_DIRECTORIES do if [[ $file == */$ex/* ]] then excluded=true break fi done $excluded || echo "$file" done ) for disallowedFunction in "${DISALLOWED_FUNCTIONS[@]}" do if grep -e "$disallowedFunction" $files | grep -v -e 'nolint'; then echo "$disallowedFunction may only be used in example code" exit 1 fi done randutil-0.1.0/.github/lint-filename.sh000077500000000000000000000012041370307066300177570ustar00rootroot00000000000000#!/usr/bin/env bash # # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # set -e SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) GO_REGEX="^[a-zA-Z][a-zA-Z0-9_]*\.go$" find "$SCRIPT_PATH/.." -name "*.go" | while read fullpath; do filename=$(basename -- "$fullpath") if ! [[ $filename =~ $GO_REGEX ]]; then echo "$filename is not a valid filename for Go code, only alpha, numbers and underscores are supported" exit 1 fi done randutil-0.1.0/.github/workflows/000077500000000000000000000000001370307066300167345ustar00rootroot00000000000000randutil-0.1.0/.github/workflows/renovate-go-mod-fix.yaml000066400000000000000000000015401370307066300234070ustar00rootroot00000000000000# # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # If this repository should have package specific CI config, # remove the repository name from .goassets/.github/workflows/assets-sync.yml. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # name: go-mod-fix on: push: branches: - renovate/* jobs: go-mod-fix: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v2 with: fetch-depth: 2 - name: fix uses: at-wat/go-sum-fix-action@v0 with: git_user: Pion Bot git_email: 59523206+pionbot@users.noreply.github.com github_token: ${{ secrets.GITHUB_TOKEN }} commit_style: squash push: force randutil-0.1.0/.travis.yml000066400000000000000000000106121370307066300154500ustar00rootroot00000000000000# # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # If this repository should have package specific CI config, # remove the repository name from .goassets/.github/workflows/assets-sync.yml. # # If you want to update the shared CI config, send a PR to # https://github.com/pion/.goassets instead of this repository. # dist: bionic language: go branches: only: - master env: global: - GO111MODULE=on - GOLANGCI_LINT_VERSION=1.19.1 cache: directories: - ${HOME}/.cache/go-build - ${GOPATH}/pkg/mod npm: true yarn: true _lint_job: &lint_job env: CACHE_NAME=lint before_install: - if [ -f .github/.ci.conf ]; then . .github/.ci.conf; fi install: skip before_script: - | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \ | bash -s - -b $GOPATH/bin v${GOLANGCI_LINT_VERSION} script: - bash .github/assert-contributors.sh - bash .github/lint-disallowed-functions-in-library.sh - bash .github/lint-commit-message.sh - bash .github/lint-filename.sh - golangci-lint run ./... _test_job: &test_job env: CACHE_NAME=test before_install: - if [ -f .github/.ci.conf ]; then . .github/.ci.conf; fi - go mod download install: - go build ./... script: # If you want to specify repository specific test packages rule, # add `TEST_PACKAGES=$(command to list test target packages)` to .github/.ci.conf - testpkgs=${TEST_PACKAGES:-$(go list ./... | grep -v examples)} - coverpkgs=$(echo "${testpkgs}" | paste -s -d ',') - | go test \ -coverpkg=${coverpkgs} -coverprofile=cover.out -covermode=atomic \ ${TEST_EXTRA_ARGS:-} \ -v -race ${testpkgs} - if [ -n "${TEST_HOOK}" ]; then ${TEST_HOOK}; fi after_success: - travis_retry bash <(curl -s https://codecov.io/bash) -c -F go _test_i386_job: &test_i386_job env: CACHE_NAME=test386 services: docker before_install: - if [ -f .github/.ci.conf ]; then . .github/.ci.conf; fi script: - testpkgs=${TEST_PACKAGES:-$(go list ./... | grep -v examples)} - | docker run \ -u $(id -u):$(id -g) \ -e "GO111MODULE=on" \ -e "CGO_ENABLED=0" \ -v ${PWD}:/go/src/github.com/pion/$(basename ${PWD}) \ -v ${HOME}/gopath/pkg/mod:/go/pkg/mod \ -v ${HOME}/.cache/go-build:/.cache/go-build \ -w /go/src/github.com/pion/$(basename ${PWD}) \ -it i386/golang:${GO_VERSION}-alpine \ /usr/local/go/bin/go test \ ${TEST_EXTRA_ARGS:-} \ -v ${testpkgs} _test_wasm_job: &test_wasm_job env: CACHE_NAME=wasm language: node_js node_js: 12 before_install: - if [ -f .github/.ci.conf ]; then . .github/.ci.conf; fi - if ${SKIP_WASM_TEST:-false}; then exit 0; fi install: # Manually download and install Go instead of using gimme. # It looks like gimme Go causes some errors on go-test for Wasm. - curl -sSfL https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz | tar -C ~ -xzf - - export GOROOT=${HOME}/go - export PATH=${GOROOT}/bin:${PATH} - yarn install - export GO_JS_WASM_EXEC=${GO_JS_WASM_EXEC:-${GOROOT}/misc/wasm/go_js_wasm_exec} script: - testpkgs=${TEST_PACKAGES:-$(go list ./... | grep -v examples)} - coverpkgs=$(echo "${testpkgs}" | paste -s -d ',') - | GOOS=js GOARCH=wasm go test \ -coverpkg=${coverpkgs} -coverprofile=cover.out -covermode=atomic \ -exec="${GO_JS_WASM_EXEC}" \ -v ${testpkgs} after_success: - travis_retry bash <(curl -s https://codecov.io/bash) -c -F wasm jobs: include: - <<: *lint_job name: Lint 1.14 go: 1.14 - <<: *test_job name: Test 1.13 go: 1.13 - <<: *test_job name: Test 1.14 go: 1.14 - <<: *test_i386_job name: Test i386 1.13 env: GO_VERSION=1.13 go: 1.14 # Go version for host environment only for `go list`. # All tests are done on the version specified by GO_VERSION. - <<: *test_i386_job name: Test i386 1.14 env: GO_VERSION=1.14 go: 1.14 # Go version for host environment only for `go list`. # All tests are done on the version specified by GO_VERSION. - <<: *test_wasm_job name: Test WASM 1.13 env: GO_VERSION=1.13 - <<: *test_wasm_job name: Test WASM 1.14 env: GO_VERSION=1.14 notifications: email: false randutil-0.1.0/LICENSE000066400000000000000000000020451370307066300143450ustar00rootroot00000000000000MIT License Copyright (c) 2020 Pion 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. randutil-0.1.0/README.md000066400000000000000000000014341370307066300146200ustar00rootroot00000000000000# randutil Helper library for cryptographic and mathmatical randoms ### 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/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: * [Atsushi Watanabe](https://github.com/at-wat) - *Original Author* randutil-0.1.0/codecov.yml000066400000000000000000000005521370307066300155060ustar00rootroot00000000000000# # DO NOT EDIT THIS FILE # # It is automatically copied from https://github.com/pion/.goassets repository. # coverage: status: project: default: # Allow decreasing 2% of total coverage to avoid noise. threshold: 2% patch: default: target: 70% only_pulls: true ignore: - "examples/*" - "examples/**/*" randutil-0.1.0/crypto.go000066400000000000000000000012551370307066300152110ustar00rootroot00000000000000package randutil import ( crand "crypto/rand" "encoding/binary" "math/big" ) // GenerateCryptoRandomString generates a random string for cryptographic usage. func GenerateCryptoRandomString(n int, runes string) (string, error) { letters := []rune(runes) b := make([]rune, n) for i := range b { v, err := crand.Int(crand.Reader, big.NewInt(int64(len(letters)))) if err != nil { return "", err } b[i] = letters[v.Int64()] } return string(b), nil } // CryptoUint64 returns cryptographic random uint64. func CryptoUint64() (uint64, error) { var v uint64 if err := binary.Read(crand.Reader, binary.LittleEndian, &v); err != nil { return 0, err } return v, nil } randutil-0.1.0/crypto_test.go000066400000000000000000000015621370307066300162510ustar00rootroot00000000000000package randutil import ( "regexp" "testing" ) func TestCryptoRandomGenerator(t *testing.T) { isLetter := regexp.MustCompile(`^[a-zA-Z]+$`).MatchString for i := 0; i < 10000; i++ { s, err := GenerateCryptoRandomString(10, runesAlpha) if err != nil { t.Error(err) } if len(s) != 10 { t.Error("Generator returned invalid length") } if !isLetter(s) { t.Errorf("Generator returned unexpected character: %s", s) } } } func TestCryptoUint64(t *testing.T) { min := uint64(0xFFFFFFFFFFFFFFFF) max := uint64(0) for i := 0; i < 10000; i++ { r, err := CryptoUint64() if err != nil { t.Fatal(err) } if r < min { min = r } if r > max { max = r } } if min > 0x1000000000000000 { t.Error("Value around lower boundary was not generated") } if max < 0xF000000000000000 { t.Error("Value around upper boundary was not generated") } } randutil-0.1.0/go.mod000066400000000000000000000000511370307066300144410ustar00rootroot00000000000000module github.com/pion/randutil go 1.14 randutil-0.1.0/math.go000066400000000000000000000031721370307066300146220ustar00rootroot00000000000000package randutil import ( mrand "math/rand" // used for non-crypto unique ID and random port selection "sync" "time" ) // MathRandomGenerator is a random generator for non-crypto usage. type MathRandomGenerator interface { // Intn returns random integer within [0:n). Intn(n int) int // Uint32 returns random 32-bit unsigned integer. Uint32() uint32 // Uint64 returns random 64-bit unsigned integer. Uint64() uint64 // GenerateString returns ranom string using given set of runes. // It can be used for generating unique ID to avoid name collision. // // Caution: DO NOT use this for cryptographic usage. GenerateString(n int, runes string) string } type mathRandomGenerator struct { r *mrand.Rand mu sync.Mutex } // NewMathRandomGenerator creates new mathmatical random generator. // Random generator is seeded by crypto random. func NewMathRandomGenerator() MathRandomGenerator { seed, err := CryptoUint64() if err != nil { // crypto/rand is unavailable. Fallback to seed by time. seed = uint64(time.Now().UnixNano()) } return &mathRandomGenerator{r: mrand.New(mrand.NewSource(int64(seed)))} } func (g *mathRandomGenerator) Intn(n int) int { g.mu.Lock() v := g.r.Intn(n) g.mu.Unlock() return v } func (g *mathRandomGenerator) Uint32() uint32 { g.mu.Lock() v := g.r.Uint32() g.mu.Unlock() return v } func (g *mathRandomGenerator) Uint64() uint64 { g.mu.Lock() v := g.r.Uint64() g.mu.Unlock() return v } func (g *mathRandomGenerator) GenerateString(n int, runes string) string { letters := []rune(runes) b := make([]rune, n) for i := range b { b[i] = letters[g.Intn(len(letters))] } return string(b) } randutil-0.1.0/math_test.go000066400000000000000000000031741370307066300156630ustar00rootroot00000000000000package randutil import ( "regexp" "testing" ) func TestMathRandomGenerator(t *testing.T) { g := NewMathRandomGenerator() isLetter := regexp.MustCompile(`^[a-zA-Z]+$`).MatchString for i := 0; i < 10000; i++ { s := g.GenerateString(10, runesAlpha) if len(s) != 10 { t.Error("Generator returned invalid length") } if !isLetter(s) { t.Errorf("Generator returned unexpected character: %s", s) } } } func TestIntn(t *testing.T) { g := NewMathRandomGenerator() min := 100 max := 0 for i := 0; i < 10000; i++ { r := g.Intn(100) if r < 0 || r >= 100 { t.Fatalf("Out of range of Intn(100): %d", r) } if r < min { min = r } if r > max { max = r } } if min > 10 { t.Error("Value around lower boundary was not generated") } if max < 90 { t.Error("Value around upper boundary was not generated") } } func TestUint64(t *testing.T) { g := NewMathRandomGenerator() min := uint64(0xFFFFFFFFFFFFFFFF) max := uint64(0) for i := 0; i < 10000; i++ { r := g.Uint64() if r < min { min = r } if r > max { max = r } } if min > 0x1000000000000000 { t.Error("Value around lower boundary was not generated") } if max < 0xF000000000000000 { t.Error("Value around upper boundary was not generated") } } func TestUint32(t *testing.T) { g := NewMathRandomGenerator() min := uint32(0xFFFFFFFF) max := uint32(0) for i := 0; i < 10000; i++ { r := g.Uint32() if r < min { min = r } if r > max { max = r } } if min > 0x10000000 { t.Error("Value around lower boundary was not generated") } if max < 0xF0000000 { t.Error("Value around upper boundary was not generated") } } randutil-0.1.0/rand_test.go000066400000000000000000000024571370307066300156610ustar00rootroot00000000000000package randutil import ( "sync" "testing" ) const runesAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" func TestRandomGeneratorCollision(t *testing.T) { g := NewMathRandomGenerator() testCases := map[string]struct { gen func(t *testing.T) string }{ "MathRandom": { gen: func(t *testing.T) string { return g.GenerateString(10, runesAlpha) }, }, "CryptoRandom": { gen: func(t *testing.T) string { s, err := GenerateCryptoRandomString(10, runesAlpha) if err != nil { t.Fatal(err) } return s }, }, } const N = 100 const iteration = 100 for name, testCase := range testCases { testCase := testCase t.Run(name, func(t *testing.T) { for iter := 0; iter < iteration; iter++ { var wg sync.WaitGroup var mu sync.Mutex rands := make([]string, 0, N) for i := 0; i < N; i++ { wg.Add(1) go func() { r := testCase.gen(t) mu.Lock() rands = append(rands, r) mu.Unlock() wg.Done() }() } wg.Wait() if len(rands) != N { t.Fatal("Failed to generate randoms") } for i := 0; i < N; i++ { for j := i + 1; j < N; j++ { if rands[i] == rands[j] { t.Fatalf("generateRandString caused collision: %s == %s", rands[i], rands[j]) } } } } }) } } randutil-0.1.0/renovate.json000066400000000000000000000004111370307066300160510ustar00rootroot00000000000000{ "extends": [ "config:base" ], "postUpdateOptions": [ "gomodTidy" ], "commitBody": "Generated by renovateBot", "packageRules": [ { "packagePatterns": ["^golang.org/x/"], "schedule": ["on the first day of the month"] } ] }