├── go.sum ├── go.mod ├── websocket ├── AUTHORS ├── mask_safe.go ├── client_clone.go ├── conn_read.go ├── conn_read_legacy.go ├── LICENSE ├── mask.go ├── example_test.go ├── client_clone_legacy.go ├── server_test.go ├── json.go ├── mask_test.go ├── prepared_test.go ├── compression_test.go ├── client_test.go ├── json_test.go ├── util_test.go ├── prepared.go ├── conn_broadcast_test.go ├── compression.go └── util.go ├── .travis.yml ├── .gitignore ├── doc └── README.md ├── https ├── acme │ ├── utils.go │ ├── challenges.go │ ├── LICENSE │ ├── http_challenge.go │ ├── provider.go │ ├── tls_sni_challenge_server.go │ ├── error.go │ ├── tls_sni_challenge.go │ ├── jws.go │ ├── http_challenge_server.go │ ├── http.go │ └── messages.go ├── jose │ ├── doc.go │ ├── utils.go │ ├── cipher │ │ ├── concat_kdf.go │ │ ├── ecdh_es.go │ │ ├── key_wrap.go │ │ └── cbc_hmac.go │ ├── encoding.go │ └── signing.go ├── https_test.go ├── letsencrypt │ └── LICENSE ├── net │ └── context │ │ ├── go17.go │ │ └── context.go ├── https.go └── example_test.go ├── test.sh ├── LICENSE ├── avc └── example_test.go ├── amf0 └── example_test.go ├── logger ├── logger_test.go ├── pre_go17.go ├── go17.go ├── example_test.go └── example_go17_test.go ├── options ├── options_test.go ├── example_test.go └── options.go ├── errors ├── bench_test.go ├── LICENSE ├── README.md ├── stack.go └── example_test.go ├── kxps ├── doc.go ├── example_test.go ├── krps.go ├── kbps.go ├── kxps_test.go └── kxps.go ├── aac ├── example_test.go └── aac_test.go ├── flv └── example_test.go ├── rtmp └── example_test.go ├── http ├── api.go └── example_test.go ├── README.md └── json ├── example_test.go └── json.go /go.sum: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ossrs/go-oryx-lib 2 | 3 | go 1.4.0 4 | -------------------------------------------------------------------------------- /websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Joachim Bauch 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.7 6 | - 1.8 7 | 8 | before_install: 9 | - go get -t -v ./... 10 | 11 | script: 12 | - bash test.sh 13 | 14 | after_success: 15 | - bash <(curl -s https://codecov.io/bash) 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | *.aar 6 | 7 | # Folders 8 | _obj 9 | _test 10 | .idea 11 | .gradle 12 | 13 | # Architecture specific extensions/prefixes 14 | *.[568vq] 15 | [568vq].out 16 | 17 | *.cgo1.go 18 | *.cgo2.c 19 | _cgo_defun.c 20 | _cgo_gotypes.go 21 | _cgo_export.* 22 | 23 | _testmain.go 24 | 25 | *.exe 26 | *.test 27 | *.prof 28 | 29 | # Coverage files 30 | *.txt 31 | 32 | .DS_Store 33 | -------------------------------------------------------------------------------- /websocket/mask_safe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build appengine 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | func maskBytes(key [4]byte, pos int, b []byte) int { 11 | for i := range b { 12 | b[i] ^= key[pos&3] 13 | pos++ 14 | } 15 | return pos & 3 16 | } 17 | -------------------------------------------------------------------------------- /websocket/client_clone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import "crypto/tls" 11 | 12 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 13 | if cfg == nil { 14 | return &tls.Config{} 15 | } 16 | return cfg.Clone() 17 | } 18 | -------------------------------------------------------------------------------- /websocket/conn_read.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.5 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import "io" 11 | 12 | func (c *Conn) read(n int) ([]byte, error) { 13 | p, err := c.br.Peek(n) 14 | if err == io.EOF { 15 | err = errUnexpectedEOF 16 | } 17 | c.br.Discard(len(p)) 18 | return p, err 19 | } 20 | -------------------------------------------------------------------------------- /websocket/conn_read_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.5 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import "io" 11 | 12 | func (c *Conn) read(n int) ([]byte, error) { 13 | p, err := c.br.Peek(n) 14 | if err == io.EOF { 15 | err = errUnexpectedEOF 16 | } 17 | if len(p) > 0 { 18 | // advance over the bytes just read 19 | io.ReadFull(c.br, p) 20 | } 21 | return p, err 22 | } 23 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | # DOC 2 | 3 | The documents refered by this project: 4 | 5 | 1. [rtmp_specification_1.0.pdf](https://github.com/ossrs/srs/blob/2.0release/trunk/doc/rtmp_specification_1.0.pdf) 6 | 1. [amf0_spec_121207.pdf](https://github.com/ossrs/srs/blob/2.0release/trunk/doc/amf0_spec_121207.pdf) 7 | 1. [video_file_format_spec_v10.pdf](https://github.com/ossrs/srs/blob/2.0release/trunk/doc/video_file_format_spec_v10_1.pdf) 8 | 1. [ISO_IEC_14496-3-AAC-2001.pdf](https://github.com/ossrs/srs/blob/2.0release/trunk/doc/ISO_IEC_14496-3-AAC-2001.pdf) 9 | 1. [ISO_IEC_13818-7-AAC-2004.pdf](https://github.com/ossrs/srs/blob/2.0release/trunk/doc/ISO_IEC_13818-7-AAC-2004.pdf) 10 | 1. [RFC3261](https://www.ietf.org/rfc/rfc3261.txt), SIP(Session Initiation Protocol) 11 | -------------------------------------------------------------------------------- /https/acme/utils.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | // WaitFor polls the given function 'f', once every 'interval', up to 'timeout'. 11 | func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error { 12 | var lastErr string 13 | timeup := time.After(timeout) 14 | for { 15 | select { 16 | case <-timeup: 17 | return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr) 18 | default: 19 | } 20 | 21 | stop, err := f() 22 | if stop { 23 | return nil 24 | } 25 | if err != nil { 26 | lastErr = err.Error() 27 | } 28 | 29 | time.Sleep(interval) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | go test -race -v ./... 4 | ret=$?; if [[ $ret -ne 0 && $ret -ne 1 ]]; then 5 | echo "Test failed, exit $ret" 6 | exit $ret 7 | fi 8 | 9 | echo "mode: atomic" > coverage.txt 10 | 11 | function coverage() { 12 | go test $1 -race -coverprofile=tmp.txt -covermode=atomic 13 | ret=$?; if [[ $ret -eq 0 ]]; then 14 | cat tmp.txt >> coverage.txt 15 | rm -f tmp.txt 16 | fi 17 | } 18 | 19 | coverage github.com/ossrs/go-oryx-lib/aac 20 | coverage github.com/ossrs/go-oryx-lib/amf0 21 | coverage github.com/ossrs/go-oryx-lib/asprocess 22 | coverage github.com/ossrs/go-oryx-lib/avc 23 | coverage github.com/ossrs/go-oryx-lib/flv 24 | coverage github.com/ossrs/go-oryx-lib/http 25 | coverage github.com/ossrs/go-oryx-lib/https 26 | coverage github.com/ossrs/go-oryx-lib/json 27 | coverage github.com/ossrs/go-oryx-lib/kxps 28 | coverage github.com/ossrs/go-oryx-lib/logger 29 | coverage github.com/ossrs/go-oryx-lib/options 30 | coverage github.com/ossrs/go-oryx-lib/rtmp 31 | -------------------------------------------------------------------------------- /https/acme/challenges.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | // Challenge is a string that identifies a particular type and version of ACME challenge. 6 | type Challenge string 7 | 8 | const ( 9 | // HTTP01 is the "http-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http 10 | // Note: HTTP01ChallengePath returns the URL path to fulfill this challenge 11 | HTTP01 = Challenge("http-01") 12 | // TLSSNI01 is the "tls-sni-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni 13 | // Note: TLSSNI01ChallengeCert returns a certificate to fulfill this challenge 14 | TLSSNI01 = Challenge("tls-sni-01") 15 | // DNS01 is the "dns-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#dns 16 | // Note: DNS01Record returns a DNS record which will fulfill this challenge 17 | DNS01 = Challenge("dns-01") 18 | ) 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2017 winlin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /https/acme/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sebastian Erhart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /https/jose/doc.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | 19 | Package jose aims to provide an implementation of the Javascript Object Signing 20 | and Encryption set of standards. For the moment, it mainly focuses on 21 | encryption and signing based on the JSON Web Encryption and JSON Web Signature 22 | standards. The library supports both the compact and full serialization 23 | formats, and has optional support for multiple recipients. 24 | 25 | */ 26 | // from gopkg.in/square/go-jose.v1 27 | package jose // import "github.com/ossrs/go-oryx-lib/https/jose" 28 | -------------------------------------------------------------------------------- /avc/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package avc_test 23 | -------------------------------------------------------------------------------- /amf0/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package amf0_test 23 | -------------------------------------------------------------------------------- /https/https_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package https 23 | 24 | import "testing" 25 | 26 | func TestHttps(t *testing.T) { 27 | } 28 | -------------------------------------------------------------------------------- /logger/logger_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package logger 23 | 24 | import "testing" 25 | 26 | func TestLogger(t *testing.T) { 27 | } 28 | -------------------------------------------------------------------------------- /options/options_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package options 23 | 24 | import "testing" 25 | 26 | func TestOptions(t *testing.T) { 27 | } 28 | -------------------------------------------------------------------------------- /errors/bench_test.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package errors 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | 9 | stderrors "errors" 10 | ) 11 | 12 | func noErrors(at, depth int) error { 13 | if at >= depth { 14 | return stderrors.New("no error") 15 | } 16 | return noErrors(at+1, depth) 17 | } 18 | 19 | func yesErrors(at, depth int) error { 20 | if at >= depth { 21 | return New("ye error") 22 | } 23 | return yesErrors(at+1, depth) 24 | } 25 | 26 | // GlobalE is an exported global to store the result of benchmark results, 27 | // preventing the compiler from optimising the benchmark functions away. 28 | var GlobalE error 29 | 30 | func BenchmarkErrors(b *testing.B) { 31 | type run struct { 32 | stack int 33 | std bool 34 | } 35 | runs := []run{ 36 | {10, false}, 37 | {10, true}, 38 | {100, false}, 39 | {100, true}, 40 | {1000, false}, 41 | {1000, true}, 42 | } 43 | for _, r := range runs { 44 | part := "pkg/errors" 45 | if r.std { 46 | part = "errors" 47 | } 48 | name := fmt.Sprintf("%s-stack-%d", part, r.stack) 49 | b.Run(name, func(b *testing.B) { 50 | var err error 51 | f := yesErrors 52 | if r.std { 53 | f = noErrors 54 | } 55 | b.ReportAllocs() 56 | for i := 0; i < b.N; i++ { 57 | err = f(0, r.stack) 58 | } 59 | b.StopTimer() 60 | GlobalE = err 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /https/acme/http_challenge.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | ) 9 | 10 | type httpChallenge struct { 11 | jws *jws 12 | validate validateFunc 13 | provider ChallengeProvider 14 | } 15 | 16 | // HTTP01ChallengePath returns the URL path for the `http-01` challenge 17 | func HTTP01ChallengePath(token string) string { 18 | return "/.well-known/acme-challenge/" + token 19 | } 20 | 21 | func (s *httpChallenge) Solve(chlng challenge, domain string) error { 22 | 23 | logf("[INFO][%s] acme: Trying to solve HTTP-01", domain) 24 | 25 | // Generate the Key Authorization for the challenge 26 | keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | err = s.provider.Present(domain, chlng.Token, keyAuth) 32 | if err != nil { 33 | return fmt.Errorf("[%s] error presenting token: %v", domain, err) 34 | } 35 | defer func() { 36 | err := s.provider.CleanUp(domain, chlng.Token, keyAuth) 37 | if err != nil { 38 | log.Printf("[%s] error cleaning up: %v", domain, err) 39 | } 40 | }() 41 | 42 | return s.validate(s.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth}) 43 | } 44 | -------------------------------------------------------------------------------- /errors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /https/acme/provider.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import "time" 6 | 7 | // ChallengeProvider enables implementing a custom challenge 8 | // provider. Present presents the solution to a challenge available to 9 | // be solved. CleanUp will be called by the challenge if Present ends 10 | // in a non-error state. 11 | type ChallengeProvider interface { 12 | Present(domain, token, keyAuth string) error 13 | CleanUp(domain, token, keyAuth string) error 14 | } 15 | 16 | // ChallengeProviderTimeout allows for implementing a 17 | // ChallengeProvider where an unusually long timeout is required when 18 | // waiting for an ACME challenge to be satisfied, such as when 19 | // checking for DNS record progagation. If an implementor of a 20 | // ChallengeProvider provides a Timeout method, then the return values 21 | // of the Timeout method will be used when appropriate by the acme 22 | // package. The interval value is the time between checks. 23 | // 24 | // The default values used for timeout and interval are 60 seconds and 25 | // 2 seconds respectively. These are used when no Timeout method is 26 | // defined for the ChallengeProvider. 27 | type ChallengeProviderTimeout interface { 28 | ChallengeProvider 29 | Timeout() (timeout, interval time.Duration) 30 | } 31 | -------------------------------------------------------------------------------- /kxps/doc.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The oryx kxps package provides some kxps, for example: 23 | // N kbps, N k bits per seconds 24 | // N krps, N k requests per seconds 25 | // over some duration for instance 10s, 30s, 5m, average. 26 | package kxps 27 | -------------------------------------------------------------------------------- /websocket/mask.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build !appengine 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import "unsafe" 11 | 12 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 13 | 14 | func maskBytes(key [4]byte, pos int, b []byte) int { 15 | 16 | // Mask one byte at a time for small buffers. 17 | if len(b) < 2*wordSize { 18 | for i := range b { 19 | b[i] ^= key[pos&3] 20 | pos++ 21 | } 22 | return pos & 3 23 | } 24 | 25 | // Mask one byte at a time to word boundary. 26 | if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { 27 | n = wordSize - n 28 | for i := range b[:n] { 29 | b[i] ^= key[pos&3] 30 | pos++ 31 | } 32 | b = b[n:] 33 | } 34 | 35 | // Create aligned word size key. 36 | var k [wordSize]byte 37 | for i := range k { 38 | k[i] = key[(pos+i)&3] 39 | } 40 | kw := *(*uintptr)(unsafe.Pointer(&k)) 41 | 42 | // Mask one word at a time. 43 | n := (len(b) / wordSize) * wordSize 44 | for i := 0; i < n; i += wordSize { 45 | *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw 46 | } 47 | 48 | // Mask one byte at a time for remaining bytes. 49 | b = b[n:] 50 | for i := range b { 51 | b[i] ^= key[pos&3] 52 | pos++ 53 | } 54 | 55 | return pos & 3 56 | } 57 | -------------------------------------------------------------------------------- /logger/pre_go17.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // +build !go1.7 23 | 24 | package logger 25 | 26 | func (v *loggerPlus) Println(ctx Context, a ...interface{}) { 27 | args := v.format(ctx, a...) 28 | v.doPrintln(args...) 29 | } 30 | 31 | func (v *loggerPlus) Printf(ctx Context, format string, a ...interface{}) { 32 | format, args := v.formatf(ctx, format, a...) 33 | v.doPrintf(format, args...) 34 | } 35 | -------------------------------------------------------------------------------- /websocket/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket_test 7 | 8 | import ( 9 | "log" 10 | "net/http" 11 | "testing" 12 | 13 | "github.com/ossrs/go-oryx-lib/websocket" 14 | ) 15 | 16 | var ( 17 | c *websocket.Conn 18 | req *http.Request 19 | ) 20 | 21 | // The websocket.IsUnexpectedCloseError function is useful for identifying 22 | // application and protocol errors. 23 | // 24 | // This server application works with a client application running in the 25 | // browser. The client application does not explicitly close the websocket. The 26 | // only expected close message from the client has the code 27 | // websocket.CloseGoingAway. All other other close messages are likely the 28 | // result of an application or protocol error and are logged to aid debugging. 29 | func ExampleIsUnexpectedCloseError() { 30 | 31 | for { 32 | messageType, p, err := c.ReadMessage() 33 | if err != nil { 34 | if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) { 35 | log.Printf("error: %v, user-agent: %v", err, req.Header.Get("User-Agent")) 36 | } 37 | return 38 | } 39 | processMesage(messageType, p) 40 | } 41 | } 42 | 43 | func processMesage(mt int, p []byte) {} 44 | 45 | // TestX prevents godoc from showing this entire file in the example. Remove 46 | // this function when a second example is added. 47 | func TestX(t *testing.T) {} 48 | -------------------------------------------------------------------------------- /https/letsencrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /websocket/client_clone_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import "crypto/tls" 11 | 12 | // cloneTLSConfig clones all public fields except the fields 13 | // SessionTicketsDisabled and SessionTicketKey. This avoids copying the 14 | // sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a 15 | // config in active use. 16 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 17 | if cfg == nil { 18 | return &tls.Config{} 19 | } 20 | return &tls.Config{ 21 | Rand: cfg.Rand, 22 | Time: cfg.Time, 23 | Certificates: cfg.Certificates, 24 | NameToCertificate: cfg.NameToCertificate, 25 | GetCertificate: cfg.GetCertificate, 26 | RootCAs: cfg.RootCAs, 27 | NextProtos: cfg.NextProtos, 28 | ServerName: cfg.ServerName, 29 | ClientAuth: cfg.ClientAuth, 30 | ClientCAs: cfg.ClientCAs, 31 | InsecureSkipVerify: cfg.InsecureSkipVerify, 32 | CipherSuites: cfg.CipherSuites, 33 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 34 | ClientSessionCache: cfg.ClientSessionCache, 35 | MinVersion: cfg.MinVersion, 36 | MaxVersion: cfg.MaxVersion, 37 | CurvePreferences: cfg.CurvePreferences, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /websocket/server_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "net/http" 10 | "reflect" 11 | "testing" 12 | ) 13 | 14 | var subprotocolTests = []struct { 15 | h string 16 | protocols []string 17 | }{ 18 | {"", nil}, 19 | {"foo", []string{"foo"}}, 20 | {"foo,bar", []string{"foo", "bar"}}, 21 | {"foo, bar", []string{"foo", "bar"}}, 22 | {" foo, bar", []string{"foo", "bar"}}, 23 | {" foo, bar ", []string{"foo", "bar"}}, 24 | } 25 | 26 | func TestSubprotocols(t *testing.T) { 27 | for _, st := range subprotocolTests { 28 | r := http.Request{Header: http.Header{"Sec-Websocket-Protocol": {st.h}}} 29 | protocols := Subprotocols(&r) 30 | if !reflect.DeepEqual(st.protocols, protocols) { 31 | t.Errorf("SubProtocols(%q) returned %#v, want %#v", st.h, protocols, st.protocols) 32 | } 33 | } 34 | } 35 | 36 | var isWebSocketUpgradeTests = []struct { 37 | ok bool 38 | h http.Header 39 | }{ 40 | {false, http.Header{"Upgrade": {"websocket"}}}, 41 | {false, http.Header{"Connection": {"upgrade"}}}, 42 | {true, http.Header{"Connection": {"upgRade"}, "Upgrade": {"WebSocket"}}}, 43 | } 44 | 45 | func TestIsWebSocketUpgrade(t *testing.T) { 46 | for _, tt := range isWebSocketUpgradeTests { 47 | ok := IsWebSocketUpgrade(&http.Request{Header: tt.h}) 48 | if tt.ok != ok { 49 | t.Errorf("IsWebSocketUpgrade(%v) returned %v, want %v", tt.h, ok, tt.ok) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /options/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package options_test 23 | 24 | import ( 25 | "fmt" 26 | oo "github.com/ossrs/go-oryx-lib/options" 27 | "os" 28 | ) 29 | 30 | func ExampleOptions() { 31 | var err error 32 | 33 | // Parse config file from argv: 34 | // ./binary -c file 35 | // ./binary -c conf/oryx.json 36 | configFile := oo.ParseArgv("conf/console.json", "1.0", "GoOryx/1.0") 37 | 38 | var f *os.File 39 | if f, err = os.Open(configFile); err != nil { 40 | fmt.Println("Open config file failed, err is", err) 41 | return 42 | } 43 | defer f.Close() 44 | 45 | // Use the config file. 46 | _ = f 47 | } 48 | -------------------------------------------------------------------------------- /websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "encoding/json" 10 | "io" 11 | ) 12 | 13 | // WriteJSON writes the JSON encoding of v as a message. 14 | // 15 | // Deprecated: Use c.WriteJSON instead. 16 | func WriteJSON(c *Conn, v interface{}) error { 17 | return c.WriteJSON(v) 18 | } 19 | 20 | // WriteJSON writes the JSON encoding of v as a message. 21 | // 22 | // See the documentation for encoding/json Marshal for details about the 23 | // conversion of Go values to JSON. 24 | func (c *Conn) WriteJSON(v interface{}) error { 25 | w, err := c.NextWriter(TextMessage) 26 | if err != nil { 27 | return err 28 | } 29 | err1 := json.NewEncoder(w).Encode(v) 30 | err2 := w.Close() 31 | if err1 != nil { 32 | return err1 33 | } 34 | return err2 35 | } 36 | 37 | // ReadJSON reads the next JSON-encoded message from the connection and stores 38 | // it in the value pointed to by v. 39 | // 40 | // Deprecated: Use c.ReadJSON instead. 41 | func ReadJSON(c *Conn, v interface{}) error { 42 | return c.ReadJSON(v) 43 | } 44 | 45 | // ReadJSON reads the next JSON-encoded message from the connection and stores 46 | // it in the value pointed to by v. 47 | // 48 | // See the documentation for the encoding/json Unmarshal function for details 49 | // about the conversion of JSON to a Go value. 50 | func (c *Conn) ReadJSON(v interface{}) error { 51 | _, r, err := c.NextReader() 52 | if err != nil { 53 | return err 54 | } 55 | err = json.NewDecoder(r).Decode(v) 56 | if err == io.EOF { 57 | // One value is expected in the message. 58 | err = io.ErrUnexpectedEOF 59 | } 60 | return err 61 | } 62 | -------------------------------------------------------------------------------- /https/acme/tls_sni_challenge_server.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "crypto/tls" 7 | "fmt" 8 | "net" 9 | "net/http" 10 | ) 11 | 12 | // TLSProviderServer implements ChallengeProvider for `TLS-SNI-01` challenge 13 | // It may be instantiated without using the NewTLSProviderServer function if 14 | // you want only to use the default values. 15 | type TLSProviderServer struct { 16 | iface string 17 | port string 18 | done chan bool 19 | listener net.Listener 20 | } 21 | 22 | // NewTLSProviderServer creates a new TLSProviderServer on the selected interface and port. 23 | // Setting iface and / or port to an empty string will make the server fall back to 24 | // the "any" interface and port 443 respectively. 25 | func NewTLSProviderServer(iface, port string) *TLSProviderServer { 26 | return &TLSProviderServer{iface: iface, port: port} 27 | } 28 | 29 | // Present makes the keyAuth available as a cert 30 | func (s *TLSProviderServer) Present(domain, token, keyAuth string) error { 31 | if s.port == "" { 32 | s.port = "443" 33 | } 34 | 35 | cert, err := TLSSNI01ChallengeCert(keyAuth) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | tlsConf := new(tls.Config) 41 | tlsConf.Certificates = []tls.Certificate{cert} 42 | 43 | s.listener, err = tls.Listen("tcp", net.JoinHostPort(s.iface, s.port), tlsConf) 44 | if err != nil { 45 | return fmt.Errorf("Could not start HTTPS server for challenge -> %v", err) 46 | } 47 | 48 | s.done = make(chan bool) 49 | go func() { 50 | http.Serve(s.listener, nil) 51 | s.done <- true 52 | }() 53 | return nil 54 | } 55 | 56 | // CleanUp closes the HTTP server. 57 | func (s *TLSProviderServer) CleanUp(domain, token, keyAuth string) error { 58 | if s.listener == nil { 59 | return nil 60 | } 61 | s.listener.Close() 62 | <-s.done 63 | return nil 64 | } 65 | -------------------------------------------------------------------------------- /websocket/mask_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // Require 1.7 for sub-bencmarks 6 | // +build go1.7,!appengine 7 | 8 | // fork from https://github.com/gorilla/websocket 9 | package websocket 10 | 11 | import ( 12 | "fmt" 13 | "testing" 14 | ) 15 | 16 | func maskBytesByByte(key [4]byte, pos int, b []byte) int { 17 | for i := range b { 18 | b[i] ^= key[pos&3] 19 | pos++ 20 | } 21 | return pos & 3 22 | } 23 | 24 | func notzero(b []byte) int { 25 | for i := range b { 26 | if b[i] != 0 { 27 | return i 28 | } 29 | } 30 | return -1 31 | } 32 | 33 | func TestMaskBytes(t *testing.T) { 34 | key := [4]byte{1, 2, 3, 4} 35 | for size := 1; size <= 1024; size++ { 36 | for align := 0; align < wordSize; align++ { 37 | for pos := 0; pos < 4; pos++ { 38 | b := make([]byte, size+align)[align:] 39 | maskBytes(key, pos, b) 40 | maskBytesByByte(key, pos, b) 41 | if i := notzero(b); i >= 0 { 42 | t.Errorf("size:%d, align:%d, pos:%d, offset:%d", size, align, pos, i) 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | func BenchmarkMaskBytes(b *testing.B) { 50 | for _, size := range []int{2, 4, 8, 16, 32, 512, 1024} { 51 | b.Run(fmt.Sprintf("size-%d", size), func(b *testing.B) { 52 | for _, align := range []int{wordSize / 2} { 53 | b.Run(fmt.Sprintf("align-%d", align), func(b *testing.B) { 54 | for _, fn := range []struct { 55 | name string 56 | fn func(key [4]byte, pos int, b []byte) int 57 | }{ 58 | {"byte", maskBytesByByte}, 59 | {"word", maskBytes}, 60 | } { 61 | b.Run(fn.name, func(b *testing.B) { 62 | key := newMaskKey() 63 | data := make([]byte, size+align)[align:] 64 | for i := 0; i < b.N; i++ { 65 | fn.fn(key, 0, data) 66 | } 67 | b.SetBytes(int64(len(data))) 68 | }) 69 | } 70 | }) 71 | } 72 | }) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /kxps/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package kxps_test 23 | 24 | import ( 25 | "github.com/ossrs/go-oryx-lib/kxps" 26 | ) 27 | 28 | func ExampleKrps() { 29 | // user must provides the krps source 30 | var source kxps.KrpsSource 31 | 32 | krps := kxps.NewKrps(nil, source) 33 | defer krps.Close() 34 | 35 | if err := krps.Start(); err != nil { 36 | return 37 | } 38 | 39 | _ = krps.Average() 40 | _ = krps.Rps10s() 41 | _ = krps.Rps30s() 42 | _ = krps.Rps300s() 43 | } 44 | 45 | func ExampleKbps() { 46 | // user must provides the kbps source 47 | var source kxps.KbpsSource 48 | 49 | kbps := kxps.NewKbps(nil, source) 50 | defer kbps.Close() 51 | 52 | if err := kbps.Start(); err != nil { 53 | return 54 | } 55 | 56 | _ = kbps.Average() 57 | _ = kbps.Kbps10s() 58 | _ = kbps.Kbps30s() 59 | _ = kbps.Kbps300s() 60 | } 61 | -------------------------------------------------------------------------------- /https/jose/utils.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1 18 | package jose 19 | 20 | import ( 21 | "crypto/x509" 22 | "encoding/pem" 23 | "fmt" 24 | ) 25 | 26 | // LoadPublicKey loads a public key from PEM/DER-encoded data. 27 | func LoadPublicKey(data []byte) (interface{}, error) { 28 | input := data 29 | 30 | block, _ := pem.Decode(data) 31 | if block != nil { 32 | input = block.Bytes 33 | } 34 | 35 | // Try to load SubjectPublicKeyInfo 36 | pub, err0 := x509.ParsePKIXPublicKey(input) 37 | if err0 == nil { 38 | return pub, nil 39 | } 40 | 41 | cert, err1 := x509.ParseCertificate(input) 42 | if err1 == nil { 43 | return cert.PublicKey, nil 44 | } 45 | 46 | return nil, fmt.Errorf("square/go-jose: parse error, got '%s' and '%s'", err0, err1) 47 | } 48 | 49 | // LoadPrivateKey loads a private key from PEM/DER-encoded data. 50 | func LoadPrivateKey(data []byte) (interface{}, error) { 51 | input := data 52 | 53 | block, _ := pem.Decode(data) 54 | if block != nil { 55 | input = block.Bytes 56 | } 57 | 58 | var priv interface{} 59 | priv, err0 := x509.ParsePKCS1PrivateKey(input) 60 | if err0 == nil { 61 | return priv, nil 62 | } 63 | 64 | priv, err1 := x509.ParsePKCS8PrivateKey(input) 65 | if err1 == nil { 66 | return priv, nil 67 | } 68 | 69 | priv, err2 := x509.ParseECPrivateKey(input) 70 | if err2 == nil { 71 | return priv, nil 72 | } 73 | 74 | return nil, fmt.Errorf("square/go-jose: parse error, got '%s', '%s' and '%s'", err0, err1, err2) 75 | } 76 | -------------------------------------------------------------------------------- /https/jose/cipher/concat_kdf.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1/cipher 18 | package josecipher 19 | 20 | import ( 21 | "crypto" 22 | "encoding/binary" 23 | "hash" 24 | "io" 25 | ) 26 | 27 | type concatKDF struct { 28 | z, info []byte 29 | i uint32 30 | cache []byte 31 | hasher hash.Hash 32 | } 33 | 34 | // NewConcatKDF builds a KDF reader based on the given inputs. 35 | func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader { 36 | buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo))) 37 | n := 0 38 | n += copy(buffer, algID) 39 | n += copy(buffer[n:], ptyUInfo) 40 | n += copy(buffer[n:], ptyVInfo) 41 | n += copy(buffer[n:], supPubInfo) 42 | copy(buffer[n:], supPrivInfo) 43 | 44 | hasher := hash.New() 45 | 46 | return &concatKDF{ 47 | z: z, 48 | info: buffer, 49 | hasher: hasher, 50 | cache: []byte{}, 51 | i: 1, 52 | } 53 | } 54 | 55 | func (ctx *concatKDF) Read(out []byte) (int, error) { 56 | copied := copy(out, ctx.cache) 57 | ctx.cache = ctx.cache[copied:] 58 | 59 | for copied < len(out) { 60 | ctx.hasher.Reset() 61 | 62 | // Write on a hash.Hash never fails 63 | _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i) 64 | _, _ = ctx.hasher.Write(ctx.z) 65 | _, _ = ctx.hasher.Write(ctx.info) 66 | 67 | hash := ctx.hasher.Sum(nil) 68 | chunkCopied := copy(out[copied:], hash) 69 | copied += chunkCopied 70 | ctx.cache = hash[chunkCopied:] 71 | 72 | ctx.i++ 73 | } 74 | 75 | return copied, nil 76 | } 77 | -------------------------------------------------------------------------------- /https/acme/error.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "strings" 10 | ) 11 | 12 | const ( 13 | tosAgreementError = "Must agree to subscriber agreement before any further actions" 14 | ) 15 | 16 | // RemoteError is the base type for all errors specific to the ACME protocol. 17 | type RemoteError struct { 18 | StatusCode int `json:"status,omitempty"` 19 | Type string `json:"type"` 20 | Detail string `json:"detail"` 21 | } 22 | 23 | func (e RemoteError) Error() string { 24 | return fmt.Sprintf("acme: Error %d - %s - %s", e.StatusCode, e.Type, e.Detail) 25 | } 26 | 27 | // TOSError represents the error which is returned if the user needs to 28 | // accept the TOS. 29 | // TODO: include the new TOS url if we can somehow obtain it. 30 | type TOSError struct { 31 | RemoteError 32 | } 33 | 34 | type domainError struct { 35 | Domain string 36 | Error error 37 | } 38 | 39 | type challengeError struct { 40 | RemoteError 41 | records []validationRecord 42 | } 43 | 44 | func (c challengeError) Error() string { 45 | 46 | var errStr string 47 | for _, validation := range c.records { 48 | errStr = errStr + fmt.Sprintf("\tValidation for %s:%s\n\tResolved to:\n\t\t%s\n\tUsed: %s\n\n", 49 | validation.Hostname, validation.Port, strings.Join(validation.ResolvedAddresses, "\n\t\t"), validation.UsedAddress) 50 | } 51 | 52 | return fmt.Sprintf("%s\nError Detail:\n%s", c.RemoteError.Error(), errStr) 53 | } 54 | 55 | func handleHTTPError(resp *http.Response) error { 56 | var errorDetail RemoteError 57 | decoder := json.NewDecoder(resp.Body) 58 | err := decoder.Decode(&errorDetail) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | errorDetail.StatusCode = resp.StatusCode 64 | 65 | // Check for errors we handle specifically 66 | if errorDetail.StatusCode == http.StatusForbidden && errorDetail.Detail == tosAgreementError { 67 | return TOSError{errorDetail} 68 | } 69 | 70 | return errorDetail 71 | } 72 | 73 | func handleChallengeError(chlng challenge) error { 74 | return challengeError{chlng.Error, chlng.ValidationRecords} 75 | } 76 | -------------------------------------------------------------------------------- /websocket/prepared_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "bytes" 10 | "compress/flate" 11 | "math/rand" 12 | "testing" 13 | ) 14 | 15 | var preparedMessageTests = []struct { 16 | messageType int 17 | isServer bool 18 | enableWriteCompression bool 19 | compressionLevel int 20 | }{ 21 | // Server 22 | {TextMessage, true, false, flate.BestSpeed}, 23 | {TextMessage, true, true, flate.BestSpeed}, 24 | {TextMessage, true, true, flate.BestCompression}, 25 | {PingMessage, true, false, flate.BestSpeed}, 26 | {PingMessage, true, true, flate.BestSpeed}, 27 | 28 | // Client 29 | {TextMessage, false, false, flate.BestSpeed}, 30 | {TextMessage, false, true, flate.BestSpeed}, 31 | {TextMessage, false, true, flate.BestCompression}, 32 | {PingMessage, false, false, flate.BestSpeed}, 33 | {PingMessage, false, true, flate.BestSpeed}, 34 | } 35 | 36 | func TestPreparedMessage(t *testing.T) { 37 | for _, tt := range preparedMessageTests { 38 | var data = []byte("this is a test") 39 | var buf bytes.Buffer 40 | c := newConn(fakeNetConn{Reader: nil, Writer: &buf}, tt.isServer, 1024, 1024) 41 | if tt.enableWriteCompression { 42 | c.newCompressionWriter = compressNoContextTakeover 43 | } 44 | c.SetCompressionLevel(tt.compressionLevel) 45 | 46 | // Seed random number generator for consistent frame mask. 47 | rand.Seed(1234) 48 | 49 | if err := c.WriteMessage(tt.messageType, data); err != nil { 50 | t.Fatal(err) 51 | } 52 | want := buf.String() 53 | 54 | pm, err := NewPreparedMessage(tt.messageType, data) 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | 59 | // Scribble on data to ensure that NewPreparedMessage takes a snapshot. 60 | copy(data, "hello world") 61 | 62 | // Seed random number generator for consistent frame mask. 63 | rand.Seed(1234) 64 | 65 | buf.Reset() 66 | if err := c.WritePreparedMessage(pm); err != nil { 67 | t.Fatal(err) 68 | } 69 | got := buf.String() 70 | 71 | if got != want { 72 | t.Errorf("write message != prepared message for %+v", tt) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /websocket/compression_test.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/gorilla/websocket 2 | package websocket 3 | 4 | import ( 5 | "bytes" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "testing" 10 | ) 11 | 12 | type nopCloser struct{ io.Writer } 13 | 14 | func (nopCloser) Close() error { return nil } 15 | 16 | func TestTruncWriter(t *testing.T) { 17 | const data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlkmnopqrstuvwxyz987654321" 18 | for n := 1; n <= 10; n++ { 19 | var b bytes.Buffer 20 | w := &truncWriter{w: nopCloser{&b}} 21 | p := []byte(data) 22 | for len(p) > 0 { 23 | m := len(p) 24 | if m > n { 25 | m = n 26 | } 27 | w.Write(p[:m]) 28 | p = p[m:] 29 | } 30 | if b.String() != data[:len(data)-len(w.p)] { 31 | t.Errorf("%d: %q", n, b.String()) 32 | } 33 | } 34 | } 35 | 36 | func textMessages(num int) [][]byte { 37 | messages := make([][]byte, num) 38 | for i := 0; i < num; i++ { 39 | msg := fmt.Sprintf("planet: %d, country: %d, city: %d, street: %d", i, i, i, i) 40 | messages[i] = []byte(msg) 41 | } 42 | return messages 43 | } 44 | 45 | func BenchmarkWriteNoCompression(b *testing.B) { 46 | w := ioutil.Discard 47 | c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024) 48 | messages := textMessages(100) 49 | b.ResetTimer() 50 | for i := 0; i < b.N; i++ { 51 | c.WriteMessage(TextMessage, messages[i%len(messages)]) 52 | } 53 | b.ReportAllocs() 54 | } 55 | 56 | func BenchmarkWriteWithCompression(b *testing.B) { 57 | w := ioutil.Discard 58 | c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024) 59 | messages := textMessages(100) 60 | c.enableWriteCompression = true 61 | c.newCompressionWriter = compressNoContextTakeover 62 | b.ResetTimer() 63 | for i := 0; i < b.N; i++ { 64 | c.WriteMessage(TextMessage, messages[i%len(messages)]) 65 | } 66 | b.ReportAllocs() 67 | } 68 | 69 | func TestValidCompressionLevel(t *testing.T) { 70 | c := newConn(fakeNetConn{}, false, 1024, 1024) 71 | for _, level := range []int{minCompressionLevel - 1, maxCompressionLevel + 1} { 72 | if err := c.SetCompressionLevel(level); err == nil { 73 | t.Errorf("no error for level %d", level) 74 | } 75 | } 76 | for _, level := range []int{minCompressionLevel, maxCompressionLevel} { 77 | if err := c.SetCompressionLevel(level); err != nil { 78 | t.Errorf("error for level %d", level) 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /https/jose/cipher/ecdh_es.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1/cipher 18 | package josecipher 19 | 20 | import ( 21 | "crypto" 22 | "crypto/ecdsa" 23 | "encoding/binary" 24 | ) 25 | 26 | // DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA. 27 | // It is an error to call this function with a private/public key that are not on the same 28 | // curve. Callers must ensure that the keys are valid before calling this function. Output 29 | // size may be at most 1<<16 bytes (64 KiB). 30 | func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte { 31 | if size > 1<<16 { 32 | panic("ECDH-ES output size too large, must be less than 1<<16") 33 | } 34 | 35 | // algId, partyUInfo, partyVInfo inputs must be prefixed with the length 36 | algID := lengthPrefixed([]byte(alg)) 37 | ptyUInfo := lengthPrefixed(apuData) 38 | ptyVInfo := lengthPrefixed(apvData) 39 | 40 | // suppPubInfo is the encoded length of the output size in bits 41 | supPubInfo := make([]byte, 4) 42 | binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8) 43 | 44 | if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) { 45 | panic("public key not on same curve as private key") 46 | } 47 | 48 | z, _ := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) 49 | reader := NewConcatKDF(crypto.SHA256, z.Bytes(), algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) 50 | 51 | key := make([]byte, size) 52 | 53 | // Read on the KDF will never fail 54 | _, _ = reader.Read(key) 55 | return key 56 | } 57 | 58 | func lengthPrefixed(data []byte) []byte { 59 | out := make([]byte, len(data)+4) 60 | binary.BigEndian.PutUint32(out, uint32(len(data))) 61 | copy(out[4:], data) 62 | return out 63 | } 64 | -------------------------------------------------------------------------------- /errors/README.md: -------------------------------------------------------------------------------- 1 | # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) 2 | 3 | Package errors provides simple error handling primitives. 4 | 5 | `go get github.com/pkg/errors` 6 | 7 | The traditional error handling idiom in Go is roughly akin to 8 | ```go 9 | if err != nil { 10 | return err 11 | } 12 | ``` 13 | which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. 14 | 15 | ## Adding context to an error 16 | 17 | The errors.Wrap function returns a new error that adds context to the original error. For example 18 | ```go 19 | _, err := ioutil.ReadAll(r) 20 | if err != nil { 21 | return errors.Wrap(err, "read failed") 22 | } 23 | ``` 24 | ## Retrieving the cause of an error 25 | 26 | Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. 27 | ```go 28 | type causer interface { 29 | Cause() error 30 | } 31 | ``` 32 | `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: 33 | ```go 34 | switch err := errors.Cause(err).(type) { 35 | case *MyError: 36 | // handle specifically 37 | default: 38 | // unknown error 39 | } 40 | ``` 41 | 42 | [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). 43 | 44 | ## Contributing 45 | 46 | We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. 47 | 48 | Before proposing a change, please discuss your change by raising an issue. 49 | 50 | ## Licence 51 | 52 | BSD-2-Clause 53 | -------------------------------------------------------------------------------- /aac/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package aac_test 23 | 24 | import ( 25 | "fmt" 26 | "github.com/ossrs/go-oryx-lib/aac" 27 | ) 28 | 29 | func ExampleADTSImpl_Decode() { 30 | var err error 31 | var adts aac.ADTS 32 | if adts, err = aac.NewADTS(); err != nil { 33 | fmt.Println(fmt.Sprintf("APP: Create ADTS failed, err is %+v", err)) 34 | return 35 | } 36 | 37 | var data []byte // Read ADTS data from file or network. 38 | 39 | // Ignore the left, assume that the RAW only contains one AAC frame. 40 | var raw []byte 41 | if raw, _, err = adts.Decode(data); err != nil { 42 | fmt.Println(fmt.Sprintf("APP: ADTS decode failed, err is %+v", err)) 43 | return 44 | } 45 | 46 | // Use the RAW data. 47 | _ = raw 48 | 49 | // Use the asc object, for example, used as RTMP audio sequence header. 50 | _ = adts.ASC() 51 | } 52 | 53 | func ExampleADTSImpl_Encode() { 54 | var err error 55 | var adts aac.ADTS 56 | if adts, err = aac.NewADTS(); err != nil { 57 | fmt.Println(fmt.Sprintf("APP: Create ADTS failed, err is %+v", err)) 58 | return 59 | } 60 | 61 | var raw []byte // Read RAW AAC from file or network. 62 | var data []byte 63 | if data, err = adts.Encode(raw); err != nil { 64 | fmt.Println(fmt.Sprintf("APP: ADTS encode failed, err is %+v", err)) 65 | return 66 | } 67 | 68 | // Use the ADTS data. 69 | _ = data 70 | } 71 | -------------------------------------------------------------------------------- /https/acme/tls_sni_challenge.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "crypto/rsa" 7 | "crypto/sha256" 8 | "crypto/tls" 9 | "encoding/hex" 10 | "fmt" 11 | "log" 12 | ) 13 | 14 | type tlsSNIChallenge struct { 15 | jws *jws 16 | validate validateFunc 17 | provider ChallengeProvider 18 | } 19 | 20 | func (t *tlsSNIChallenge) Solve(chlng challenge, domain string) error { 21 | // FIXME: https://github.com/ietf-wg-acme/acme/pull/22 22 | // Currently we implement this challenge to track boulder, not the current spec! 23 | 24 | logf("[INFO][%s] acme: Trying to solve TLS-SNI-01", domain) 25 | 26 | // Generate the Key Authorization for the challenge 27 | keyAuth, err := getKeyAuthorization(chlng.Token, t.jws.privKey) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | err = t.provider.Present(domain, chlng.Token, keyAuth) 33 | if err != nil { 34 | return fmt.Errorf("[%s] error presenting token: %v", domain, err) 35 | } 36 | defer func() { 37 | err := t.provider.CleanUp(domain, chlng.Token, keyAuth) 38 | if err != nil { 39 | log.Printf("[%s] error cleaning up: %v", domain, err) 40 | } 41 | }() 42 | return t.validate(t.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth}) 43 | } 44 | 45 | // TLSSNI01ChallengeCert returns a certificate and target domain for the `tls-sni-01` challenge 46 | func TLSSNI01ChallengeCertDomain(keyAuth string) (tls.Certificate, string, error) { 47 | // generate a new RSA key for the certificates 48 | tempPrivKey, err := generatePrivateKey(RSA2048) 49 | if err != nil { 50 | return tls.Certificate{}, "", err 51 | } 52 | rsaPrivKey := tempPrivKey.(*rsa.PrivateKey) 53 | rsaPrivPEM := pemEncode(rsaPrivKey) 54 | 55 | zBytes := sha256.Sum256([]byte(keyAuth)) 56 | z := hex.EncodeToString(zBytes[:sha256.Size]) 57 | domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:]) 58 | tempCertPEM, err := generatePemCert(rsaPrivKey, domain) 59 | if err != nil { 60 | return tls.Certificate{}, "", err 61 | } 62 | 63 | certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM) 64 | if err != nil { 65 | return tls.Certificate{}, "", err 66 | } 67 | 68 | return certificate, domain, nil 69 | } 70 | 71 | // TLSSNI01ChallengeCert returns a certificate for the `tls-sni-01` challenge 72 | func TLSSNI01ChallengeCert(keyAuth string) (tls.Certificate, error) { 73 | cert, _, err := TLSSNI01ChallengeCertDomain(keyAuth) 74 | return cert, err 75 | } 76 | -------------------------------------------------------------------------------- /flv/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package flv_test 23 | 24 | import ( 25 | "github.com/ossrs/go-oryx-lib/flv" 26 | "io" 27 | ) 28 | 29 | func ExampleDemuxer() { 30 | // To open a flv file, or http flv stream. 31 | var r io.Reader 32 | 33 | var err error 34 | var f flv.Demuxer 35 | if f, err = flv.NewDemuxer(r); err != nil { 36 | return 37 | } 38 | defer f.Close() 39 | 40 | var version uint8 41 | var hasVideo, hasAudio bool 42 | if version, hasVideo, hasAudio, err = f.ReadHeader(); err != nil { 43 | return 44 | } 45 | 46 | // Optional, user can check the header. 47 | _ = version 48 | _ = hasAudio 49 | _ = hasVideo 50 | 51 | var tagType flv.TagType 52 | var tagSize, timestamp uint32 53 | if tagType, tagSize, timestamp, err = f.ReadTagHeader(); err != nil { 54 | return 55 | } 56 | 57 | var tag []byte 58 | if tag, err = f.ReadTag(tagSize); err != nil { 59 | return 60 | } 61 | 62 | // Using the FLV tag type, dts and body. 63 | // Refer to @doc video_file_format_spec_v10.pdf, @page 9, @section FLV tags 64 | _ = tagType 65 | _ = timestamp 66 | _ = tag 67 | } 68 | 69 | func ExampleMuxer() { 70 | // To open a flv file or http post stream. 71 | var w io.Writer 72 | 73 | var err error 74 | var f flv.Muxer 75 | if f, err = flv.NewMuxer(w); err != nil { 76 | return 77 | } 78 | defer f.Close() 79 | 80 | if err = f.WriteHeader(true, true); err != nil { 81 | return 82 | } 83 | 84 | var tagType flv.TagType 85 | var timestamp uint32 86 | var tag []byte 87 | // Get a FLV tag to write to muxer. 88 | if err = f.WriteTag(tagType, timestamp, tag); err != nil { 89 | return 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /websocket/client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "net/url" 10 | "reflect" 11 | "testing" 12 | ) 13 | 14 | var parseURLTests = []struct { 15 | s string 16 | u *url.URL 17 | rui string 18 | }{ 19 | {"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"}, 20 | {"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"}, 21 | {"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"}, 22 | {"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"}, 23 | {"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"}, 24 | {"ss://example.com/a/b", nil, ""}, 25 | {"ws://webmaster@example.com/", nil, ""}, 26 | {"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"}, 27 | {"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"}, 28 | } 29 | 30 | func TestParseURL(t *testing.T) { 31 | for _, tt := range parseURLTests { 32 | u, err := parseURL(tt.s) 33 | if tt.u != nil && err != nil { 34 | t.Errorf("parseURL(%q) returned error %v", tt.s, err) 35 | continue 36 | } 37 | if tt.u == nil { 38 | if err == nil { 39 | t.Errorf("parseURL(%q) did not return error", tt.s) 40 | } 41 | continue 42 | } 43 | if !reflect.DeepEqual(u, tt.u) { 44 | t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u) 45 | continue 46 | } 47 | if u.RequestURI() != tt.rui { 48 | t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui) 49 | } 50 | } 51 | } 52 | 53 | var hostPortNoPortTests = []struct { 54 | u *url.URL 55 | hostPort, hostNoPort string 56 | }{ 57 | {&url.URL{Scheme: "ws", Host: "example.com"}, "example.com:80", "example.com"}, 58 | {&url.URL{Scheme: "wss", Host: "example.com"}, "example.com:443", "example.com"}, 59 | {&url.URL{Scheme: "ws", Host: "example.com:7777"}, "example.com:7777", "example.com"}, 60 | {&url.URL{Scheme: "wss", Host: "example.com:7777"}, "example.com:7777", "example.com"}, 61 | } 62 | 63 | func TestHostPortNoPort(t *testing.T) { 64 | for _, tt := range hostPortNoPortTests { 65 | hostPort, hostNoPort := hostPortNoPort(tt.u) 66 | if hostPort != tt.hostPort { 67 | t.Errorf("hostPortNoPort(%v) returned hostPort %q, want %q", tt.u, hostPort, tt.hostPort) 68 | } 69 | if hostNoPort != tt.hostNoPort { 70 | t.Errorf("hostPortNoPort(%v) returned hostNoPort %q, want %q", tt.u, hostNoPort, tt.hostNoPort) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /https/acme/jws.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "bytes" 7 | "crypto" 8 | "crypto/ecdsa" 9 | "crypto/elliptic" 10 | "crypto/rsa" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/ossrs/go-oryx-lib/https/jose" 15 | ) 16 | 17 | type jws struct { 18 | directoryURL string 19 | privKey crypto.PrivateKey 20 | nonces []string 21 | } 22 | 23 | func keyAsJWK(key interface{}) *jose.JsonWebKey { 24 | switch k := key.(type) { 25 | case *ecdsa.PublicKey: 26 | return &jose.JsonWebKey{Key: k, Algorithm: "EC"} 27 | case *rsa.PublicKey: 28 | return &jose.JsonWebKey{Key: k, Algorithm: "RSA"} 29 | 30 | default: 31 | return nil 32 | } 33 | } 34 | 35 | // Posts a JWS signed message to the specified URL 36 | func (j *jws) post(url string, content []byte) (*http.Response, error) { 37 | signedContent, err := j.signContent(content) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | j.getNonceFromResponse(resp) 48 | 49 | return resp, err 50 | } 51 | 52 | func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { 53 | 54 | var alg jose.SignatureAlgorithm 55 | switch k := j.privKey.(type) { 56 | case *rsa.PrivateKey: 57 | alg = jose.RS256 58 | case *ecdsa.PrivateKey: 59 | if k.Curve == elliptic.P256() { 60 | alg = jose.ES256 61 | } else if k.Curve == elliptic.P384() { 62 | alg = jose.ES384 63 | } 64 | } 65 | 66 | signer, err := jose.NewSigner(alg, j.privKey) 67 | if err != nil { 68 | return nil, err 69 | } 70 | signer.SetNonceSource(j) 71 | 72 | signed, err := signer.Sign(content) 73 | if err != nil { 74 | return nil, err 75 | } 76 | return signed, nil 77 | } 78 | 79 | func (j *jws) getNonceFromResponse(resp *http.Response) error { 80 | nonce := resp.Header.Get("Replay-Nonce") 81 | if nonce == "" { 82 | return fmt.Errorf("Server did not respond with a proper nonce header.") 83 | } 84 | 85 | j.nonces = append(j.nonces, nonce) 86 | return nil 87 | } 88 | 89 | func (j *jws) getNonce() error { 90 | resp, err := httpHead(j.directoryURL) 91 | if err != nil { 92 | return err 93 | } 94 | 95 | return j.getNonceFromResponse(resp) 96 | } 97 | 98 | func (j *jws) Nonce() (string, error) { 99 | nonce := "" 100 | if len(j.nonces) == 0 { 101 | err := j.getNonce() 102 | if err != nil { 103 | return nonce, err 104 | } 105 | } 106 | 107 | nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] 108 | return nonce, nil 109 | } 110 | -------------------------------------------------------------------------------- /https/acme/http_challenge_server.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "fmt" 7 | "net" 8 | "net/http" 9 | "strings" 10 | ) 11 | 12 | // HTTPProviderServer implements ChallengeProvider for `http-01` challenge 13 | // It may be instantiated without using the NewHTTPProviderServer function if 14 | // you want only to use the default values. 15 | type HTTPProviderServer struct { 16 | iface string 17 | port string 18 | done chan bool 19 | listener net.Listener 20 | } 21 | 22 | // NewHTTPProviderServer creates a new HTTPProviderServer on the selected interface and port. 23 | // Setting iface and / or port to an empty string will make the server fall back to 24 | // the "any" interface and port 80 respectively. 25 | func NewHTTPProviderServer(iface, port string) *HTTPProviderServer { 26 | return &HTTPProviderServer{iface: iface, port: port} 27 | } 28 | 29 | // Present starts a web server and makes the token available at `HTTP01ChallengePath(token)` for web requests. 30 | func (s *HTTPProviderServer) Present(domain, token, keyAuth string) error { 31 | if s.port == "" { 32 | s.port = "80" 33 | } 34 | 35 | var err error 36 | s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port)) 37 | if err != nil { 38 | return fmt.Errorf("Could not start HTTP server for challenge -> %v", err) 39 | } 40 | 41 | s.done = make(chan bool) 42 | go s.serve(domain, token, keyAuth) 43 | return nil 44 | } 45 | 46 | // CleanUp closes the HTTP server and removes the token from `HTTP01ChallengePath(token)` 47 | func (s *HTTPProviderServer) CleanUp(domain, token, keyAuth string) error { 48 | if s.listener == nil { 49 | return nil 50 | } 51 | s.listener.Close() 52 | <-s.done 53 | return nil 54 | } 55 | 56 | func (s *HTTPProviderServer) serve(domain, token, keyAuth string) { 57 | path := HTTP01ChallengePath(token) 58 | 59 | // The handler validates the HOST header and request type. 60 | // For validation it then writes the token the server returned with the challenge 61 | mux := http.NewServeMux() 62 | mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { 63 | if strings.HasPrefix(r.Host, domain) && r.Method == "GET" { 64 | w.Header().Add("Content-Type", "text/plain") 65 | w.Write([]byte(keyAuth)) 66 | logf("[INFO][%s] Served key authentication", domain) 67 | } else { 68 | logf("[INFO] Received request for domain %s with method %s", r.Host, r.Method) 69 | w.Write([]byte("TEST")) 70 | } 71 | }) 72 | 73 | httpServer := &http.Server{ 74 | Handler: mux, 75 | } 76 | // Once httpServer is shut down we don't want any lingering 77 | // connections, so disable KeepAlives. 78 | httpServer.SetKeepAlivesEnabled(false) 79 | httpServer.Serve(s.listener) 80 | s.done <- true 81 | } 82 | -------------------------------------------------------------------------------- /websocket/json_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "bytes" 10 | "encoding/json" 11 | "io" 12 | "reflect" 13 | "testing" 14 | ) 15 | 16 | func TestJSON(t *testing.T) { 17 | var buf bytes.Buffer 18 | c := fakeNetConn{&buf, &buf} 19 | wc := newConn(c, true, 1024, 1024) 20 | rc := newConn(c, false, 1024, 1024) 21 | 22 | var actual, expect struct { 23 | A int 24 | B string 25 | } 26 | expect.A = 1 27 | expect.B = "hello" 28 | 29 | if err := wc.WriteJSON(&expect); err != nil { 30 | t.Fatal("write", err) 31 | } 32 | 33 | if err := rc.ReadJSON(&actual); err != nil { 34 | t.Fatal("read", err) 35 | } 36 | 37 | if !reflect.DeepEqual(&actual, &expect) { 38 | t.Fatal("equal", actual, expect) 39 | } 40 | } 41 | 42 | func TestPartialJSONRead(t *testing.T) { 43 | var buf bytes.Buffer 44 | c := fakeNetConn{&buf, &buf} 45 | wc := newConn(c, true, 1024, 1024) 46 | rc := newConn(c, false, 1024, 1024) 47 | 48 | var v struct { 49 | A int 50 | B string 51 | } 52 | v.A = 1 53 | v.B = "hello" 54 | 55 | messageCount := 0 56 | 57 | // Partial JSON values. 58 | 59 | data, err := json.Marshal(v) 60 | if err != nil { 61 | t.Fatal(err) 62 | } 63 | for i := len(data) - 1; i >= 0; i-- { 64 | if err := wc.WriteMessage(TextMessage, data[:i]); err != nil { 65 | t.Fatal(err) 66 | } 67 | messageCount++ 68 | } 69 | 70 | // Whitespace. 71 | 72 | if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil { 73 | t.Fatal(err) 74 | } 75 | messageCount++ 76 | 77 | // Close. 78 | 79 | if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil { 80 | t.Fatal(err) 81 | } 82 | 83 | for i := 0; i < messageCount; i++ { 84 | err := rc.ReadJSON(&v) 85 | if err != io.ErrUnexpectedEOF { 86 | t.Error("read", i, err) 87 | } 88 | } 89 | 90 | err = rc.ReadJSON(&v) 91 | if _, ok := err.(*CloseError); !ok { 92 | t.Error("final", err) 93 | } 94 | } 95 | 96 | func TestDeprecatedJSON(t *testing.T) { 97 | var buf bytes.Buffer 98 | c := fakeNetConn{&buf, &buf} 99 | wc := newConn(c, true, 1024, 1024) 100 | rc := newConn(c, false, 1024, 1024) 101 | 102 | var actual, expect struct { 103 | A int 104 | B string 105 | } 106 | expect.A = 1 107 | expect.B = "hello" 108 | 109 | if err := WriteJSON(wc, &expect); err != nil { 110 | t.Fatal("write", err) 111 | } 112 | 113 | if err := ReadJSON(rc, &actual); err != nil { 114 | t.Fatal("read", err) 115 | } 116 | 117 | if !reflect.DeepEqual(&actual, &expect) { 118 | t.Fatal("equal", actual, expect) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /websocket/util_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "net/http" 10 | "reflect" 11 | "testing" 12 | ) 13 | 14 | var tokenListContainsValueTests = []struct { 15 | value string 16 | ok bool 17 | }{ 18 | {"WebSocket", true}, 19 | {"WEBSOCKET", true}, 20 | {"websocket", true}, 21 | {"websockets", false}, 22 | {"x websocket", false}, 23 | {"websocket x", false}, 24 | {"other,websocket,more", true}, 25 | {"other, websocket, more", true}, 26 | } 27 | 28 | func TestTokenListContainsValue(t *testing.T) { 29 | for _, tt := range tokenListContainsValueTests { 30 | h := http.Header{"Upgrade": {tt.value}} 31 | ok := tokenListContainsValue(h, "Upgrade", "websocket") 32 | if ok != tt.ok { 33 | t.Errorf("tokenListContainsValue(h, n, %q) = %v, want %v", tt.value, ok, tt.ok) 34 | } 35 | } 36 | } 37 | 38 | var parseExtensionTests = []struct { 39 | value string 40 | extensions []map[string]string 41 | }{ 42 | {`foo`, []map[string]string{map[string]string{"": "foo"}}}, 43 | {`foo, bar; baz=2`, []map[string]string{ 44 | map[string]string{"": "foo"}, 45 | map[string]string{"": "bar", "baz": "2"}}}, 46 | {`foo; bar="b,a;z"`, []map[string]string{ 47 | map[string]string{"": "foo", "bar": "b,a;z"}}}, 48 | {`foo , bar; baz = 2`, []map[string]string{ 49 | map[string]string{"": "foo"}, 50 | map[string]string{"": "bar", "baz": "2"}}}, 51 | {`foo, bar; baz=2 junk`, []map[string]string{ 52 | map[string]string{"": "foo"}}}, 53 | {`foo junk, bar; baz=2 junk`, nil}, 54 | {`mux; max-channels=4; flow-control, deflate-stream`, []map[string]string{ 55 | map[string]string{"": "mux", "max-channels": "4", "flow-control": ""}, 56 | map[string]string{"": "deflate-stream"}}}, 57 | {`permessage-foo; x="10"`, []map[string]string{ 58 | map[string]string{"": "permessage-foo", "x": "10"}}}, 59 | {`permessage-foo; use_y, permessage-foo`, []map[string]string{ 60 | map[string]string{"": "permessage-foo", "use_y": ""}, 61 | map[string]string{"": "permessage-foo"}}}, 62 | {`permessage-deflate; client_max_window_bits; server_max_window_bits=10 , permessage-deflate; client_max_window_bits`, []map[string]string{ 63 | map[string]string{"": "permessage-deflate", "client_max_window_bits": "", "server_max_window_bits": "10"}, 64 | map[string]string{"": "permessage-deflate", "client_max_window_bits": ""}}}, 65 | } 66 | 67 | func TestParseExtensions(t *testing.T) { 68 | for _, tt := range parseExtensionTests { 69 | h := http.Header{http.CanonicalHeaderKey("Sec-WebSocket-Extensions"): {tt.value}} 70 | extensions := parseExtensions(h) 71 | if !reflect.DeepEqual(extensions, tt.extensions) { 72 | t.Errorf("parseExtensions(%q)\n = %v,\nwant %v", tt.value, extensions, tt.extensions) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rtmp/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package rtmp_test 23 | 24 | import ( 25 | "math/rand" 26 | "net" 27 | "time" 28 | 29 | "github.com/ossrs/go-oryx-lib/rtmp" 30 | "github.com/ossrs/go-oryx-lib/amf0" 31 | ) 32 | 33 | func ExampleRtmpClientHandshake() { 34 | // Connect to RTMP server via TCP client. 35 | c, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 1935}) 36 | if err != nil { 37 | panic(err) 38 | } 39 | defer c.Close() 40 | 41 | rd := rand.New(rand.NewSource(time.Now().UnixNano())) 42 | hs := rtmp.NewHandshake(rd) 43 | 44 | // Client send C0,C1 45 | if err := hs.WriteC0S0(c); err != nil { 46 | panic(err) 47 | } 48 | if err := hs.WriteC1S1(c); err != nil { 49 | panic(err) 50 | } 51 | 52 | // Receive S0,S1,S2 from RTMP server. 53 | if _, err = hs.ReadC0S0(c); err != nil { 54 | panic(err) 55 | } 56 | s1, err := hs.ReadC1S1(c) 57 | if err != nil { 58 | panic(err) 59 | } 60 | if _, err = hs.ReadC2S2(c); err != nil { 61 | panic(err) 62 | } 63 | 64 | // Client send C2 65 | if err := hs.WriteC2S2(c, s1); err != nil { 66 | panic(err) 67 | } 68 | } 69 | 70 | func ExampleRtmpClientConnect() { 71 | // Connect to RTMP server via TCP, then finish the RTMP handshake see ExampleRtmpClientHandshake. 72 | var c *net.TCPConn 73 | 74 | // Create a RTMP client. 75 | client := rtmp.NewProtocol(c) 76 | 77 | // Send RTMP connect tcURL packet. 78 | connectApp := rtmp.NewConnectAppPacket() 79 | connectApp.CommandObject.Set("tcUrl", amf0.NewString("rtmp://localhost/live")) 80 | if err := client.WritePacket(connectApp, 1); err != nil { 81 | panic(err) 82 | } 83 | 84 | var connectAppRes *rtmp.ConnectAppResPacket 85 | if _, err := client.ExpectPacket(&connectAppRes); err != nil { 86 | panic(err) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /http/api.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The oryx http package, the response parse service. 23 | package http 24 | 25 | import ( 26 | "encoding/json" 27 | "fmt" 28 | "io/ioutil" 29 | "net/http" 30 | ) 31 | 32 | // Read http api by HTTP GET and parse the code/data. 33 | func ApiRequest(url string) (code int, body []byte, err error) { 34 | if body, err = apiGet(url); err != nil { 35 | return 36 | } 37 | 38 | if code, _, err = apiParse(url, body); err != nil { 39 | return 40 | } 41 | 42 | return 43 | } 44 | 45 | // Read http api by HTTP GET. 46 | func apiGet(url string) (body []byte, err error) { 47 | var resp *http.Response 48 | if resp, err = http.Get(url); err != nil { 49 | err = fmt.Errorf("api get failed, url=%v, err is %v", url, err) 50 | return 51 | } 52 | defer resp.Body.Close() 53 | 54 | if body, err = ioutil.ReadAll(resp.Body); err != nil { 55 | err = fmt.Errorf("api read failed, url=%v, err is %v", url, err) 56 | return 57 | } 58 | 59 | return 60 | } 61 | 62 | // Parse the standard response {code:int,data:object}. 63 | func apiParse(url string, body []byte) (code int, data interface{}, err error) { 64 | obj := make(map[string]interface{}) 65 | if err = json.Unmarshal(body, &obj); err != nil { 66 | err = fmt.Errorf("api parse failed, url=%v, body=%v, err is %v", url, string(body), err) 67 | return 68 | } 69 | 70 | if value, ok := obj["code"]; !ok { 71 | err = fmt.Errorf("api no code, url=%v, body=%v", url, string(body)) 72 | return 73 | } else if value, ok := value.(float64); !ok { 74 | err = fmt.Errorf("api code not number, code=%v, url=%v, body=%v", value, url, string(body)) 75 | return 76 | } else { 77 | code = int(value) 78 | } 79 | 80 | data, _ = obj["data"] 81 | if code != 0 { 82 | err = fmt.Errorf("api error, code=%v, url=%v, body=%v, data=%v", code, url, string(body), data) 83 | return 84 | } 85 | 86 | return 87 | } 88 | -------------------------------------------------------------------------------- /logger/go17.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // +build go1.7 23 | 24 | package logger 25 | 26 | import ( 27 | "context" 28 | "fmt" 29 | "os" 30 | ) 31 | 32 | func (v *loggerPlus) Println(ctx Context, a ...interface{}) { 33 | args := v.contextFormat(ctx, a...) 34 | v.doPrintln(args...) 35 | } 36 | 37 | func (v *loggerPlus) Printf(ctx Context, format string, a ...interface{}) { 38 | format, args := v.contextFormatf(ctx, format, a...) 39 | v.doPrintf(format, args...) 40 | } 41 | 42 | func (v *loggerPlus) contextFormat(ctx Context, a ...interface{}) []interface{} { 43 | if ctx, ok := ctx.(context.Context); ok { 44 | if cid, ok := ctx.Value(cidKey).(int); ok { 45 | return append([]interface{}{fmt.Sprintf("[%v][%v]", os.Getpid(), cid)}, a...) 46 | } 47 | } else { 48 | return v.format(ctx, a...) 49 | } 50 | return a 51 | } 52 | 53 | func (v *loggerPlus) contextFormatf(ctx Context, format string, a ...interface{}) (string, []interface{}) { 54 | if ctx, ok := ctx.(context.Context); ok { 55 | if cid, ok := ctx.Value(cidKey).(int); ok { 56 | return "[%v][%v] " + format, append([]interface{}{os.Getpid(), cid}, a...) 57 | } 58 | } else { 59 | return v.formatf(ctx, format, a...) 60 | } 61 | return format, a 62 | } 63 | 64 | // User should use context with value to pass the cid. 65 | type key string 66 | 67 | var cidKey key = "cid.logger.ossrs.org" 68 | 69 | var gCid int = 999 70 | 71 | // Create context with value. 72 | func WithContext(ctx context.Context) context.Context { 73 | gCid += 1 74 | return context.WithValue(ctx, cidKey, gCid) 75 | } 76 | 77 | // Create context with value from parent, copy the cid from source context. 78 | // @remark Create new cid if source has no cid represent. 79 | func AliasContext(parent context.Context, source context.Context) context.Context { 80 | if source != nil { 81 | if cid, ok := source.Value(cidKey).(int); ok { 82 | return context.WithValue(parent, cidKey, cid) 83 | } 84 | } 85 | return WithContext(parent) 86 | } 87 | -------------------------------------------------------------------------------- /kxps/krps.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The krps is about the request or message rate. 23 | package kxps 24 | 25 | import ( 26 | ol "github.com/ossrs/go-oryx-lib/logger" 27 | "io" 28 | ) 29 | 30 | // The source to stat the requests. 31 | type KrpsSource interface { 32 | // Get total number of requests. 33 | NbRequests() uint64 34 | } 35 | 36 | // The object to calc the krps. 37 | type Krps interface { 38 | // Start the krps sample goroutine. 39 | Start() (err error) 40 | 41 | // Get the rps in last 10s. 42 | Rps10s() float64 43 | // Get the rps in last 30s. 44 | Rps30s() float64 45 | // Get the rps in last 300s. 46 | Rps300s() float64 47 | // Get the rps in average 48 | Average() float64 49 | 50 | // When closed, this krps should never use again. 51 | io.Closer 52 | } 53 | 54 | // The implementation object. 55 | type krps struct { 56 | source KrpsSource 57 | imp *kxps 58 | } 59 | 60 | func NewKrps(ctx ol.Context, s KrpsSource) Krps { 61 | v := &krps{ 62 | source: s, 63 | } 64 | v.imp = newKxps(ctx, v) 65 | return v 66 | } 67 | 68 | func (v *krps) Count() uint64 { 69 | return v.source.NbRequests() 70 | } 71 | 72 | func (v *krps) Close() (err error) { 73 | return v.imp.Close() 74 | } 75 | 76 | func (v *krps) Rps10s() float64 { 77 | if !v.imp.started { 78 | panic("should start krps first.") 79 | } 80 | return v.imp.Xps10s() 81 | } 82 | 83 | func (v *krps) Rps30s() float64 { 84 | if !v.imp.started { 85 | panic("should start krps first.") 86 | } 87 | return v.imp.Xps30s() 88 | } 89 | 90 | func (v *krps) Rps300s() float64 { 91 | if !v.imp.started { 92 | panic("should start krps first.") 93 | } 94 | return v.imp.Xps300s() 95 | } 96 | 97 | func (v *krps) Average() float64 { 98 | if !v.imp.started { 99 | panic("should start krps first.") 100 | } 101 | return v.imp.Average() 102 | } 103 | 104 | func (v *krps) Start() (err error) { 105 | return v.imp.Start() 106 | } 107 | -------------------------------------------------------------------------------- /https/net/context/go17.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | // fork from golang.org/x/net/context 8 | // from https://github.com/golang/net 9 | package context 10 | 11 | import ( 12 | "context" // standard library's context, as of Go 1.7 13 | "time" 14 | ) 15 | 16 | var ( 17 | todo = context.TODO() 18 | background = context.Background() 19 | ) 20 | 21 | // Canceled is the error returned by Context.Err when the context is canceled. 22 | var Canceled = context.Canceled 23 | 24 | // DeadlineExceeded is the error returned by Context.Err when the context's 25 | // deadline passes. 26 | var DeadlineExceeded = context.DeadlineExceeded 27 | 28 | // WithCancel returns a copy of parent with a new Done channel. The returned 29 | // context's Done channel is closed when the returned cancel function is called 30 | // or when the parent context's Done channel is closed, whichever happens first. 31 | // 32 | // Canceling this context releases resources associated with it, so code should 33 | // call cancel as soon as the operations running in this Context complete. 34 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { 35 | ctx, f := context.WithCancel(parent) 36 | return ctx, CancelFunc(f) 37 | } 38 | 39 | // WithDeadline returns a copy of the parent context with the deadline adjusted 40 | // to be no later than d. If the parent's deadline is already earlier than d, 41 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned 42 | // context's Done channel is closed when the deadline expires, when the returned 43 | // cancel function is called, or when the parent context's Done channel is 44 | // closed, whichever happens first. 45 | // 46 | // Canceling this context releases resources associated with it, so code should 47 | // call cancel as soon as the operations running in this Context complete. 48 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { 49 | ctx, f := context.WithDeadline(parent, deadline) 50 | return ctx, CancelFunc(f) 51 | } 52 | 53 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). 54 | // 55 | // Canceling this context releases resources associated with it, so code should 56 | // call cancel as soon as the operations running in this Context complete: 57 | // 58 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { 59 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 60 | // defer cancel() // releases resources if slowOperation completes before timeout elapses 61 | // return slowOperation(ctx) 62 | // } 63 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { 64 | return WithDeadline(parent, time.Now().Add(timeout)) 65 | } 66 | 67 | // WithValue returns a copy of parent in which the value associated with key is 68 | // val. 69 | // 70 | // Use context Values only for request-scoped data that transits processes and 71 | // APIs, not for passing optional parameters to functions. 72 | func WithValue(parent Context, key interface{}, val interface{}) Context { 73 | return context.WithValue(parent, key, val) 74 | } 75 | -------------------------------------------------------------------------------- /https/jose/cipher/key_wrap.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1/cipher 18 | package josecipher 19 | 20 | import ( 21 | "crypto/cipher" 22 | "crypto/subtle" 23 | "encoding/binary" 24 | "errors" 25 | ) 26 | 27 | var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} 28 | 29 | // KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. 30 | func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { 31 | if len(cek)%8 != 0 { 32 | return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") 33 | } 34 | 35 | n := len(cek) / 8 36 | r := make([][]byte, n) 37 | 38 | for i := range r { 39 | r[i] = make([]byte, 8) 40 | copy(r[i], cek[i*8:]) 41 | } 42 | 43 | buffer := make([]byte, 16) 44 | tBytes := make([]byte, 8) 45 | copy(buffer, defaultIV) 46 | 47 | for t := 0; t < 6*n; t++ { 48 | copy(buffer[8:], r[t%n]) 49 | 50 | block.Encrypt(buffer, buffer) 51 | 52 | binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 53 | 54 | for i := 0; i < 8; i++ { 55 | buffer[i] = buffer[i] ^ tBytes[i] 56 | } 57 | copy(r[t%n], buffer[8:]) 58 | } 59 | 60 | out := make([]byte, (n+1)*8) 61 | copy(out, buffer[:8]) 62 | for i := range r { 63 | copy(out[(i+1)*8:], r[i]) 64 | } 65 | 66 | return out, nil 67 | } 68 | 69 | // KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher. 70 | func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { 71 | if len(ciphertext)%8 != 0 { 72 | return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") 73 | } 74 | 75 | n := (len(ciphertext) / 8) - 1 76 | r := make([][]byte, n) 77 | 78 | for i := range r { 79 | r[i] = make([]byte, 8) 80 | copy(r[i], ciphertext[(i+1)*8:]) 81 | } 82 | 83 | buffer := make([]byte, 16) 84 | tBytes := make([]byte, 8) 85 | copy(buffer[:8], ciphertext[:8]) 86 | 87 | for t := 6*n - 1; t >= 0; t-- { 88 | binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 89 | 90 | for i := 0; i < 8; i++ { 91 | buffer[i] = buffer[i] ^ tBytes[i] 92 | } 93 | copy(buffer[8:], r[t%n]) 94 | 95 | block.Decrypt(buffer, buffer) 96 | 97 | copy(r[t%n], buffer[8:]) 98 | } 99 | 100 | if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 { 101 | return nil, errors.New("square/go-jose: failed to unwrap key") 102 | } 103 | 104 | out := make([]byte, n*8) 105 | for i := range r { 106 | copy(out[i*8:], r[i]) 107 | } 108 | 109 | return out, nil 110 | } 111 | -------------------------------------------------------------------------------- /kxps/kbps.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The kbps is about the bitrate. 23 | package kxps 24 | 25 | import ( 26 | ol "github.com/ossrs/go-oryx-lib/logger" 27 | "io" 28 | ) 29 | 30 | // The source to stat the bitrate. 31 | type KbpsSource interface { 32 | // Get total number of bytes. 33 | TotalBytes() uint64 34 | } 35 | 36 | // The object to calc the kbps. 37 | type Kbps interface { 38 | // Start the kbps sample goroutine. 39 | Start() (err error) 40 | 41 | // Get the kbps in last 10s. 42 | Kbps10s() float64 43 | // Get the kbps in last 30s. 44 | Kbps30s() float64 45 | // Get the kbps in last 300s. 46 | Kbps300s() float64 47 | // Get the kbps in average 48 | Average() float64 49 | 50 | // When closed, this kbps should never use again. 51 | io.Closer 52 | } 53 | 54 | type kbps struct { 55 | source KbpsSource 56 | imp *kxps 57 | } 58 | 59 | func NewKbps(ctx ol.Context, source KbpsSource) Kbps { 60 | v := &kbps{source: source} 61 | v.imp = newKxps(ctx, v) 62 | return v 63 | } 64 | 65 | func (v *kbps) Count() uint64 { 66 | return v.source.TotalBytes() 67 | } 68 | 69 | func (v *kbps) Close() (err error) { 70 | return v.imp.Close() 71 | } 72 | 73 | func (v *kbps) Kbps10s() float64 { 74 | if !v.imp.started { 75 | panic("should start kbps first.") 76 | } 77 | // Bps to Kbps 78 | return v.imp.Xps10s() * 8 / 1000 79 | } 80 | 81 | func (v *kbps) Kbps30s() float64 { 82 | if !v.imp.started { 83 | panic("should start kbps first.") 84 | } 85 | // Bps to Kbps 86 | return v.imp.Xps30s() * 8 / 1000 87 | } 88 | 89 | func (v *kbps) Kbps300s() float64 { 90 | if !v.imp.started { 91 | panic("should start kbps first.") 92 | } 93 | // Bps to Kbps 94 | return v.imp.Xps300s() * 8 / 1000 95 | } 96 | 97 | func (v *kbps) Average() float64 { 98 | if !v.imp.started { 99 | panic("should start kbps first.") 100 | } 101 | // Bps to Kbps 102 | return v.imp.Average() * 8 / 1000 103 | } 104 | 105 | func (v *kbps) Start() (err error) { 106 | return v.imp.Start() 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-oryx-lib 2 | 3 | ![](http://ossrs.net:8000/gif/v1/sls.gif?site=github.com&path=/srs/gooryxlib) 4 | [![](https://cloud.githubusercontent.com/assets/2777660/22814959/c51cbe72-ef92-11e6-81cc-32b657b285d5.png)](https://github.com/ossrs/srs/wiki/v1_CN_Contact#wechat) 5 | [![Build Status](https://travis-ci.org/ossrs/go-oryx-lib.svg?branch=master)](https://travis-ci.org/ossrs/go-oryx-lib) 6 | [![codecov](https://codecov.io/gh/ossrs/go-oryx-lib/branch/master/graph/badge.svg)](https://codecov.io/gh/ossrs/go-oryx-lib) 7 | 8 | This library is exported for [Oryx](https://github.com/ossrs/oryx). 9 | 10 | ## Requires 11 | 12 | [GO1.4](https://golang.org/dl/)+ 13 | 14 | ## Packages 15 | 16 | The library provides packages about network and multiple media processing: 17 | 18 | - [x] [logger](logger/example_test.go): Connection-Oriented logger for application server. 19 | - [x] [json](json/example_test.go): Json+ supports c and c++ style comments. 20 | - [x] [options](options/example_test.go): Frequently used service options with config file. 21 | - [x] [http](http/example_test.go): For http response with error, jsonp and std reponse. 22 | - [x] [kxps](kxps/example_test.go): The k-some-ps, for example, kbps, krps. 23 | - [x] [https](https/example_test.go): For https server over [lego/acme](https://github.com/xenolf/lego/tree/master/acme) of [letsencrypt](https://letsencrypt.org/). 24 | - [x] [flv](flv/example_test.go): The FLV muxer and demuxer, for oryx. 25 | - [x] [errors](errors/example_test.go): Fork from [pkg/errors](https://github.com/pkg/errors), a complex error with message and stack, read [article](https://gocn.io/article/348). 26 | - [x] [aac](aac/example_test.go): The AAC utilities to demux and mux AAC RAW data, for oryx. 27 | - [x] [websocket](https://golang.org/x/net/websocket): Fork from [websocket](https://github.com/gorilla/websocket/tree/v1.2.0). 28 | - [x] [rtmp](rtmp/example_test.go): The RTMP protocol stack, for oryx. 29 | - [x] [avc](avc/example_test.go): The AVC utilities to demux and mux AVC RAW data, for oryx. 30 | 31 | > Remark: For library, please never use `logger`, use `errors` instead. 32 | 33 | Other multiple media libraries in golang: 34 | 35 | - [x] [go-speex](https://github.com/winlinvip/go-speex): A go binding for [speex](https://speex.org/). 36 | - [x] [go-fdkaac](https://github.com/winlinvip/go-fdkaac): A go binding for [fdk-aac](https://github.com/mstorsjo/fdk-aac). 37 | - [x] [go-aresample](https://github.com/winlinvip/go-aresample): Resample the audio PCM. 38 | 39 | ## License 40 | 41 | This library just depends on golang standard library, 42 | we do this by copying the code of other libraries, 43 | while all the licenses are liberal: 44 | 45 | 1. [go-oryx-lib](LICENSE) uses [MIT License](https://github.com/ossrs/go-oryx-lib/blob/master/LICENSE). 46 | 1. [pkg/errors](errors/LICENSE) uses [BSD 2-clause "Simplified" License](https://github.com/pkg/errors/blob/master/LICENSE). 47 | 1. [acme](https/acme/LICENSE) uses [MIT License](https://github.com/xenolf/lego/blob/master/LICENSE). 48 | 1. [jose](https/jose/LICENSE) uses [Apache License 2.0](https://github.com/square/go-jose/blob/v1.1.0/LICENSE). 49 | 1. [letsencrypt](https/letsencrypt/LICENSE) uses [BSD 3-clause "New" or "Revised" License](https://github.com/rsc/letsencrypt/blob/master/LICENSE). 50 | 1. [websocket](https://github.com/gorilla/websocket) uses [BSD 2-clause "Simplified" License](https://github.com/gorilla/websocket/blob/master/LICENSE). 51 | 52 | Winlin 2016 53 | -------------------------------------------------------------------------------- /logger/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package logger_test 23 | 24 | import ( 25 | ol "github.com/ossrs/go-oryx-lib/logger" 26 | "os" 27 | ) 28 | 29 | func ExampleLogger_ToConsole() { 30 | // Simply log to console. 31 | ol.Info.Println(nil, "The log text.") 32 | ol.Trace.Println(nil, "The log text.") 33 | ol.Warn.Println(nil, "The log text.") 34 | ol.Error.Println(nil, "The log text.") 35 | 36 | // Use short aliases. 37 | ol.I(nil, "The log text.") 38 | ol.T(nil, "The log text.") 39 | ol.W(nil, "The log text.") 40 | ol.E(nil, "The log text.") 41 | 42 | // Use printf style log. 43 | ol.If(nil, "The log %v", "text") 44 | ol.Tf(nil, "The log %v", "text") 45 | ol.Wf(nil, "The log %v", "text") 46 | ol.Ef(nil, "The log %v", "text") 47 | } 48 | 49 | func ExampleLogger_ToFile() { 50 | // Open logger file and change the tank for logger. 51 | var err error 52 | var f *os.File 53 | if f, err = os.Open("sys.log"); err != nil { 54 | return 55 | } 56 | ol.Switch(f) 57 | 58 | // Use logger, which will write to file. 59 | ol.T(nil, "The log text.") 60 | 61 | // Close logger file when your application quit. 62 | defer ol.Close() 63 | } 64 | 65 | func ExampleLogger_SwitchFile() { 66 | // Initialize logger with file. 67 | var err error 68 | var f *os.File 69 | if f, err = os.Open("sys.log"); err != nil { 70 | return 71 | } 72 | ol.Switch(f) 73 | 74 | // When need to reap log file, 75 | // user must close current log file. 76 | ol.Close() 77 | // User can move the sys.log away. 78 | // Then reopen the log file and notify logger to use it. 79 | if f, err = os.Open("sys.log"); err != nil { 80 | return 81 | } 82 | // All logs between close and switch are dropped. 83 | ol.Switch(f) 84 | 85 | // Always close it. 86 | defer ol.Close() 87 | } 88 | 89 | // Each context is specified a connection, 90 | // which user must implement the interface. 91 | type cidContext int 92 | 93 | func (v cidContext) Cid() int { 94 | return int(v) 95 | } 96 | 97 | func ExampleLogger_ConnectionBased() { 98 | ctx := cidContext(100) 99 | ol.Info.Println(ctx, "The log text") 100 | ol.Trace.Println(ctx, "The log text.") 101 | ol.Warn.Println(ctx, "The log text.") 102 | ol.Error.Println(ctx, "The log text.") 103 | } 104 | -------------------------------------------------------------------------------- /logger/example_go17_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // +build go1.7 23 | 24 | package logger_test 25 | 26 | import ( 27 | "context" 28 | ol "github.com/ossrs/go-oryx-lib/logger" 29 | ) 30 | 31 | func ExampleLogger_ContextGO17() { 32 | ctx := context.Background() 33 | 34 | ctx, cancel := context.WithCancel(ctx) 35 | defer cancel() 36 | 37 | // Wrap the context, to support CID. 38 | ctx = ol.WithContext(ctx) 39 | 40 | // We must wrap the context. 41 | // For each coroutine or request, we must use a context. 42 | go func(ctx context.Context) { 43 | ol.T(ctx, "Log with context") 44 | 45 | ctx, cancel := context.WithCancel(ctx) 46 | defer cancel() 47 | func(ctx context.Context) { 48 | ol.T(ctx, "Log in child function") 49 | }(ctx) 50 | }(ctx) 51 | } 52 | 53 | func ExampleLogger_MultipleContextGO17() { 54 | ctx := context.Background() 55 | 56 | pfn := func(ctx context.Context) { 57 | ol.T(ctx, "Log with context") 58 | 59 | ctx, cancel := context.WithCancel(ctx) 60 | defer cancel() 61 | func(ctx context.Context) { 62 | ol.T(ctx, "Log in child function") 63 | }(ctx) 64 | } 65 | 66 | // We must wrap the context. 67 | // For each coroutine or request, we must use a context. 68 | func(ctx context.Context) { 69 | ctx, cancel := context.WithCancel(ctx) 70 | defer cancel() 71 | 72 | // Wrap the context, to support CID. 73 | ctx = ol.WithContext(ctx) 74 | go pfn(ctx) 75 | }(ctx) 76 | 77 | // Another goroutine, use another context if they aren't in the same scope. 78 | func(ctx context.Context) { 79 | ctx, cancel := context.WithCancel(ctx) 80 | defer cancel() 81 | 82 | // Wrap the context, to support CID. 83 | ctx = ol.WithContext(ctx) 84 | go pfn(ctx) 85 | }(ctx) 86 | } 87 | 88 | func ExampleLogger_AliasContext() { 89 | // This is the source context. 90 | source := ol.WithContext(context.Background()) 91 | 92 | // We should inherit from the parent context. 93 | parent := context.Background() 94 | 95 | // However, we maybe need to create a context from parent, 96 | // but with the same cid of source. 97 | ctx := ol.AliasContext(parent, source) 98 | 99 | // Now use the context, which has the same cid of source, 100 | // and it belongs to the parent context tree. 101 | _ = ctx 102 | } 103 | -------------------------------------------------------------------------------- /websocket/prepared.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "bytes" 10 | "net" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | // PreparedMessage caches on the wire representations of a message payload. 16 | // Use PreparedMessage to efficiently send a message payload to multiple 17 | // connections. PreparedMessage is especially useful when compression is used 18 | // because the CPU and memory expensive compression operation can be executed 19 | // once for a given set of compression options. 20 | type PreparedMessage struct { 21 | messageType int 22 | data []byte 23 | err error 24 | mu sync.Mutex 25 | frames map[prepareKey]*preparedFrame 26 | } 27 | 28 | // prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. 29 | type prepareKey struct { 30 | isServer bool 31 | compress bool 32 | compressionLevel int 33 | } 34 | 35 | // preparedFrame contains data in wire representation. 36 | type preparedFrame struct { 37 | once sync.Once 38 | data []byte 39 | } 40 | 41 | // NewPreparedMessage returns an initialized PreparedMessage. You can then send 42 | // it to connection using WritePreparedMessage method. Valid wire 43 | // representation will be calculated lazily only once for a set of current 44 | // connection options. 45 | func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { 46 | pm := &PreparedMessage{ 47 | messageType: messageType, 48 | frames: make(map[prepareKey]*preparedFrame), 49 | data: data, 50 | } 51 | 52 | // Prepare a plain server frame. 53 | _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | // To protect against caller modifying the data argument, remember the data 59 | // copied to the plain server frame. 60 | pm.data = frameData[len(frameData)-len(data):] 61 | return pm, nil 62 | } 63 | 64 | func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { 65 | pm.mu.Lock() 66 | frame, ok := pm.frames[key] 67 | if !ok { 68 | frame = &preparedFrame{} 69 | pm.frames[key] = frame 70 | } 71 | pm.mu.Unlock() 72 | 73 | var err error 74 | frame.once.Do(func() { 75 | // Prepare a frame using a 'fake' connection. 76 | // TODO: Refactor code in conn.go to allow more direct construction of 77 | // the frame. 78 | mu := make(chan bool, 1) 79 | mu <- true 80 | var nc prepareConn 81 | c := &Conn{ 82 | conn: &nc, 83 | mu: mu, 84 | isServer: key.isServer, 85 | compressionLevel: key.compressionLevel, 86 | enableWriteCompression: true, 87 | writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), 88 | } 89 | if key.compress { 90 | c.newCompressionWriter = compressNoContextTakeover 91 | } 92 | err = c.WriteMessage(pm.messageType, pm.data) 93 | frame.data = nc.buf.Bytes() 94 | }) 95 | return pm.messageType, frame.data, err 96 | } 97 | 98 | type prepareConn struct { 99 | buf bytes.Buffer 100 | net.Conn 101 | } 102 | 103 | func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } 104 | func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } 105 | -------------------------------------------------------------------------------- /json/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package json_test 23 | 24 | import ( 25 | "bytes" 26 | "encoding/json" 27 | "fmt" 28 | oj "github.com/ossrs/go-oryx-lib/json" 29 | "io/ioutil" 30 | ) 31 | 32 | func ExampleJson() { 33 | r := bytes.NewReader([]byte(` 34 | { 35 | "code":0, // An int error code, where 0 is success. 36 | "data": /*An interface{} data.*/ "There is no error", 37 | "json+": true // Both "" and '' is ok for json+ 38 | } 39 | `)) 40 | 41 | j := json.NewDecoder(oj.NewJsonPlusReader(r)) 42 | 43 | obj := struct { 44 | Code int `json:"code"` 45 | Data string `json:"data"` 46 | JsonPlus bool `json:"json+"` 47 | }{} 48 | if err := j.Decode(&obj); err != nil { 49 | fmt.Println("json+ decode failed, err is", err) 50 | return 51 | } 52 | 53 | // User can decode more objects from reader. 54 | 55 | fmt.Println("Code:", obj.Code) 56 | fmt.Println("Data:", obj.Data) 57 | fmt.Println("JsonPlus:", obj.JsonPlus) 58 | 59 | // Output: 60 | // Code: 0 61 | // Data: There is no error 62 | // JsonPlus: true 63 | } 64 | 65 | func ExampleJson_Unmarshal() { 66 | s := `{"code":100,"data":"There is something error"}` 67 | var obj interface{} 68 | if err := oj.Unmarshal(bytes.NewBuffer([]byte(s)), &obj); err != nil { 69 | fmt.Println("json+ unmarshal failed, err is", err) 70 | return 71 | } 72 | 73 | if obj, ok := obj.(map[string]interface{}); ok { 74 | fmt.Println("Code:", obj["code"]) 75 | fmt.Println("Data:", obj["data"]) 76 | } 77 | 78 | // Output: 79 | // Code: 100 80 | // Data: There is something error 81 | } 82 | 83 | func ExampleJson_NewCommentReader() { 84 | // The following is comment: 85 | // # xxxx \n 86 | // Where the following is string: 87 | // 'xxx' 88 | // "xxx" 89 | // That is, the following is not a comment: 90 | // "xxx'xx'xx#xxx" 91 | r := bytes.NewReader([]byte(` 92 | # for which cannot identify the required vhost. 93 | vhost __defaultVhost__ { 94 | } 95 | `)) 96 | cr := oj.NewCommentReader(r, 97 | [][]byte{[]byte("'"), []byte("\""), []byte("#")}, 98 | [][]byte{[]byte("'"), []byte("\""), []byte("\n")}, 99 | []bool{false, false, true}, 100 | []bool{true, true, false}, 101 | ) 102 | if o, err := ioutil.ReadAll(cr); err != nil { 103 | fmt.Println("json+ read without comments failed, err is", err) 104 | return 105 | } else { 106 | fmt.Println(string(o)) 107 | } 108 | 109 | // Output: 110 | // vhost __defaultVhost__ { 111 | // } 112 | } 113 | -------------------------------------------------------------------------------- /options/options.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The oryx options package parse the options with config file. 23 | // -c, to specifies the config file. 24 | // -v, to print version and quit. 25 | // -g, to print signature and quit. 26 | // -h, to print help and quit. 27 | // We return the parsed config file path. 28 | package options 29 | 30 | import ( 31 | "flag" 32 | "fmt" 33 | "os" 34 | ) 35 | 36 | // parse the argv with config, version and signature. 37 | // @param rcf The recomment config file path. 38 | // @param version The vesion of application, such as 1.2.3 39 | // @param signature The signature of application, such as SRS/1.2.3 40 | func ParseArgv(rcf, version, signature string) (confFile string) { 41 | // the args format: 42 | // -c conf/ory.json 43 | // --c conf/oryx.json 44 | // -c=conf/oryx.json 45 | // --c=conf/oryx.json 46 | // --conf=conf/oryx.json 47 | if true { 48 | dv := "" 49 | ua := "The config file" 50 | flag.StringVar(&confFile, "c", dv, ua) 51 | flag.StringVar(&confFile, "conf", dv, ua) 52 | } 53 | 54 | var showVersion bool 55 | if true { 56 | dv := false 57 | ua := "Print version" 58 | flag.BoolVar(&showVersion, "v", dv, ua) 59 | flag.BoolVar(&showVersion, "V", dv, ua) 60 | flag.BoolVar(&showVersion, "version", dv, ua) 61 | } 62 | 63 | var showSignature bool 64 | if true { 65 | dv := false 66 | ua := "print signature" 67 | flag.BoolVar(&showSignature, "g", dv, ua) 68 | flag.BoolVar(&showSignature, "signature", dv, ua) 69 | } 70 | 71 | flag.Usage = func() { 72 | fmt.Println(signature) 73 | fmt.Println(fmt.Sprintf("Usage: %v [-c|--conf ] [-?|-h|--help] [-v|-V|--version] [-g|--signature]", os.Args[0])) 74 | fmt.Println(fmt.Sprintf(" -c, --conf filename : The config file path")) 75 | fmt.Println(fmt.Sprintf(" -?, -h, --help : Show this help and exit")) 76 | fmt.Println(fmt.Sprintf(" -v, -V, --version : Print version and exit")) 77 | fmt.Println(fmt.Sprintf(" -g, --signature : Print signature and exit")) 78 | fmt.Println(fmt.Sprintf("For example:")) 79 | fmt.Println(fmt.Sprintf(" %v -c %v", os.Args[0], rcf)) 80 | } 81 | flag.Parse() 82 | 83 | if showVersion { 84 | fmt.Fprintln(os.Stderr, version) 85 | os.Exit(0) 86 | } 87 | 88 | if showSignature { 89 | fmt.Fprintln(os.Stderr, signature) 90 | os.Exit(0) 91 | } 92 | 93 | if len(confFile) == 0 { 94 | flag.Usage() 95 | os.Exit(-1) 96 | } 97 | 98 | return 99 | } 100 | -------------------------------------------------------------------------------- /websocket/conn_broadcast_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | // fork from https://github.com/gorilla/websocket 8 | package websocket 9 | 10 | import ( 11 | "io" 12 | "io/ioutil" 13 | "sync/atomic" 14 | "testing" 15 | ) 16 | 17 | // broadcastBench allows to run broadcast benchmarks. 18 | // In every broadcast benchmark we create many connections, then send the same 19 | // message into every connection and wait for all writes complete. This emulates 20 | // an application where many connections listen to the same data - i.e. PUB/SUB 21 | // scenarios with many subscribers in one channel. 22 | type broadcastBench struct { 23 | w io.Writer 24 | message *broadcastMessage 25 | closeCh chan struct{} 26 | doneCh chan struct{} 27 | count int32 28 | conns []*broadcastConn 29 | compression bool 30 | usePrepared bool 31 | } 32 | 33 | type broadcastMessage struct { 34 | payload []byte 35 | prepared *PreparedMessage 36 | } 37 | 38 | type broadcastConn struct { 39 | conn *Conn 40 | msgCh chan *broadcastMessage 41 | } 42 | 43 | func newBroadcastConn(c *Conn) *broadcastConn { 44 | return &broadcastConn{ 45 | conn: c, 46 | msgCh: make(chan *broadcastMessage, 1), 47 | } 48 | } 49 | 50 | func newBroadcastBench(usePrepared, compression bool) *broadcastBench { 51 | bench := &broadcastBench{ 52 | w: ioutil.Discard, 53 | doneCh: make(chan struct{}), 54 | closeCh: make(chan struct{}), 55 | usePrepared: usePrepared, 56 | compression: compression, 57 | } 58 | msg := &broadcastMessage{ 59 | payload: textMessages(1)[0], 60 | } 61 | if usePrepared { 62 | pm, _ := NewPreparedMessage(TextMessage, msg.payload) 63 | msg.prepared = pm 64 | } 65 | bench.message = msg 66 | bench.makeConns(10000) 67 | return bench 68 | } 69 | 70 | func (b *broadcastBench) makeConns(numConns int) { 71 | conns := make([]*broadcastConn, numConns) 72 | 73 | for i := 0; i < numConns; i++ { 74 | c := newConn(fakeNetConn{Reader: nil, Writer: b.w}, true, 1024, 1024) 75 | if b.compression { 76 | c.enableWriteCompression = true 77 | c.newCompressionWriter = compressNoContextTakeover 78 | } 79 | conns[i] = newBroadcastConn(c) 80 | go func(c *broadcastConn) { 81 | for { 82 | select { 83 | case msg := <-c.msgCh: 84 | if b.usePrepared { 85 | c.conn.WritePreparedMessage(msg.prepared) 86 | } else { 87 | c.conn.WriteMessage(TextMessage, msg.payload) 88 | } 89 | val := atomic.AddInt32(&b.count, 1) 90 | if val%int32(numConns) == 0 { 91 | b.doneCh <- struct{}{} 92 | } 93 | case <-b.closeCh: 94 | return 95 | } 96 | } 97 | }(conns[i]) 98 | } 99 | b.conns = conns 100 | } 101 | 102 | func (b *broadcastBench) close() { 103 | close(b.closeCh) 104 | } 105 | 106 | func (b *broadcastBench) runOnce() { 107 | for _, c := range b.conns { 108 | c.msgCh <- b.message 109 | } 110 | <-b.doneCh 111 | } 112 | 113 | func BenchmarkBroadcast(b *testing.B) { 114 | benchmarks := []struct { 115 | name string 116 | usePrepared bool 117 | compression bool 118 | }{ 119 | {"NoCompression", false, false}, 120 | {"WithCompression", false, true}, 121 | {"NoCompressionPrepared", true, false}, 122 | {"WithCompressionPrepared", true, true}, 123 | } 124 | for _, bm := range benchmarks { 125 | b.Run(bm.name, func(b *testing.B) { 126 | bench := newBroadcastBench(bm.usePrepared, bm.compression) 127 | defer bench.close() 128 | b.ResetTimer() 129 | for i := 0; i < b.N; i++ { 130 | bench.runOnce() 131 | } 132 | b.ReportAllocs() 133 | }) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /websocket/compression.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "compress/flate" 10 | "errors" 11 | "io" 12 | "strings" 13 | "sync" 14 | ) 15 | 16 | const ( 17 | minCompressionLevel = -2 // flate.HuffmanOnly not defined in Go < 1.6 18 | maxCompressionLevel = flate.BestCompression 19 | defaultCompressionLevel = 1 20 | ) 21 | 22 | var ( 23 | flateWriterPools [maxCompressionLevel - minCompressionLevel + 1]sync.Pool 24 | flateReaderPool = sync.Pool{New: func() interface{} { 25 | return flate.NewReader(nil) 26 | }} 27 | ) 28 | 29 | func decompressNoContextTakeover(r io.Reader) io.ReadCloser { 30 | const tail = 31 | // Add four bytes as specified in RFC 32 | "\x00\x00\xff\xff" + 33 | // Add final block to squelch unexpected EOF error from flate reader. 34 | "\x01\x00\x00\xff\xff" 35 | 36 | fr, _ := flateReaderPool.Get().(io.ReadCloser) 37 | fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil) 38 | return &flateReadWrapper{fr} 39 | } 40 | 41 | func isValidCompressionLevel(level int) bool { 42 | return minCompressionLevel <= level && level <= maxCompressionLevel 43 | } 44 | 45 | func compressNoContextTakeover(w io.WriteCloser, level int) io.WriteCloser { 46 | p := &flateWriterPools[level-minCompressionLevel] 47 | tw := &truncWriter{w: w} 48 | fw, _ := p.Get().(*flate.Writer) 49 | if fw == nil { 50 | fw, _ = flate.NewWriter(tw, level) 51 | } else { 52 | fw.Reset(tw) 53 | } 54 | return &flateWriteWrapper{fw: fw, tw: tw, p: p} 55 | } 56 | 57 | // truncWriter is an io.Writer that writes all but the last four bytes of the 58 | // stream to another io.Writer. 59 | type truncWriter struct { 60 | w io.WriteCloser 61 | n int 62 | p [4]byte 63 | } 64 | 65 | func (w *truncWriter) Write(p []byte) (int, error) { 66 | n := 0 67 | 68 | // fill buffer first for simplicity. 69 | if w.n < len(w.p) { 70 | n = copy(w.p[w.n:], p) 71 | p = p[n:] 72 | w.n += n 73 | if len(p) == 0 { 74 | return n, nil 75 | } 76 | } 77 | 78 | m := len(p) 79 | if m > len(w.p) { 80 | m = len(w.p) 81 | } 82 | 83 | if nn, err := w.w.Write(w.p[:m]); err != nil { 84 | return n + nn, err 85 | } 86 | 87 | copy(w.p[:], w.p[m:]) 88 | copy(w.p[len(w.p)-m:], p[len(p)-m:]) 89 | nn, err := w.w.Write(p[:len(p)-m]) 90 | return n + nn, err 91 | } 92 | 93 | type flateWriteWrapper struct { 94 | fw *flate.Writer 95 | tw *truncWriter 96 | p *sync.Pool 97 | } 98 | 99 | func (w *flateWriteWrapper) Write(p []byte) (int, error) { 100 | if w.fw == nil { 101 | return 0, errWriteClosed 102 | } 103 | return w.fw.Write(p) 104 | } 105 | 106 | func (w *flateWriteWrapper) Close() error { 107 | if w.fw == nil { 108 | return errWriteClosed 109 | } 110 | err1 := w.fw.Flush() 111 | w.p.Put(w.fw) 112 | w.fw = nil 113 | if w.tw.p != [4]byte{0, 0, 0xff, 0xff} { 114 | return errors.New("websocket: internal error, unexpected bytes at end of flate stream") 115 | } 116 | err2 := w.tw.w.Close() 117 | if err1 != nil { 118 | return err1 119 | } 120 | return err2 121 | } 122 | 123 | type flateReadWrapper struct { 124 | fr io.ReadCloser 125 | } 126 | 127 | func (r *flateReadWrapper) Read(p []byte) (int, error) { 128 | if r.fr == nil { 129 | return 0, io.ErrClosedPipe 130 | } 131 | n, err := r.fr.Read(p) 132 | if err == io.EOF { 133 | // Preemptively place the reader back in the pool. This helps with 134 | // scenarios where the application does not call NextReader() soon after 135 | // this final read. 136 | r.Close() 137 | } 138 | return n, err 139 | } 140 | 141 | func (r *flateReadWrapper) Close() error { 142 | if r.fr == nil { 143 | return io.ErrClosedPipe 144 | } 145 | err := r.fr.Close() 146 | flateReaderPool.Put(r.fr) 147 | r.fr = nil 148 | return err 149 | } 150 | -------------------------------------------------------------------------------- /https/acme/http.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "encoding/json" 7 | "errors" 8 | "fmt" 9 | "io" 10 | "net/http" 11 | "runtime" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | // UserAgent (if non-empty) will be tacked onto the User-Agent string in requests. 17 | var UserAgent string 18 | 19 | // defaultClient is an HTTP client with a reasonable timeout value. 20 | var defaultClient = http.Client{Timeout: 10 * time.Second} 21 | 22 | const ( 23 | // defaultGoUserAgent is the Go HTTP package user agent string. Too 24 | // bad it isn't exported. If it changes, we should update it here, too. 25 | defaultGoUserAgent = "Go-http-client/1.1" 26 | 27 | // ourUserAgent is the User-Agent of this underlying library package. 28 | ourUserAgent = "xenolf-acme" 29 | ) 30 | 31 | // httpHead performs a HEAD request with a proper User-Agent string. 32 | // The response body (resp.Body) is already closed when this function returns. 33 | func httpHead(url string) (resp *http.Response, err error) { 34 | req, err := http.NewRequest("HEAD", url, nil) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | req.Header.Set("User-Agent", userAgent()) 40 | 41 | resp, err = defaultClient.Do(req) 42 | if err != nil { 43 | return resp, err 44 | } 45 | resp.Body.Close() 46 | return resp, err 47 | } 48 | 49 | // httpPost performs a POST request with a proper User-Agent string. 50 | // Callers should close resp.Body when done reading from it. 51 | func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) { 52 | req, err := http.NewRequest("POST", url, body) 53 | if err != nil { 54 | return nil, err 55 | } 56 | req.Header.Set("Content-Type", bodyType) 57 | req.Header.Set("User-Agent", userAgent()) 58 | 59 | return defaultClient.Do(req) 60 | } 61 | 62 | // httpGet performs a GET request with a proper User-Agent string. 63 | // Callers should close resp.Body when done reading from it. 64 | func httpGet(url string) (resp *http.Response, err error) { 65 | req, err := http.NewRequest("GET", url, nil) 66 | if err != nil { 67 | return nil, err 68 | } 69 | req.Header.Set("User-Agent", userAgent()) 70 | 71 | return defaultClient.Do(req) 72 | } 73 | 74 | // getJSON performs an HTTP GET request and parses the response body 75 | // as JSON, into the provided respBody object. 76 | func getJSON(uri string, respBody interface{}) (http.Header, error) { 77 | resp, err := httpGet(uri) 78 | if err != nil { 79 | return nil, fmt.Errorf("failed to get %q: %v", uri, err) 80 | } 81 | defer resp.Body.Close() 82 | 83 | if resp.StatusCode >= http.StatusBadRequest { 84 | return resp.Header, handleHTTPError(resp) 85 | } 86 | 87 | return resp.Header, json.NewDecoder(resp.Body).Decode(respBody) 88 | } 89 | 90 | // postJSON performs an HTTP POST request and parses the response body 91 | // as JSON, into the provided respBody object. 92 | func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) { 93 | jsonBytes, err := json.Marshal(reqBody) 94 | if err != nil { 95 | return nil, errors.New("Failed to marshal network message...") 96 | } 97 | 98 | resp, err := j.post(uri, jsonBytes) 99 | if err != nil { 100 | return nil, fmt.Errorf("Failed to post JWS message. -> %v", err) 101 | } 102 | defer resp.Body.Close() 103 | 104 | if resp.StatusCode >= http.StatusBadRequest { 105 | return resp.Header, handleHTTPError(resp) 106 | } 107 | 108 | if respBody == nil { 109 | return resp.Header, nil 110 | } 111 | 112 | return resp.Header, json.NewDecoder(resp.Body).Decode(respBody) 113 | } 114 | 115 | // userAgent builds and returns the User-Agent string to use in requests. 116 | func userAgent() string { 117 | ua := fmt.Sprintf("%s (%s; %s) %s %s", defaultGoUserAgent, runtime.GOOS, runtime.GOARCH, ourUserAgent, UserAgent) 118 | return strings.TrimSpace(ua) 119 | } 120 | -------------------------------------------------------------------------------- /https/https.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package https 23 | 24 | import ( 25 | "crypto/tls" 26 | "fmt" 27 | "github.com/ossrs/go-oryx-lib/https/letsencrypt" 28 | "runtime" 29 | "strconv" 30 | "strings" 31 | ) 32 | 33 | // Requires golang 1.6+, because there's bug in http.Server 34 | // to set the GetCertificate of TLSConfig. 35 | func checkRuntime() (err error) { 36 | version := strings.Trim(runtime.Version(), "go") 37 | if versions := strings.Split(version, "."); len(versions) < 1 { 38 | return fmt.Errorf("invalid version=%v", version) 39 | } else if major, err := strconv.Atoi(versions[0]); err != nil { 40 | return fmt.Errorf("invalid version=%v, err=%v", version, err) 41 | } else if minor, err := strconv.Atoi(versions[1]); err != nil { 42 | return fmt.Errorf("invalid version=%v, err=%v", version, err) 43 | } else if major == 1 && minor < 6 { 44 | return fmt.Errorf("requires golang 1.6+, version=%v(%v.%v)", version, major, minor) 45 | } 46 | 47 | return 48 | } 49 | 50 | // The https manager which provides the certificate. 51 | type Manager interface { 52 | GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) 53 | } 54 | 55 | // The cert is sign by ourself. 56 | type selfSignManager struct { 57 | cert *tls.Certificate 58 | certFile string 59 | keyFile string 60 | } 61 | 62 | func NewSelfSignManager(certFile, keyFile string) (m Manager, err error) { 63 | if err = checkRuntime(); err != nil { 64 | return 65 | } 66 | return &selfSignManager{certFile: certFile, keyFile: keyFile}, nil 67 | } 68 | 69 | func (v *selfSignManager) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { 70 | if v.cert != nil { 71 | return v.cert, nil 72 | } 73 | 74 | cert, err := tls.LoadX509KeyPair(v.certFile, v.keyFile) 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | // cache the cert. 80 | v.cert = &cert 81 | 82 | return &cert, err 83 | } 84 | 85 | // The cert is sign by letsencrypt 86 | type letsencryptManager struct { 87 | lets letsencrypt.Manager 88 | } 89 | 90 | // Register the email to letsencrypt, cache the certs in cacheFile, set allow hosts. 91 | // @remark set hosts to empty string when allow all request hosts, but maybe attack. 92 | // @remark set email to nil to not regiester, use empty email to request cert from letsencrypt. 93 | // @remark set cacheFile to empty string to not cache the info and certs. 94 | // @remark we only use tls validate, https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni 95 | // so the https port must be 443, we cannot serve at other ports. 96 | func NewLetsencryptManager(email string, hosts []string, cacheFile string) (m Manager, err error) { 97 | v := &letsencryptManager{} 98 | 99 | if err = checkRuntime(); err != nil { 100 | return 101 | } 102 | 103 | if cacheFile != "" { 104 | if err = v.lets.CacheFile(cacheFile); err != nil { 105 | return 106 | } 107 | } 108 | 109 | if len(hosts) > 0 { 110 | v.lets.SetHosts(hosts) 111 | } 112 | 113 | if email != "" { 114 | if err = v.lets.Register(email, nil); err != nil { 115 | return 116 | } 117 | } 118 | 119 | return v, nil 120 | } 121 | 122 | func (v *letsencryptManager) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { 123 | return v.lets.GetCertificate(clientHello) 124 | } 125 | -------------------------------------------------------------------------------- /https/acme/messages.go: -------------------------------------------------------------------------------- 1 | // fork from https://github.com/rsc/letsencrypt/tree/master/vendor/github.com/xenolf/lego/acme 2 | // fork from https://github.com/xenolf/lego/tree/master/acme 3 | package acme 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/ossrs/go-oryx-lib/https/jose" 9 | ) 10 | 11 | type directory struct { 12 | NewAuthzURL string `json:"new-authz"` 13 | NewCertURL string `json:"new-cert"` 14 | NewRegURL string `json:"new-reg"` 15 | RevokeCertURL string `json:"revoke-cert"` 16 | } 17 | 18 | type recoveryKeyMessage struct { 19 | Length int `json:"length,omitempty"` 20 | Client jose.JsonWebKey `json:"client,omitempty"` 21 | Server jose.JsonWebKey `json:"client,omitempty"` 22 | } 23 | 24 | type registrationMessage struct { 25 | Resource string `json:"resource"` 26 | Contact []string `json:"contact"` 27 | // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"` 28 | } 29 | 30 | // Registration is returned by the ACME server after the registration 31 | // The client implementation should save this registration somewhere. 32 | type Registration struct { 33 | Resource string `json:"resource,omitempty"` 34 | ID int `json:"id"` 35 | Key jose.JsonWebKey `json:"key"` 36 | Contact []string `json:"contact"` 37 | Agreement string `json:"agreement,omitempty"` 38 | Authorizations string `json:"authorizations,omitempty"` 39 | Certificates string `json:"certificates,omitempty"` 40 | // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"` 41 | } 42 | 43 | // RegistrationResource represents all important informations about a registration 44 | // of which the client needs to keep track itself. 45 | type RegistrationResource struct { 46 | Body Registration `json:"body,omitempty"` 47 | URI string `json:"uri,omitempty"` 48 | NewAuthzURL string `json:"new_authzr_uri,omitempty"` 49 | TosURL string `json:"terms_of_service,omitempty"` 50 | } 51 | 52 | type authorizationResource struct { 53 | Body authorization 54 | Domain string 55 | NewCertURL string 56 | AuthURL string 57 | } 58 | 59 | type authorization struct { 60 | Resource string `json:"resource,omitempty"` 61 | Identifier identifier `json:"identifier"` 62 | Status string `json:"status,omitempty"` 63 | Expires time.Time `json:"expires,omitempty"` 64 | Challenges []challenge `json:"challenges,omitempty"` 65 | Combinations [][]int `json:"combinations,omitempty"` 66 | } 67 | 68 | type identifier struct { 69 | Type string `json:"type"` 70 | Value string `json:"value"` 71 | } 72 | 73 | type validationRecord struct { 74 | URI string `json:"url,omitempty"` 75 | Hostname string `json:"hostname,omitempty"` 76 | Port string `json:"port,omitempty"` 77 | ResolvedAddresses []string `json:"addressesResolved,omitempty"` 78 | UsedAddress string `json:"addressUsed,omitempty"` 79 | } 80 | 81 | type challenge struct { 82 | Resource string `json:"resource,omitempty"` 83 | Type Challenge `json:"type,omitempty"` 84 | Status string `json:"status,omitempty"` 85 | URI string `json:"uri,omitempty"` 86 | Token string `json:"token,omitempty"` 87 | KeyAuthorization string `json:"keyAuthorization,omitempty"` 88 | TLS bool `json:"tls,omitempty"` 89 | Iterations int `json:"n,omitempty"` 90 | Error RemoteError `json:"error,omitempty"` 91 | ValidationRecords []validationRecord `json:"validationRecord,omitempty"` 92 | } 93 | 94 | type csrMessage struct { 95 | Resource string `json:"resource,omitempty"` 96 | Csr string `json:"csr"` 97 | Authorizations []string `json:"authorizations"` 98 | } 99 | 100 | type revokeCertMessage struct { 101 | Resource string `json:"resource"` 102 | Certificate string `json:"certificate"` 103 | } 104 | 105 | // CertificateResource represents a CA issued certificate. 106 | // PrivateKey and Certificate are both already PEM encoded 107 | // and can be directly written to disk. Certificate may 108 | // be a certificate bundle, depending on the options supplied 109 | // to create it. 110 | type CertificateResource struct { 111 | Domain string `json:"domain"` 112 | CertURL string `json:"certUrl"` 113 | CertStableURL string `json:"certStableUrl"` 114 | AccountRef string `json:"accountRef,omitempty"` 115 | PrivateKey []byte `json:"-"` 116 | Certificate []byte `json:"-"` 117 | } 118 | -------------------------------------------------------------------------------- /aac/aac_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package aac 23 | 24 | import ( 25 | "bytes" 26 | "testing" 27 | ) 28 | 29 | func TestAudioSpecificConfig_MarshalBinary(t *testing.T) { 30 | asc := &AudioSpecificConfig{} 31 | 32 | if _, err := asc.MarshalBinary(); err == nil { 33 | t.Error("marshal") 34 | } 35 | 36 | asc.Object = ObjectTypeMain 37 | if _, err := asc.MarshalBinary(); err == nil { 38 | t.Error("marshal") 39 | } 40 | 41 | asc.SampleRate = SampleRateIndex44kHz 42 | if _, err := asc.MarshalBinary(); err == nil { 43 | t.Error("marshal") 44 | } 45 | 46 | asc.Channels = ChannelStereo 47 | if _, err := asc.MarshalBinary(); err != nil { 48 | t.Errorf("marshal failed %+v", err) 49 | } 50 | } 51 | 52 | func TestAudioSpecificConfig_UnmarshalBinary(t *testing.T) { 53 | asc := &AudioSpecificConfig{} 54 | 55 | if err := asc.UnmarshalBinary(nil); err == nil { 56 | t.Error("unmarshal") 57 | } 58 | 59 | if err := asc.UnmarshalBinary([]byte{0x12}); err == nil { 60 | t.Error("unmarshal") 61 | } 62 | 63 | if err := asc.UnmarshalBinary([]byte{0x12, 0x10}); err != nil { 64 | t.Errorf("%+v", err) 65 | } 66 | } 67 | 68 | func TestAdts_Encode(t *testing.T) { 69 | adts, err := NewADTS() 70 | if err != nil { 71 | t.Errorf("%+v", err) 72 | } 73 | 74 | if err = adts.SetASC([]byte{0x12, 0x10}); err != nil { 75 | t.Errorf("%+v", err) 76 | } 77 | 78 | if data, err := adts.Encode(nil); err != nil { 79 | t.Errorf("%+v", err) 80 | } else if len(data) != 7 { 81 | t.Error("encode") 82 | } 83 | 84 | if data, err := adts.Encode([]byte{0x00}); err != nil { 85 | t.Errorf("%+v", err) 86 | } else if len(data) != 8 { 87 | t.Error("encode") 88 | } 89 | } 90 | 91 | func TestAdts_Decode(t *testing.T) { 92 | adts, err := NewADTS() 93 | if err != nil { 94 | t.Errorf("%+v", err) 95 | } 96 | 97 | if raw, left, err := adts.Decode([]byte{ 98 | 0xff, 0xf1, 0x50, 0x80, 0x01, 0x00, 0xfc, 0x00, 99 | }); err != nil { 100 | t.Errorf("%+v", err) 101 | } else if bytes.Compare(raw, []byte{0x00}) != 0 { 102 | t.Errorf("%#x", raw) 103 | } else if len(left) != 0 { 104 | t.Errorf("%#x", left) 105 | } 106 | 107 | asc := adts.ASC() 108 | if asc.Object != ObjectTypeLC { 109 | t.Error(asc.Object) 110 | } 111 | if asc.SampleRate != SampleRateIndex44kHz { 112 | t.Error(asc.SampleRate) 113 | } 114 | if asc.Channels != ChannelStereo { 115 | t.Error(asc.Channels) 116 | } 117 | } 118 | 119 | func TestAdts_Decode2(t *testing.T) { 120 | adts, err := NewADTS() 121 | if err != nil { 122 | t.Errorf("%+v", err) 123 | } 124 | 125 | if raw, left, err := adts.Decode([]byte{ 126 | 0xff, 0xf1, 0x50, 0x80, 0x01, 0x00, 0xfc, 0x00, 0x01, 127 | }); err != nil { 128 | t.Errorf("%+v", err) 129 | } else if bytes.Compare(raw, []byte{0x00}) != 0 { 130 | t.Errorf("%#x", raw) 131 | } else if bytes.Compare(left, []byte{0x01}) != 0 { 132 | t.Errorf("%#x", left) 133 | } 134 | } 135 | 136 | func TestAdts_Decode3(t *testing.T) { 137 | adts, err := NewADTS() 138 | if err != nil { 139 | t.Errorf("%+v", err) 140 | } 141 | 142 | if _, _, err = adts.Decode(nil); err == nil { 143 | t.Error("decode") 144 | } 145 | 146 | if _, _, err = adts.Decode([]byte{0x00}); err == nil { 147 | t.Error("decode") 148 | } 149 | 150 | if _, _, err = adts.Decode(make([]byte, 7)); err == nil { 151 | t.Error("decode") 152 | } 153 | } 154 | 155 | func TestAdts_Decode4(t *testing.T) { 156 | adts, err := NewADTS() 157 | if err != nil { 158 | t.Errorf("%+v", err) 159 | } 160 | 161 | if _, _, err := adts.Decode([]byte{ 162 | 0xff, 0xf1, 0xff, 0x80, 0x01, 0x00, 0xfc, 0x00, 163 | }); err == nil { 164 | t.Error("decode") 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /http/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package http_test 23 | 24 | import ( 25 | "fmt" 26 | oh "github.com/ossrs/go-oryx-lib/http" 27 | "net/http" 28 | ) 29 | 30 | func ExampleHttpTest_Global() { 31 | oh.Server = "Test" 32 | fmt.Println("Server:", oh.Server) 33 | 34 | // Output: 35 | // Server: Test 36 | } 37 | 38 | func ExampleHttpTest_RawResponse() { 39 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 40 | // Set the common response header when need to write RAW message. 41 | oh.SetHeader(w) 42 | 43 | // Write RAW message only, or should use the Error() or Data() functions. 44 | w.Write([]byte("Hello, World!")) 45 | }) 46 | } 47 | 48 | func ExampleHttpTest_JsonData() { 49 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 50 | // Response data which can be marshal to json. 51 | oh.Data(nil, map[string]interface{}{ 52 | "version": "1.0", 53 | "count": 100, 54 | }).ServeHTTP(w, r) 55 | }) 56 | } 57 | 58 | func ExampleHttpTest_Error() { 59 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 60 | // Response unknown error with HTTP/500 61 | oh.Error(nil, fmt.Errorf("System error")).ServeHTTP(w, r) 62 | }) 63 | 64 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 65 | // Response known error {code:xx} 66 | oh.Error(nil, oh.SystemError(100)).ServeHTTP(w, r) 67 | }) 68 | 69 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 70 | // Response known complex error {code:xx,data:"xxx"} 71 | oh.Error(nil, oh.SystemComplexError{oh.SystemError(100), "Error description"}).ServeHTTP(w, r) 72 | }) 73 | 74 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 75 | // Response known complex error {code:xx,data:"xxx"} 76 | oh.CplxError(nil, oh.SystemError(100), "Error description").ServeHTTP(w, r) 77 | }) 78 | } 79 | 80 | func ExampleWrite() { 81 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 82 | // Only response a success json. 83 | oh.Success(nil, w, r) 84 | }) 85 | 86 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 87 | // Response data which can be marshal to json. 88 | oh.WriteData(nil, w, r, map[string]interface{}{ 89 | "version": "1.0", 90 | "count": 100, 91 | }) 92 | }) 93 | 94 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 95 | // Response unknown error with HTTP/500 96 | oh.WriteError(nil, w, r, fmt.Errorf("System error")) 97 | }) 98 | 99 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 100 | // Response known error {code:xx} 101 | oh.WriteError(nil, w, r, oh.SystemError(100)) 102 | }) 103 | 104 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 105 | // Response known complex error {code:xx,data:"xxx"} 106 | oh.WriteError(nil, w, r, oh.SystemComplexError{oh.SystemError(100), "Error description"}) 107 | }) 108 | 109 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 110 | // Response known complex error {code:xx,data:"xxx"} 111 | oh.WriteCplxError(nil, w, r, oh.SystemError(100), "Error description") 112 | }) 113 | } 114 | 115 | func ExampleWriteVersion() { 116 | http.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { 117 | // version is major.minor.revisoin-extra 118 | oh.WriteVersion(w, r, "1.2.3-4") 119 | }) 120 | } 121 | 122 | func ExampleApiRequest() { 123 | var err error 124 | var body []byte 125 | if _, body, err = oh.ApiRequest("http://127.0.0.1985/api/v1/versions"); err != nil { 126 | return 127 | } 128 | 129 | // user can use the body to parse to specified struct. 130 | _ = body 131 | } 132 | -------------------------------------------------------------------------------- /json/json.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The oryx json package support json with c++ style comments. 23 | // User can use the following APIs: 24 | // Unmarshal, directly unmarshal a Reader to object, like json.Unmarshal 25 | // NewJsonPlusReader, convert the Reader to data stream without comments. 26 | // NewCommentReader, specified the special comment or tags. 27 | package json 28 | 29 | import ( 30 | "bufio" 31 | "bytes" 32 | "encoding/json" 33 | "errors" 34 | "io" 35 | ) 36 | 37 | // user can directly use this to UnMarshal a json stream. 38 | func Unmarshal(r io.Reader, v interface{}) (err error) { 39 | // read the whole config to []byte. 40 | var d *json.Decoder 41 | 42 | d = json.NewDecoder(NewJsonPlusReader(r)) 43 | //d = json.NewDecoder(f) 44 | 45 | if err = d.Decode(v); err != nil { 46 | return 47 | } 48 | return 49 | } 50 | 51 | // the reader support c++-style comment, 52 | // block: /* comments */ 53 | // line: // comments 54 | // to filter the comment and got pure raw data. 55 | func NewJsonPlusReader(r io.Reader) io.Reader { 56 | startMatches := [][]byte{[]byte("'"), []byte("\""), []byte("//"), []byte("/*")} 57 | endMatches := [][]byte{[]byte("'"), []byte("\""), []byte("\n"), []byte("*/")} 58 | isComments := []bool{false, false, true, true} 59 | requiredMatches := []bool{true, true, false, true} 60 | return NewCommentReader(r, startMatches, endMatches, isComments, requiredMatches) 61 | } 62 | 63 | // error when comment not match. 64 | var commentNotMatch = errors.New("comment not match") 65 | 66 | // the reader to ignore specified comments or tags. 67 | func NewCommentReader(r io.Reader, startMatches, endMatches [][]byte, isComments, requiredMatches []bool) io.Reader { 68 | v := &commentReader{ 69 | s: bufio.NewScanner(r), 70 | b: &bytes.Buffer{}, 71 | } 72 | 73 | v.s.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) { 74 | if atEOF && len(data) == 0 { 75 | // read more. 76 | return 0, nil, nil 77 | } 78 | 79 | pos, index := firstMatch(data, startMatches) 80 | if pos == -1 || index == -1 { 81 | if atEOF { 82 | return len(data), data[:], nil 83 | } 84 | return 0, nil, nil 85 | } 86 | 87 | var extra int 88 | left := data[pos+len(startMatches[index]):] 89 | if extra = bytes.Index(left, endMatches[index]); extra == -1 { 90 | if atEOF { 91 | if requiredMatches[index] { 92 | return 0, nil, commentNotMatch 93 | } 94 | extra = len(left) - len(endMatches[index]) 95 | } else { 96 | return 0, nil, nil 97 | } 98 | } 99 | 100 | // always consume util end of match. 101 | advance = pos + len(startMatches[index]) + extra + len(endMatches[index]) 102 | 103 | if !isComments[index] { 104 | return advance, data[:advance], nil 105 | } 106 | return advance, data[:pos], nil 107 | }) 108 | return v 109 | } 110 | 111 | // the reader support comment with start and end chars. 112 | type commentReader struct { 113 | b *bytes.Buffer 114 | s *bufio.Scanner 115 | } 116 | 117 | // interface io.Reader 118 | func (v *commentReader) Read(p []byte) (n int, err error) { 119 | for { 120 | if v.b.Len() > 0 { 121 | return v.b.Read(p) 122 | } 123 | 124 | for v.s.Scan() { 125 | if len(v.s.Bytes()) > 0 { 126 | if _, err = v.b.Write(v.s.Bytes()); err != nil { 127 | return 128 | } 129 | break 130 | } 131 | } 132 | 133 | if err = v.s.Err(); err != nil { 134 | return 135 | } 136 | 137 | if v.b.Len() == 0 { 138 | return 0, io.EOF 139 | } 140 | } 141 | 142 | return 143 | } 144 | 145 | // get the first match in flags. 146 | // @return the matched pos in data and the index of flags. 147 | func firstMatch(data []byte, flags [][]byte) (pos, index int) { 148 | pos = -1 149 | index = pos 150 | 151 | for i, flag := range flags { 152 | if position := bytes.Index(data, flag); position >= 0 { 153 | if pos > position || pos == -1 { 154 | pos = position 155 | index = i 156 | } 157 | } 158 | } 159 | 160 | return 161 | } 162 | -------------------------------------------------------------------------------- /kxps/kxps_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package kxps 23 | 24 | import ( 25 | "testing" 26 | "time" 27 | ) 28 | 29 | type mockSource struct { 30 | s uint64 31 | } 32 | 33 | func (v *mockSource) Count() uint64 { 34 | return v.s 35 | } 36 | 37 | func TestKxps_Average(t *testing.T) { 38 | s := &mockSource{} 39 | kxps := newKxps(nil, s) 40 | 41 | if v := kxps.sampleAverage(time.Unix(0, 0)); v != 0 { 42 | t.Errorf("invalid average %v", v) 43 | } 44 | 45 | s.s = 10 46 | if v := kxps.sampleAverage(time.Unix(10, 0)); v != 0 { 47 | t.Errorf("invalid average %v", v) 48 | } 49 | 50 | s.s = 20 51 | if v := kxps.sampleAverage(time.Unix(10, 0)); v != 0 { 52 | t.Errorf("invalid average %v", v) 53 | } else if v := kxps.sampleAverage(time.Unix(20, 0)); v != 10.0/10.0 { 54 | t.Errorf("invalid average %v", v) 55 | } 56 | } 57 | 58 | func TestKxps_Rps10s(t *testing.T) { 59 | s := &mockSource{} 60 | kxps := newKxps(nil, s) 61 | 62 | if err := kxps.doSample(time.Unix(0, 0)); err != nil { 63 | t.Errorf("sample failed, err is %+v", err) 64 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 { 65 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 66 | } 67 | 68 | s.s = 10 69 | if err := kxps.doSample(time.Unix(10, 0)); err != nil { 70 | t.Errorf("sample failed, err is %+v", err) 71 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 { 72 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 73 | } 74 | 75 | s.s = 20 76 | if err := kxps.doSample(time.Unix(20, 0)); err != nil { 77 | t.Errorf("sample failed, err is %+v", err) 78 | } else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 { 79 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 80 | } else if err := kxps.doSample(time.Unix(30, 0)); err != nil { 81 | t.Errorf("sample failed, err is %+v", err) 82 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 { 83 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 84 | } 85 | 86 | s.s = 30 87 | if err := kxps.doSample(time.Unix(40, 0)); err != nil { 88 | t.Errorf("sample failed, err is %+v", err) 89 | } else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 20.0/30.0 || kxps.Xps300s() != 0 { 90 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 91 | } else if err := kxps.doSample(time.Unix(50, 0)); err != nil { 92 | t.Errorf("sample failed, err is %+v", err) 93 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 20.0/30.0 || kxps.Xps300s() != 0 { 94 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 95 | } 96 | 97 | s.s = 40 98 | if err := kxps.doSample(time.Unix(310, 0)); err != nil { 99 | t.Errorf("sample failed, err is %+v", err) 100 | } else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 10.0/30.0 || kxps.Xps300s() != 30.0/300.0 { 101 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 102 | } else if err := kxps.doSample(time.Unix(320, 0)); err != nil { 103 | t.Errorf("sample failed, err is %+v", err) 104 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 10.0/30.0 || kxps.Xps300s() != 30.0/300.0 { 105 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 106 | } else if err := kxps.doSample(time.Unix(340, 0)); err != nil { 107 | t.Errorf("sample failed, err is %+v", err) 108 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 30.0/300.0 { 109 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 110 | } else if err := kxps.doSample(time.Unix(610, 0)); err != nil { 111 | t.Errorf("sample failed, err is %+v", err) 112 | } else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 { 113 | t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s()) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /kxps/kxps.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // The shared objects for kxps. 23 | package kxps 24 | 25 | import ( 26 | "fmt" 27 | ol "github.com/ossrs/go-oryx-lib/logger" 28 | "sync" 29 | "time" 30 | ) 31 | 32 | // The source to stat the requests. 33 | type kxpsSource interface { 34 | // Get total count. 35 | Count() uint64 36 | } 37 | 38 | // sample for krps. 39 | type sample struct { 40 | rps float64 41 | count uint64 42 | create time.Time 43 | lastSample time.Time 44 | // Duration in seconds. 45 | interval time.Duration 46 | } 47 | 48 | func (v *sample) String() string { 49 | return fmt.Sprintf("rps=%v, count=%v, interval=%v", v.rps, v.count, v.interval) 50 | } 51 | 52 | func (v *sample) initialize(now time.Time, nbRequests uint64) { 53 | v.count = nbRequests 54 | v.lastSample = now 55 | v.create = now 56 | } 57 | 58 | func (v *sample) sample(now time.Time, nbRequests uint64) bool { 59 | if v.lastSample.Add(v.interval).After(now) { 60 | return false 61 | } 62 | 63 | diff := int64(nbRequests - v.count) 64 | v.count = nbRequests 65 | v.lastSample = now 66 | if diff <= 0 { 67 | v.rps = 0 68 | return true 69 | } 70 | 71 | interval := int(v.interval / time.Millisecond) 72 | v.rps = float64(diff) * 1000 / float64(interval) 73 | 74 | return true 75 | } 76 | 77 | var kxpsClosed = fmt.Errorf("kxps closed") 78 | 79 | // The implementation object. 80 | type kxps struct { 81 | // internal objects. 82 | source kxpsSource 83 | ctx ol.Context 84 | closed bool 85 | started bool 86 | lock *sync.Mutex 87 | // samples 88 | r10s sample 89 | r30s sample 90 | r300s sample 91 | // for average 92 | average uint64 93 | create time.Time 94 | } 95 | 96 | func newKxps(ctx ol.Context, s kxpsSource) *kxps { 97 | v := &kxps{ 98 | lock: &sync.Mutex{}, 99 | source: s, 100 | ctx: ctx, 101 | } 102 | 103 | v.r10s.interval = time.Duration(10) * time.Second 104 | v.r30s.interval = time.Duration(30) * time.Second 105 | v.r300s.interval = time.Duration(300) * time.Second 106 | 107 | return v 108 | } 109 | 110 | func (v *kxps) Close() (err error) { 111 | v.lock.Lock() 112 | defer v.lock.Unlock() 113 | 114 | v.closed = true 115 | v.started = false 116 | return 117 | } 118 | 119 | func (v *kxps) Xps10s() float64 { 120 | return v.r10s.rps 121 | } 122 | 123 | func (v *kxps) Xps30s() float64 { 124 | return v.r30s.rps 125 | } 126 | 127 | func (v *kxps) Xps300s() float64 { 128 | return v.r300s.rps 129 | } 130 | 131 | func (v *kxps) Average() float64 { 132 | return v.sampleAverage(time.Now()) 133 | } 134 | 135 | func (v *kxps) sampleAverage(now time.Time) float64 { 136 | if v.source.Count() == 0 { 137 | return 0 138 | } 139 | 140 | if v.average == 0 { 141 | v.average = v.source.Count() 142 | v.create = now 143 | return 0 144 | } 145 | 146 | diff := int64(v.source.Count() - v.average) 147 | if diff <= 0 { 148 | return 0 149 | } 150 | 151 | duration := int64(now.Sub(v.create) / time.Millisecond) 152 | if duration <= 0 { 153 | return 0 154 | } 155 | 156 | return float64(diff) * 1000 / float64(duration) 157 | } 158 | 159 | func (v *kxps) doSample(now time.Time) (err error) { 160 | count := v.source.Count() 161 | if count == 0 { 162 | return 163 | } 164 | 165 | if v.r10s.count == 0 { 166 | v.r10s.initialize(now, count) 167 | v.r30s.initialize(now, count) 168 | v.r300s.initialize(now, count) 169 | return 170 | } 171 | 172 | if !v.r10s.sample(now, count) { 173 | return 174 | } 175 | 176 | if !v.r30s.sample(now, count) { 177 | return 178 | } 179 | 180 | if !v.r300s.sample(now, count) { 181 | return 182 | } 183 | 184 | return 185 | } 186 | 187 | func (v *kxps) Start() (err error) { 188 | ctx := v.ctx 189 | 190 | go func() { 191 | for { 192 | if err := v.sample(); err != nil { 193 | if err == kxpsClosed { 194 | return 195 | } 196 | ol.W(ctx, "kxps ignore sample failed, err is", err) 197 | } 198 | time.Sleep(time.Duration(10) * time.Second) 199 | } 200 | }() 201 | 202 | v.started = true 203 | 204 | return 205 | } 206 | 207 | func (v *kxps) sample() (err error) { 208 | ctx := v.ctx 209 | 210 | defer func() { 211 | if r := recover(); r != nil { 212 | ol.W(ctx, "recover kxps from", r) 213 | } 214 | }() 215 | 216 | v.lock.Lock() 217 | defer v.lock.Unlock() 218 | 219 | if v.closed { 220 | return kxpsClosed 221 | } 222 | 223 | return v.doSample(time.Now()) 224 | } 225 | -------------------------------------------------------------------------------- /https/example_test.go: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2013-2017 Oryx(ossrs) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | // the Software, and to permit persons to whom the Software is furnished to do so, 10 | // subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package https_test 23 | 24 | import ( 25 | "crypto/tls" 26 | "fmt" 27 | "github.com/ossrs/go-oryx-lib/https" 28 | "net/http" 29 | ) 30 | 31 | // Requires golang 1.6+, because there's bug in http.Server 32 | // to set the GetCertificate of TLSConfig. 33 | func ExampleLetsencryptManagerHttpAndHttps() { 34 | http.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { 35 | w.Write([]byte("Hello, HTTPS over letsencrypt~")) 36 | }) 37 | 38 | go func() { 39 | if err := http.ListenAndServe(":http", nil); err != nil { 40 | fmt.Println("http serve failed, err is", err) 41 | } 42 | }() 43 | 44 | var err error 45 | var m https.Manager 46 | if m, err = https.NewLetsencryptManager("", []string{"winlin.cn"}, "letsencrypt.cache"); err != nil { 47 | fmt.Println("https failed, err is", err) 48 | return 49 | } 50 | 51 | // @remark only support listen at :https, for the validation use tls, 52 | // https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni 53 | svr := &http.Server{ 54 | Addr: ":https", 55 | TLSConfig: &tls.Config{ 56 | GetCertificate: m.GetCertificate, 57 | }, 58 | } 59 | 60 | if err := svr.ListenAndServeTLS("", ""); err != nil { 61 | fmt.Println("https serve failed, err is", err) 62 | } 63 | } 64 | 65 | // Requires golang 1.6+, because there's bug in http.Server 66 | // to set the GetCertificate of TLSConfig. 67 | func ExampleLetsencryptManagerHttps() { 68 | http.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { 69 | w.Write([]byte("Hello, HTTPS over letsencrypt~")) 70 | }) 71 | 72 | var err error 73 | var m https.Manager 74 | if m, err = https.NewLetsencryptManager("", []string{"winlin.cn"}, "letsencrypt.cache"); err != nil { 75 | fmt.Println("https failed, err is", err) 76 | return 77 | } 78 | 79 | // @remark only support listen at :https, for the validation use tls, 80 | // https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni 81 | svr := &http.Server{ 82 | Addr: ":https", 83 | TLSConfig: &tls.Config{ 84 | GetCertificate: m.GetCertificate, 85 | }, 86 | } 87 | 88 | if err := svr.ListenAndServeTLS("", ""); err != nil { 89 | fmt.Println("https serve failed, err is", err) 90 | } 91 | } 92 | 93 | // Requires golang 1.6+, because there's bug in http.Server 94 | // to set the GetCertificate of TLSConfig. 95 | func ExampleSelfSignHttps() { 96 | http.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { 97 | w.Write([]byte("Hello, HTTPS~")) 98 | }) 99 | 100 | // http://studygolang.com/articles/3175 101 | // openssl genrsa -out server.key 2048 102 | // openssl req -new -x509 -key server.key -out server.crt -days 365 103 | var err error 104 | var m https.Manager 105 | if m, err = https.NewSelfSignManager("server.crt", "server.key"); err != nil { 106 | fmt.Println("https failed, err is", err) 107 | return 108 | } 109 | 110 | svr := &http.Server{ 111 | Addr: ":https", 112 | TLSConfig: &tls.Config{ 113 | GetCertificate: m.GetCertificate, 114 | }, 115 | } 116 | 117 | if err := svr.ListenAndServeTLS("", ""); err != nil { 118 | fmt.Println("serve failed, err is", err) 119 | } 120 | } 121 | 122 | // Requires golang 1.6+, because there's bug in http.Server 123 | // to set the GetCertificate of TLSConfig. 124 | func ExampleSelfSignHttpAndHttps() { 125 | http.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { 126 | w.Write([]byte("Hello, HTTP and HTTPS~")) 127 | }) 128 | 129 | go func() { 130 | if err := http.ListenAndServe(":http", nil); err != nil { 131 | fmt.Println("http serve failed, err is", err) 132 | } 133 | }() 134 | 135 | // http://studygolang.com/articles/3175 136 | // openssl genrsa -out server.key 2048 137 | // openssl req -new -x509 -key server.key -out server.crt -days 365 138 | var err error 139 | var m https.Manager 140 | if m, err = https.NewSelfSignManager("server.crt", "server.key"); err != nil { 141 | fmt.Println("https failed, err is", err) 142 | return 143 | } 144 | 145 | svr := &http.Server{ 146 | Addr: ":https", 147 | TLSConfig: &tls.Config{ 148 | GetCertificate: m.GetCertificate, 149 | }, 150 | } 151 | 152 | if err := svr.ListenAndServeTLS("", ""); err != nil { 153 | fmt.Println("https serve failed, err is", err) 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /errors/stack.go: -------------------------------------------------------------------------------- 1 | // Fork from https://github.com/pkg/errors 2 | package errors 3 | 4 | import ( 5 | "fmt" 6 | "io" 7 | "path" 8 | "runtime" 9 | "strings" 10 | ) 11 | 12 | // Frame represents a program counter inside a stack frame. 13 | type Frame uintptr 14 | 15 | // pc returns the program counter for this frame; 16 | // multiple frames may have the same PC value. 17 | func (f Frame) pc() uintptr { return uintptr(f) - 1 } 18 | 19 | // file returns the full path to the file that contains the 20 | // function for this Frame's pc. 21 | func (f Frame) file() string { 22 | fn := runtime.FuncForPC(f.pc()) 23 | if fn == nil { 24 | return "unknown" 25 | } 26 | file, _ := fn.FileLine(f.pc()) 27 | return file 28 | } 29 | 30 | // line returns the line number of source code of the 31 | // function for this Frame's pc. 32 | func (f Frame) line() int { 33 | fn := runtime.FuncForPC(f.pc()) 34 | if fn == nil { 35 | return 0 36 | } 37 | _, line := fn.FileLine(f.pc()) 38 | return line 39 | } 40 | 41 | // Format formats the frame according to the fmt.Formatter interface. 42 | // 43 | // %s source file 44 | // %d source line 45 | // %n function name 46 | // %v equivalent to %s:%d 47 | // 48 | // Format accepts flags that alter the printing of some verbs, as follows: 49 | // 50 | // %+s path of source file relative to the compile time GOPATH 51 | // %+v equivalent to %+s:%d 52 | func (f Frame) Format(s fmt.State, verb rune) { 53 | switch verb { 54 | case 's': 55 | switch { 56 | case s.Flag('+'): 57 | pc := f.pc() 58 | fn := runtime.FuncForPC(pc) 59 | if fn == nil { 60 | io.WriteString(s, "unknown") 61 | } else { 62 | file, _ := fn.FileLine(pc) 63 | fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) 64 | } 65 | default: 66 | io.WriteString(s, path.Base(f.file())) 67 | } 68 | case 'd': 69 | fmt.Fprintf(s, "%d", f.line()) 70 | case 'n': 71 | name := runtime.FuncForPC(f.pc()).Name() 72 | io.WriteString(s, funcname(name)) 73 | case 'v': 74 | f.Format(s, 's') 75 | io.WriteString(s, ":") 76 | f.Format(s, 'd') 77 | } 78 | } 79 | 80 | // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). 81 | type StackTrace []Frame 82 | 83 | // Format formats the stack of Frames according to the fmt.Formatter interface. 84 | // 85 | // %s lists source files for each Frame in the stack 86 | // %v lists the source file and line number for each Frame in the stack 87 | // 88 | // Format accepts flags that alter the printing of some verbs, as follows: 89 | // 90 | // %+v Prints filename, function, and line number for each Frame in the stack. 91 | func (st StackTrace) Format(s fmt.State, verb rune) { 92 | switch verb { 93 | case 'v': 94 | switch { 95 | case s.Flag('+'): 96 | for _, f := range st { 97 | fmt.Fprintf(s, "\n%+v", f) 98 | } 99 | case s.Flag('#'): 100 | fmt.Fprintf(s, "%#v", []Frame(st)) 101 | default: 102 | fmt.Fprintf(s, "%v", []Frame(st)) 103 | } 104 | case 's': 105 | fmt.Fprintf(s, "%s", []Frame(st)) 106 | } 107 | } 108 | 109 | // stack represents a stack of program counters. 110 | type stack []uintptr 111 | 112 | func (s *stack) Format(st fmt.State, verb rune) { 113 | switch verb { 114 | case 'v': 115 | switch { 116 | case st.Flag('+'): 117 | for _, pc := range *s { 118 | f := Frame(pc) 119 | fmt.Fprintf(st, "\n%+v", f) 120 | } 121 | } 122 | } 123 | } 124 | 125 | func (s *stack) StackTrace() StackTrace { 126 | f := make([]Frame, len(*s)) 127 | for i := 0; i < len(f); i++ { 128 | f[i] = Frame((*s)[i]) 129 | } 130 | return f 131 | } 132 | 133 | func callers() *stack { 134 | const depth = 32 135 | var pcs [depth]uintptr 136 | n := runtime.Callers(3, pcs[:]) 137 | var st stack = pcs[0:n] 138 | return &st 139 | } 140 | 141 | // funcname removes the path prefix component of a function's name reported by func.Name(). 142 | func funcname(name string) string { 143 | i := strings.LastIndex(name, "/") 144 | name = name[i+1:] 145 | i = strings.Index(name, ".") 146 | return name[i+1:] 147 | } 148 | 149 | func trimGOPATH(name, file string) string { 150 | // Here we want to get the source file path relative to the compile time 151 | // GOPATH. As of Go 1.6.x there is no direct way to know the compiled 152 | // GOPATH at runtime, but we can infer the number of path segments in the 153 | // GOPATH. We note that fn.Name() returns the function name qualified by 154 | // the import path, which does not include the GOPATH. Thus we can trim 155 | // segments from the beginning of the file path until the number of path 156 | // separators remaining is one more than the number of path separators in 157 | // the function name. For example, given: 158 | // 159 | // GOPATH /home/user 160 | // file /home/user/src/pkg/sub/file.go 161 | // fn.Name() pkg/sub.Type.Method 162 | // 163 | // We want to produce: 164 | // 165 | // pkg/sub/file.go 166 | // 167 | // From this we can easily see that fn.Name() has one less path separator 168 | // than our desired output. We count separators from the end of the file 169 | // path until it finds two more than in the function name and then move 170 | // one character forward to preserve the initial path segment without a 171 | // leading separator. 172 | const sep = "/" 173 | goal := strings.Count(name, sep) + 2 174 | i := len(file) 175 | for n := 0; n < goal; n++ { 176 | i = strings.LastIndex(file[:i], sep) 177 | if i == -1 { 178 | // not enough separators found, set i so that the slice expression 179 | // below leaves file unmodified 180 | i = -len(sep) 181 | break 182 | } 183 | } 184 | // get back to 0 or trim the leading separator 185 | file = file[i+len(sep):] 186 | return file 187 | } 188 | -------------------------------------------------------------------------------- /https/jose/encoding.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1 18 | package jose 19 | 20 | import ( 21 | "bytes" 22 | "compress/flate" 23 | "encoding/base64" 24 | "encoding/binary" 25 | "io" 26 | "math/big" 27 | "regexp" 28 | "strings" 29 | 30 | "encoding/json" 31 | ) 32 | 33 | var stripWhitespaceRegex = regexp.MustCompile("\\s") 34 | 35 | // Url-safe base64 encode that strips padding 36 | func base64URLEncode(data []byte) string { 37 | var result = base64.URLEncoding.EncodeToString(data) 38 | return strings.TrimRight(result, "=") 39 | } 40 | 41 | // Url-safe base64 decoder that adds padding 42 | func base64URLDecode(data string) ([]byte, error) { 43 | var missing = (4 - len(data)%4) % 4 44 | data += strings.Repeat("=", missing) 45 | return base64.URLEncoding.DecodeString(data) 46 | } 47 | 48 | // Helper function to serialize known-good objects. 49 | // Precondition: value is not a nil pointer. 50 | func mustSerializeJSON(value interface{}) []byte { 51 | out, err := json.Marshal(value) 52 | if err != nil { 53 | panic(err) 54 | } 55 | // We never want to serialize the top-level value "null," since it's not a 56 | // valid JOSE message. But if a caller passes in a nil pointer to this method, 57 | // MarshalJSON will happily serialize it as the top-level value "null". If 58 | // that value is then embedded in another operation, for instance by being 59 | // base64-encoded and fed as input to a signing algorithm 60 | // (https://github.com/square/go-jose/issues/22), the result will be 61 | // incorrect. Because this method is intended for known-good objects, and a nil 62 | // pointer is not a known-good object, we are free to panic in this case. 63 | // Note: It's not possible to directly check whether the data pointed at by an 64 | // interface is a nil pointer, so we do this hacky workaround. 65 | // https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I 66 | if string(out) == "null" { 67 | panic("Tried to serialize a nil pointer.") 68 | } 69 | return out 70 | } 71 | 72 | // Strip all newlines and whitespace 73 | func stripWhitespace(data string) string { 74 | return stripWhitespaceRegex.ReplaceAllString(data, "") 75 | } 76 | 77 | // Perform compression based on algorithm 78 | func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { 79 | switch algorithm { 80 | case DEFLATE: 81 | return deflate(input) 82 | default: 83 | return nil, ErrUnsupportedAlgorithm 84 | } 85 | } 86 | 87 | // Perform decompression based on algorithm 88 | func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { 89 | switch algorithm { 90 | case DEFLATE: 91 | return inflate(input) 92 | default: 93 | return nil, ErrUnsupportedAlgorithm 94 | } 95 | } 96 | 97 | // Compress with DEFLATE 98 | func deflate(input []byte) ([]byte, error) { 99 | output := new(bytes.Buffer) 100 | 101 | // Writing to byte buffer, err is always nil 102 | writer, _ := flate.NewWriter(output, 1) 103 | _, _ = io.Copy(writer, bytes.NewBuffer(input)) 104 | 105 | err := writer.Close() 106 | return output.Bytes(), err 107 | } 108 | 109 | // Decompress with DEFLATE 110 | func inflate(input []byte) ([]byte, error) { 111 | output := new(bytes.Buffer) 112 | reader := flate.NewReader(bytes.NewBuffer(input)) 113 | 114 | _, err := io.Copy(output, reader) 115 | if err != nil { 116 | return nil, err 117 | } 118 | 119 | err = reader.Close() 120 | return output.Bytes(), err 121 | } 122 | 123 | // byteBuffer represents a slice of bytes that can be serialized to url-safe base64. 124 | type byteBuffer struct { 125 | data []byte 126 | } 127 | 128 | func newBuffer(data []byte) *byteBuffer { 129 | if data == nil { 130 | return nil 131 | } 132 | return &byteBuffer{ 133 | data: data, 134 | } 135 | } 136 | 137 | func newFixedSizeBuffer(data []byte, length int) *byteBuffer { 138 | if len(data) > length { 139 | panic("square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") 140 | } 141 | pad := make([]byte, length-len(data)) 142 | return newBuffer(append(pad, data...)) 143 | } 144 | 145 | func newBufferFromInt(num uint64) *byteBuffer { 146 | data := make([]byte, 8) 147 | binary.BigEndian.PutUint64(data, num) 148 | return newBuffer(bytes.TrimLeft(data, "\x00")) 149 | } 150 | 151 | func (b *byteBuffer) MarshalJSON() ([]byte, error) { 152 | return json.Marshal(b.base64()) 153 | } 154 | 155 | func (b *byteBuffer) UnmarshalJSON(data []byte) error { 156 | var encoded string 157 | err := json.Unmarshal(data, &encoded) 158 | if err != nil { 159 | return err 160 | } 161 | 162 | if encoded == "" { 163 | return nil 164 | } 165 | 166 | decoded, err := base64URLDecode(encoded) 167 | if err != nil { 168 | return err 169 | } 170 | 171 | *b = *newBuffer(decoded) 172 | 173 | return nil 174 | } 175 | 176 | func (b *byteBuffer) base64() string { 177 | return base64URLEncode(b.data) 178 | } 179 | 180 | func (b *byteBuffer) bytes() []byte { 181 | // Handling nil here allows us to transparently handle nil slices when serializing. 182 | if b == nil { 183 | return nil 184 | } 185 | return b.data 186 | } 187 | 188 | func (b byteBuffer) bigInt() *big.Int { 189 | return new(big.Int).SetBytes(b.data) 190 | } 191 | 192 | func (b byteBuffer) toInt() int { 193 | return int(b.bigInt().Int64()) 194 | } 195 | -------------------------------------------------------------------------------- /websocket/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fork from https://github.com/gorilla/websocket 6 | package websocket 7 | 8 | import ( 9 | "crypto/rand" 10 | "crypto/sha1" 11 | "encoding/base64" 12 | "io" 13 | "net/http" 14 | "strings" 15 | ) 16 | 17 | var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") 18 | 19 | func computeAcceptKey(challengeKey string) string { 20 | h := sha1.New() 21 | h.Write([]byte(challengeKey)) 22 | h.Write(keyGUID) 23 | return base64.StdEncoding.EncodeToString(h.Sum(nil)) 24 | } 25 | 26 | func generateChallengeKey() (string, error) { 27 | p := make([]byte, 16) 28 | if _, err := io.ReadFull(rand.Reader, p); err != nil { 29 | return "", err 30 | } 31 | return base64.StdEncoding.EncodeToString(p), nil 32 | } 33 | 34 | // Octet types from RFC 2616. 35 | var octetTypes [256]byte 36 | 37 | const ( 38 | isTokenOctet = 1 << iota 39 | isSpaceOctet 40 | ) 41 | 42 | func init() { 43 | // From RFC 2616 44 | // 45 | // OCTET = 46 | // CHAR = 47 | // CTL = 48 | // CR = 49 | // LF = 50 | // SP = 51 | // HT = 52 | // <"> = 53 | // CRLF = CR LF 54 | // LWS = [CRLF] 1*( SP | HT ) 55 | // TEXT = 56 | // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> 57 | // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT 58 | // token = 1* 59 | // qdtext = > 60 | 61 | for c := 0; c < 256; c++ { 62 | var t byte 63 | isCtl := c <= 31 || c == 127 64 | isChar := 0 <= c && c <= 127 65 | isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 66 | if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { 67 | t |= isSpaceOctet 68 | } 69 | if isChar && !isCtl && !isSeparator { 70 | t |= isTokenOctet 71 | } 72 | octetTypes[c] = t 73 | } 74 | } 75 | 76 | func skipSpace(s string) (rest string) { 77 | i := 0 78 | for ; i < len(s); i++ { 79 | if octetTypes[s[i]]&isSpaceOctet == 0 { 80 | break 81 | } 82 | } 83 | return s[i:] 84 | } 85 | 86 | func nextToken(s string) (token, rest string) { 87 | i := 0 88 | for ; i < len(s); i++ { 89 | if octetTypes[s[i]]&isTokenOctet == 0 { 90 | break 91 | } 92 | } 93 | return s[:i], s[i:] 94 | } 95 | 96 | func nextTokenOrQuoted(s string) (value string, rest string) { 97 | if !strings.HasPrefix(s, "\"") { 98 | return nextToken(s) 99 | } 100 | s = s[1:] 101 | for i := 0; i < len(s); i++ { 102 | switch s[i] { 103 | case '"': 104 | return s[:i], s[i+1:] 105 | case '\\': 106 | p := make([]byte, len(s)-1) 107 | j := copy(p, s[:i]) 108 | escape := true 109 | for i = i + 1; i < len(s); i++ { 110 | b := s[i] 111 | switch { 112 | case escape: 113 | escape = false 114 | p[j] = b 115 | j++ 116 | case b == '\\': 117 | escape = true 118 | case b == '"': 119 | return string(p[:j]), s[i+1:] 120 | default: 121 | p[j] = b 122 | j++ 123 | } 124 | } 125 | return "", "" 126 | } 127 | } 128 | return "", "" 129 | } 130 | 131 | // tokenListContainsValue returns true if the 1#token header with the given 132 | // name contains token. 133 | func tokenListContainsValue(header http.Header, name string, value string) bool { 134 | headers: 135 | for _, s := range header[name] { 136 | for { 137 | var t string 138 | t, s = nextToken(skipSpace(s)) 139 | if t == "" { 140 | continue headers 141 | } 142 | s = skipSpace(s) 143 | if s != "" && s[0] != ',' { 144 | continue headers 145 | } 146 | if strings.EqualFold(t, value) { 147 | return true 148 | } 149 | if s == "" { 150 | continue headers 151 | } 152 | s = s[1:] 153 | } 154 | } 155 | return false 156 | } 157 | 158 | // parseExtensiosn parses WebSocket extensions from a header. 159 | func parseExtensions(header http.Header) []map[string]string { 160 | 161 | // From RFC 6455: 162 | // 163 | // Sec-WebSocket-Extensions = extension-list 164 | // extension-list = 1#extension 165 | // extension = extension-token *( ";" extension-param ) 166 | // extension-token = registered-token 167 | // registered-token = token 168 | // extension-param = token [ "=" (token | quoted-string) ] 169 | // ;When using the quoted-string syntax variant, the value 170 | // ;after quoted-string unescaping MUST conform to the 171 | // ;'token' ABNF. 172 | 173 | var result []map[string]string 174 | headers: 175 | for _, s := range header["Sec-Websocket-Extensions"] { 176 | for { 177 | var t string 178 | t, s = nextToken(skipSpace(s)) 179 | if t == "" { 180 | continue headers 181 | } 182 | ext := map[string]string{"": t} 183 | for { 184 | s = skipSpace(s) 185 | if !strings.HasPrefix(s, ";") { 186 | break 187 | } 188 | var k string 189 | k, s = nextToken(skipSpace(s[1:])) 190 | if k == "" { 191 | continue headers 192 | } 193 | s = skipSpace(s) 194 | var v string 195 | if strings.HasPrefix(s, "=") { 196 | v, s = nextTokenOrQuoted(skipSpace(s[1:])) 197 | s = skipSpace(s) 198 | } 199 | if s != "" && s[0] != ',' && s[0] != ';' { 200 | continue headers 201 | } 202 | ext[k] = v 203 | } 204 | if s != "" && s[0] != ',' { 205 | continue headers 206 | } 207 | result = append(result, ext) 208 | if s == "" { 209 | continue headers 210 | } 211 | s = s[1:] 212 | } 213 | } 214 | return result 215 | } 216 | -------------------------------------------------------------------------------- /https/jose/cipher/cbc_hmac.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1/cipher 18 | package josecipher 19 | 20 | import ( 21 | "bytes" 22 | "crypto/cipher" 23 | "crypto/hmac" 24 | "crypto/sha256" 25 | "crypto/sha512" 26 | "crypto/subtle" 27 | "encoding/binary" 28 | "errors" 29 | "hash" 30 | ) 31 | 32 | const ( 33 | nonceBytes = 16 34 | ) 35 | 36 | // NewCBCHMAC instantiates a new AEAD based on CBC+HMAC. 37 | func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) { 38 | keySize := len(key) / 2 39 | integrityKey := key[:keySize] 40 | encryptionKey := key[keySize:] 41 | 42 | blockCipher, err := newBlockCipher(encryptionKey) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | var hash func() hash.Hash 48 | switch keySize { 49 | case 16: 50 | hash = sha256.New 51 | case 24: 52 | hash = sha512.New384 53 | case 32: 54 | hash = sha512.New 55 | } 56 | 57 | return &cbcAEAD{ 58 | hash: hash, 59 | blockCipher: blockCipher, 60 | authtagBytes: keySize, 61 | integrityKey: integrityKey, 62 | }, nil 63 | } 64 | 65 | // An AEAD based on CBC+HMAC 66 | type cbcAEAD struct { 67 | hash func() hash.Hash 68 | authtagBytes int 69 | integrityKey []byte 70 | blockCipher cipher.Block 71 | } 72 | 73 | func (ctx *cbcAEAD) NonceSize() int { 74 | return nonceBytes 75 | } 76 | 77 | func (ctx *cbcAEAD) Overhead() int { 78 | // Maximum overhead is block size (for padding) plus auth tag length, where 79 | // the length of the auth tag is equivalent to the key size. 80 | return ctx.blockCipher.BlockSize() + ctx.authtagBytes 81 | } 82 | 83 | // Seal encrypts and authenticates the plaintext. 84 | func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { 85 | // Output buffer -- must take care not to mangle plaintext input. 86 | ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)] 87 | copy(ciphertext, plaintext) 88 | ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize()) 89 | 90 | cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce) 91 | 92 | cbc.CryptBlocks(ciphertext, ciphertext) 93 | authtag := ctx.computeAuthTag(data, nonce, ciphertext) 94 | 95 | ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag))) 96 | copy(out, ciphertext) 97 | copy(out[len(ciphertext):], authtag) 98 | 99 | return ret 100 | } 101 | 102 | // Open decrypts and authenticates the ciphertext. 103 | func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { 104 | if len(ciphertext) < ctx.authtagBytes { 105 | return nil, errors.New("square/go-jose: invalid ciphertext (too short)") 106 | } 107 | 108 | offset := len(ciphertext) - ctx.authtagBytes 109 | expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) 110 | match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) 111 | if match != 1 { 112 | return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)") 113 | } 114 | 115 | cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) 116 | 117 | // Make copy of ciphertext buffer, don't want to modify in place 118 | buffer := append([]byte{}, []byte(ciphertext[:offset])...) 119 | 120 | if len(buffer)%ctx.blockCipher.BlockSize() > 0 { 121 | return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)") 122 | } 123 | 124 | cbc.CryptBlocks(buffer, buffer) 125 | 126 | // Remove padding 127 | plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize()) 128 | if err != nil { 129 | return nil, err 130 | } 131 | 132 | ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext))) 133 | copy(out, plaintext) 134 | 135 | return ret, nil 136 | } 137 | 138 | // Compute an authentication tag 139 | func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte { 140 | buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8) 141 | n := 0 142 | n += copy(buffer, aad) 143 | n += copy(buffer[n:], nonce) 144 | n += copy(buffer[n:], ciphertext) 145 | binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8) 146 | 147 | // According to documentation, Write() on hash.Hash never fails. 148 | hmac := hmac.New(ctx.hash, ctx.integrityKey) 149 | _, _ = hmac.Write(buffer) 150 | 151 | return hmac.Sum(nil)[:ctx.authtagBytes] 152 | } 153 | 154 | // resize ensures the the given slice has a capacity of at least n bytes. 155 | // If the capacity of the slice is less than n, a new slice is allocated 156 | // and the existing data will be copied. 157 | func resize(in []byte, n uint64) (head, tail []byte) { 158 | if uint64(cap(in)) >= n { 159 | head = in[:n] 160 | } else { 161 | head = make([]byte, n) 162 | copy(head, in) 163 | } 164 | 165 | tail = head[len(in):] 166 | return 167 | } 168 | 169 | // Apply padding 170 | func padBuffer(buffer []byte, blockSize int) []byte { 171 | missing := blockSize - (len(buffer) % blockSize) 172 | ret, out := resize(buffer, uint64(len(buffer))+uint64(missing)) 173 | padding := bytes.Repeat([]byte{byte(missing)}, missing) 174 | copy(out, padding) 175 | return ret 176 | } 177 | 178 | // Remove padding 179 | func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) { 180 | if len(buffer)%blockSize != 0 { 181 | return nil, errors.New("square/go-jose: invalid padding") 182 | } 183 | 184 | last := buffer[len(buffer)-1] 185 | count := int(last) 186 | 187 | if count == 0 || count > blockSize || count > len(buffer) { 188 | return nil, errors.New("square/go-jose: invalid padding") 189 | } 190 | 191 | padding := bytes.Repeat([]byte{last}, count) 192 | if !bytes.HasSuffix(buffer, padding) { 193 | return nil, errors.New("square/go-jose: invalid padding") 194 | } 195 | 196 | return buffer[:len(buffer)-count], nil 197 | } 198 | -------------------------------------------------------------------------------- /errors/example_test.go: -------------------------------------------------------------------------------- 1 | // Fork from https://github.com/pkg/errors 2 | package errors_test 3 | 4 | import ( 5 | "fmt" 6 | 7 | "github.com/ossrs/go-oryx-lib/errors" 8 | ) 9 | 10 | func ExampleNew() { 11 | err := errors.New("whoops") 12 | fmt.Println(err) 13 | 14 | // Output: whoops 15 | } 16 | 17 | func ExampleNew_printf() { 18 | err := errors.New("whoops") 19 | fmt.Printf("%+v", err) 20 | 21 | // Example output: 22 | // whoops 23 | // github.com/pkg/errors_test.ExampleNew_printf 24 | // /home/dfc/src/github.com/pkg/errors/example_test.go:17 25 | // testing.runExample 26 | // /home/dfc/go/src/testing/example.go:114 27 | // testing.RunExamples 28 | // /home/dfc/go/src/testing/example.go:38 29 | // testing.(*M).Run 30 | // /home/dfc/go/src/testing/testing.go:744 31 | // main.main 32 | // /github.com/pkg/errors/_test/_testmain.go:106 33 | // runtime.main 34 | // /home/dfc/go/src/runtime/proc.go:183 35 | // runtime.goexit 36 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 37 | } 38 | 39 | func ExampleWithMessage() { 40 | cause := errors.New("whoops") 41 | err := errors.WithMessage(cause, "oh noes") 42 | fmt.Println(err) 43 | 44 | // Output: oh noes: whoops 45 | } 46 | 47 | func ExampleWithStack() { 48 | cause := errors.New("whoops") 49 | err := errors.WithStack(cause) 50 | fmt.Println(err) 51 | 52 | // Output: whoops 53 | } 54 | 55 | func ExampleWithStack_printf() { 56 | cause := errors.New("whoops") 57 | err := errors.WithStack(cause) 58 | fmt.Printf("%+v", err) 59 | 60 | // Example Output: 61 | // whoops 62 | // github.com/pkg/errors_test.ExampleWithStack_printf 63 | // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55 64 | // testing.runExample 65 | // /usr/lib/go/src/testing/example.go:114 66 | // testing.RunExamples 67 | // /usr/lib/go/src/testing/example.go:38 68 | // testing.(*M).Run 69 | // /usr/lib/go/src/testing/testing.go:744 70 | // main.main 71 | // github.com/pkg/errors/_test/_testmain.go:106 72 | // runtime.main 73 | // /usr/lib/go/src/runtime/proc.go:183 74 | // runtime.goexit 75 | // /usr/lib/go/src/runtime/asm_amd64.s:2086 76 | // github.com/pkg/errors_test.ExampleWithStack_printf 77 | // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56 78 | // testing.runExample 79 | // /usr/lib/go/src/testing/example.go:114 80 | // testing.RunExamples 81 | // /usr/lib/go/src/testing/example.go:38 82 | // testing.(*M).Run 83 | // /usr/lib/go/src/testing/testing.go:744 84 | // main.main 85 | // github.com/pkg/errors/_test/_testmain.go:106 86 | // runtime.main 87 | // /usr/lib/go/src/runtime/proc.go:183 88 | // runtime.goexit 89 | // /usr/lib/go/src/runtime/asm_amd64.s:2086 90 | } 91 | 92 | func ExampleWrap() { 93 | cause := errors.New("whoops") 94 | err := errors.Wrap(cause, "oh noes") 95 | fmt.Println(err) 96 | 97 | // Output: oh noes: whoops 98 | } 99 | 100 | func fn() error { 101 | e1 := errors.New("error") 102 | e2 := errors.Wrap(e1, "inner") 103 | e3 := errors.Wrap(e2, "middle") 104 | return errors.Wrap(e3, "outer") 105 | } 106 | 107 | func ExampleCause() { 108 | err := fn() 109 | fmt.Println(err) 110 | fmt.Println(errors.Cause(err)) 111 | 112 | // Output: outer: middle: inner: error 113 | // error 114 | } 115 | 116 | func ExampleWrap_extended() { 117 | err := fn() 118 | fmt.Printf("%+v\n", err) 119 | 120 | // Example output: 121 | // error 122 | // github.com/pkg/errors_test.fn 123 | // /home/dfc/src/github.com/pkg/errors/example_test.go:47 124 | // github.com/pkg/errors_test.ExampleCause_printf 125 | // /home/dfc/src/github.com/pkg/errors/example_test.go:63 126 | // testing.runExample 127 | // /home/dfc/go/src/testing/example.go:114 128 | // testing.RunExamples 129 | // /home/dfc/go/src/testing/example.go:38 130 | // testing.(*M).Run 131 | // /home/dfc/go/src/testing/testing.go:744 132 | // main.main 133 | // /github.com/pkg/errors/_test/_testmain.go:104 134 | // runtime.main 135 | // /home/dfc/go/src/runtime/proc.go:183 136 | // runtime.goexit 137 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 138 | // github.com/pkg/errors_test.fn 139 | // /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner 140 | // github.com/pkg/errors_test.fn 141 | // /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle 142 | // github.com/pkg/errors_test.fn 143 | // /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer 144 | } 145 | 146 | func ExampleWrapf() { 147 | cause := errors.New("whoops") 148 | err := errors.Wrapf(cause, "oh noes #%d", 2) 149 | fmt.Println(err) 150 | 151 | // Output: oh noes #2: whoops 152 | } 153 | 154 | func ExampleErrorf_extended() { 155 | err := errors.Errorf("whoops: %s", "foo") 156 | fmt.Printf("%+v", err) 157 | 158 | // Example output: 159 | // whoops: foo 160 | // github.com/pkg/errors_test.ExampleErrorf 161 | // /home/dfc/src/github.com/pkg/errors/example_test.go:101 162 | // testing.runExample 163 | // /home/dfc/go/src/testing/example.go:114 164 | // testing.RunExamples 165 | // /home/dfc/go/src/testing/example.go:38 166 | // testing.(*M).Run 167 | // /home/dfc/go/src/testing/testing.go:744 168 | // main.main 169 | // /github.com/pkg/errors/_test/_testmain.go:102 170 | // runtime.main 171 | // /home/dfc/go/src/runtime/proc.go:183 172 | // runtime.goexit 173 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 174 | } 175 | 176 | func Example_stackTrace() { 177 | type stackTracer interface { 178 | StackTrace() errors.StackTrace 179 | } 180 | 181 | err, ok := errors.Cause(fn()).(stackTracer) 182 | if !ok { 183 | panic("oops, err does not implement stackTracer") 184 | } 185 | 186 | st := err.StackTrace() 187 | fmt.Printf("%+v", st[0:2]) // top two frames 188 | 189 | // Example output: 190 | // github.com/pkg/errors_test.fn 191 | // /home/dfc/src/github.com/pkg/errors/example_test.go:47 192 | // github.com/pkg/errors_test.Example_stackTrace 193 | // /home/dfc/src/github.com/pkg/errors/example_test.go:127 194 | } 195 | 196 | func ExampleCause_printf() { 197 | err := errors.Wrap(func() error { 198 | return func() error { 199 | return errors.Errorf("hello %s", fmt.Sprintf("world")) 200 | }() 201 | }(), "failed") 202 | 203 | fmt.Printf("%v", err) 204 | 205 | // Output: failed: hello world 206 | } 207 | -------------------------------------------------------------------------------- /https/jose/signing.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // from gopkg.in/square/go-jose.v1 18 | package jose 19 | 20 | import ( 21 | "crypto/ecdsa" 22 | "crypto/rsa" 23 | "fmt" 24 | ) 25 | 26 | // NonceSource represents a source of random nonces to go into JWS objects 27 | type NonceSource interface { 28 | Nonce() (string, error) 29 | } 30 | 31 | // Signer represents a signer which takes a payload and produces a signed JWS object. 32 | type Signer interface { 33 | Sign(payload []byte) (*JsonWebSignature, error) 34 | SetNonceSource(source NonceSource) 35 | SetEmbedJwk(embed bool) 36 | } 37 | 38 | // MultiSigner represents a signer which supports multiple recipients. 39 | type MultiSigner interface { 40 | Sign(payload []byte) (*JsonWebSignature, error) 41 | SetNonceSource(source NonceSource) 42 | SetEmbedJwk(embed bool) 43 | AddRecipient(alg SignatureAlgorithm, signingKey interface{}) error 44 | } 45 | 46 | type payloadSigner interface { 47 | signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) 48 | } 49 | 50 | type payloadVerifier interface { 51 | verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error 52 | } 53 | 54 | type genericSigner struct { 55 | recipients []recipientSigInfo 56 | nonceSource NonceSource 57 | embedJwk bool 58 | } 59 | 60 | type recipientSigInfo struct { 61 | sigAlg SignatureAlgorithm 62 | keyID string 63 | publicKey *JsonWebKey 64 | signer payloadSigner 65 | } 66 | 67 | // NewSigner creates an appropriate signer based on the key type 68 | func NewSigner(alg SignatureAlgorithm, signingKey interface{}) (Signer, error) { 69 | // NewMultiSigner never fails (currently) 70 | signer := NewMultiSigner() 71 | 72 | err := signer.AddRecipient(alg, signingKey) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | return signer, nil 78 | } 79 | 80 | // NewMultiSigner creates a signer for multiple recipients 81 | func NewMultiSigner() MultiSigner { 82 | return &genericSigner{ 83 | recipients: []recipientSigInfo{}, 84 | embedJwk: true, 85 | } 86 | } 87 | 88 | // newVerifier creates a verifier based on the key type 89 | func newVerifier(verificationKey interface{}) (payloadVerifier, error) { 90 | switch verificationKey := verificationKey.(type) { 91 | case *rsa.PublicKey: 92 | return &rsaEncrypterVerifier{ 93 | publicKey: verificationKey, 94 | }, nil 95 | case *ecdsa.PublicKey: 96 | return &ecEncrypterVerifier{ 97 | publicKey: verificationKey, 98 | }, nil 99 | case []byte: 100 | return &symmetricMac{ 101 | key: verificationKey, 102 | }, nil 103 | case *JsonWebKey: 104 | return newVerifier(verificationKey.Key) 105 | default: 106 | return nil, ErrUnsupportedKeyType 107 | } 108 | } 109 | 110 | func (ctx *genericSigner) AddRecipient(alg SignatureAlgorithm, signingKey interface{}) error { 111 | recipient, err := makeJWSRecipient(alg, signingKey) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | ctx.recipients = append(ctx.recipients, recipient) 117 | return nil 118 | } 119 | 120 | func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) { 121 | switch signingKey := signingKey.(type) { 122 | case *rsa.PrivateKey: 123 | return newRSASigner(alg, signingKey) 124 | case *ecdsa.PrivateKey: 125 | return newECDSASigner(alg, signingKey) 126 | case []byte: 127 | return newSymmetricSigner(alg, signingKey) 128 | case *JsonWebKey: 129 | recipient, err := makeJWSRecipient(alg, signingKey.Key) 130 | if err != nil { 131 | return recipientSigInfo{}, err 132 | } 133 | recipient.keyID = signingKey.KeyID 134 | return recipient, nil 135 | default: 136 | return recipientSigInfo{}, ErrUnsupportedKeyType 137 | } 138 | } 139 | 140 | func (ctx *genericSigner) Sign(payload []byte) (*JsonWebSignature, error) { 141 | obj := &JsonWebSignature{} 142 | obj.payload = payload 143 | obj.Signatures = make([]Signature, len(ctx.recipients)) 144 | 145 | for i, recipient := range ctx.recipients { 146 | protected := &rawHeader{ 147 | Alg: string(recipient.sigAlg), 148 | } 149 | 150 | if recipient.publicKey != nil && ctx.embedJwk { 151 | protected.Jwk = recipient.publicKey 152 | } 153 | if recipient.keyID != "" { 154 | protected.Kid = recipient.keyID 155 | } 156 | 157 | if ctx.nonceSource != nil { 158 | nonce, err := ctx.nonceSource.Nonce() 159 | if err != nil { 160 | return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err) 161 | } 162 | protected.Nonce = nonce 163 | } 164 | 165 | serializedProtected := mustSerializeJSON(protected) 166 | 167 | input := []byte(fmt.Sprintf("%s.%s", 168 | base64URLEncode(serializedProtected), 169 | base64URLEncode(payload))) 170 | 171 | signatureInfo, err := recipient.signer.signPayload(input, recipient.sigAlg) 172 | if err != nil { 173 | return nil, err 174 | } 175 | 176 | signatureInfo.protected = protected 177 | obj.Signatures[i] = signatureInfo 178 | } 179 | 180 | return obj, nil 181 | } 182 | 183 | // SetNonceSource provides or updates a nonce pool to the first recipients. 184 | // After this method is called, the signer will consume one nonce per 185 | // signature, returning an error it is unable to get a nonce. 186 | func (ctx *genericSigner) SetNonceSource(source NonceSource) { 187 | ctx.nonceSource = source 188 | } 189 | 190 | // SetEmbedJwk specifies if the signing key should be embedded in the protected header, 191 | // if any. It defaults to 'true'. 192 | func (ctx *genericSigner) SetEmbedJwk(embed bool) { 193 | ctx.embedJwk = embed 194 | } 195 | 196 | // Verify validates the signature on the object and returns the payload. 197 | func (obj JsonWebSignature) Verify(verificationKey interface{}) ([]byte, error) { 198 | verifier, err := newVerifier(verificationKey) 199 | if err != nil { 200 | return nil, err 201 | } 202 | 203 | for _, signature := range obj.Signatures { 204 | headers := signature.mergedHeaders() 205 | if len(headers.Crit) > 0 { 206 | // Unsupported crit header 207 | continue 208 | } 209 | 210 | input := obj.computeAuthData(&signature) 211 | alg := SignatureAlgorithm(headers.Alg) 212 | err := verifier.verifyPayload(input, signature.Signature, alg) 213 | if err == nil { 214 | return obj.payload, nil 215 | } 216 | } 217 | 218 | return nil, ErrCryptoFailure 219 | } 220 | -------------------------------------------------------------------------------- /https/net/context/context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package context defines the Context type, which carries deadlines, 6 | // cancelation signals, and other request-scoped values across API boundaries 7 | // and between processes. 8 | // 9 | // Incoming requests to a server should create a Context, and outgoing calls to 10 | // servers should accept a Context. The chain of function calls between must 11 | // propagate the Context, optionally replacing it with a modified copy created 12 | // using WithDeadline, WithTimeout, WithCancel, or WithValue. 13 | // 14 | // Programs that use Contexts should follow these rules to keep interfaces 15 | // consistent across packages and enable static analysis tools to check context 16 | // propagation: 17 | // 18 | // Do not store Contexts inside a struct type; instead, pass a Context 19 | // explicitly to each function that needs it. The Context should be the first 20 | // parameter, typically named ctx: 21 | // 22 | // func DoSomething(ctx context.Context, arg Arg) error { 23 | // // ... use ctx ... 24 | // } 25 | // 26 | // Do not pass a nil Context, even if a function permits it. Pass context.TODO 27 | // if you are unsure about which Context to use. 28 | // 29 | // Use context Values only for request-scoped data that transits processes and 30 | // APIs, not for passing optional parameters to functions. 31 | // 32 | // The same Context may be passed to functions running in different goroutines; 33 | // Contexts are safe for simultaneous use by multiple goroutines. 34 | // 35 | // See http://blog.golang.org/context for example code for a server that uses 36 | // Contexts. 37 | // fork from golang.org/x/net/context 38 | // from https://github.com/golang/net 39 | package context // import "github.com/ossrs/go-oryx-lib/https/net/context" 40 | 41 | import "time" 42 | 43 | // A Context carries a deadline, a cancelation signal, and other values across 44 | // API boundaries. 45 | // 46 | // Context's methods may be called by multiple goroutines simultaneously. 47 | type Context interface { 48 | // Deadline returns the time when work done on behalf of this context 49 | // should be canceled. Deadline returns ok==false when no deadline is 50 | // set. Successive calls to Deadline return the same results. 51 | Deadline() (deadline time.Time, ok bool) 52 | 53 | // Done returns a channel that's closed when work done on behalf of this 54 | // context should be canceled. Done may return nil if this context can 55 | // never be canceled. Successive calls to Done return the same value. 56 | // 57 | // WithCancel arranges for Done to be closed when cancel is called; 58 | // WithDeadline arranges for Done to be closed when the deadline 59 | // expires; WithTimeout arranges for Done to be closed when the timeout 60 | // elapses. 61 | // 62 | // Done is provided for use in select statements: 63 | // 64 | // // Stream generates values with DoSomething and sends them to out 65 | // // until DoSomething returns an error or ctx.Done is closed. 66 | // func Stream(ctx context.Context, out chan<- Value) error { 67 | // for { 68 | // v, err := DoSomething(ctx) 69 | // if err != nil { 70 | // return err 71 | // } 72 | // select { 73 | // case <-ctx.Done(): 74 | // return ctx.Err() 75 | // case out <- v: 76 | // } 77 | // } 78 | // } 79 | // 80 | // See http://blog.golang.org/pipelines for more examples of how to use 81 | // a Done channel for cancelation. 82 | Done() <-chan struct{} 83 | 84 | // Err returns a non-nil error value after Done is closed. Err returns 85 | // Canceled if the context was canceled or DeadlineExceeded if the 86 | // context's deadline passed. No other values for Err are defined. 87 | // After Done is closed, successive calls to Err return the same value. 88 | Err() error 89 | 90 | // Value returns the value associated with this context for key, or nil 91 | // if no value is associated with key. Successive calls to Value with 92 | // the same key returns the same result. 93 | // 94 | // Use context values only for request-scoped data that transits 95 | // processes and API boundaries, not for passing optional parameters to 96 | // functions. 97 | // 98 | // A key identifies a specific value in a Context. Functions that wish 99 | // to store values in Context typically allocate a key in a global 100 | // variable then use that key as the argument to context.WithValue and 101 | // Context.Value. A key can be any type that supports equality; 102 | // packages should define keys as an unexported type to avoid 103 | // collisions. 104 | // 105 | // Packages that define a Context key should provide type-safe accessors 106 | // for the values stores using that key: 107 | // 108 | // // Package user defines a User type that's stored in Contexts. 109 | // package user 110 | // 111 | // import "golang.org/x/net/context" 112 | // 113 | // // User is the type of value stored in the Contexts. 114 | // type User struct {...} 115 | // 116 | // // key is an unexported type for keys defined in this package. 117 | // // This prevents collisions with keys defined in other packages. 118 | // type key int 119 | // 120 | // // userKey is the key for user.User values in Contexts. It is 121 | // // unexported; clients use user.NewContext and user.FromContext 122 | // // instead of using this key directly. 123 | // var userKey key = 0 124 | // 125 | // // NewContext returns a new Context that carries value u. 126 | // func NewContext(ctx context.Context, u *User) context.Context { 127 | // return context.WithValue(ctx, userKey, u) 128 | // } 129 | // 130 | // // FromContext returns the User value stored in ctx, if any. 131 | // func FromContext(ctx context.Context) (*User, bool) { 132 | // u, ok := ctx.Value(userKey).(*User) 133 | // return u, ok 134 | // } 135 | Value(key interface{}) interface{} 136 | } 137 | 138 | // Background returns a non-nil, empty Context. It is never canceled, has no 139 | // values, and has no deadline. It is typically used by the main function, 140 | // initialization, and tests, and as the top-level Context for incoming 141 | // requests. 142 | func Background() Context { 143 | return background 144 | } 145 | 146 | // TODO returns a non-nil, empty Context. Code should use context.TODO when 147 | // it's unclear which Context to use or it is not yet available (because the 148 | // surrounding function has not yet been extended to accept a Context 149 | // parameter). TODO is recognized by static analysis tools that determine 150 | // whether Contexts are propagated correctly in a program. 151 | func TODO() Context { 152 | return todo 153 | } 154 | 155 | // A CancelFunc tells an operation to abandon its work. 156 | // A CancelFunc does not wait for the work to stop. 157 | // After the first call, subsequent calls to a CancelFunc do nothing. 158 | type CancelFunc func() 159 | --------------------------------------------------------------------------------