init
This commit is contained in:
commit
e2d0b51a50
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.idea/
|
22
go.mod
Normal file
22
go.mod
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
module git.tcp.direct/kayos/fla5h
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
git.tcp.direct/kayos/common v0.8.3
|
||||||
|
github.com/fasthttp/websocket v1.5.2
|
||||||
|
github.com/icza/bitio v1.1.0
|
||||||
|
github.com/rs/zerolog v1.29.1
|
||||||
|
github.com/valyala/fasthttp v1.47.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.16.3 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
|
nullprogram.com/x/rng v1.1.0 // indirect
|
||||||
|
)
|
34
go.sum
Normal file
34
go.sum
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
git.tcp.direct/kayos/common v0.8.3 h1:W2iDrrQ7GN9cIuJTcAtmxnWIyBRtDrTsmgQzzuZMTM8=
|
||||||
|
git.tcp.direct/kayos/common v0.8.3/go.mod h1:7hOMiW1jK55PcvEuerOUKac3MjOAexaLYluYqFL+2Ws=
|
||||||
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/fasthttp/websocket v1.5.2 h1:KdCb0EpLpdJpfE3IPA5YLK/aYBO3dhZcvwxz6tXe2LQ=
|
||||||
|
github.com/fasthttp/websocket v1.5.2/go.mod h1:S0KC1VBlx1SaXGXq7yi1wKz4jMub58qEnHQG9oHuqBw=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0=
|
||||||
|
github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||||
|
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k=
|
||||||
|
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||||
|
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
||||||
|
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc=
|
||||||
|
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
|
||||||
|
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
nullprogram.com/x/rng v1.1.0 h1:SMU7DHaQSWtKJNTpNFIFt8Wd/KSmOuSDPXrMFp/UMro=
|
||||||
|
nullprogram.com/x/rng v1.1.0/go.mod h1:glGw6V87vyfawxCzqOABL3WfL95G65az9Z2JZCylCkg=
|
18
pkg/bitstream/bits.go
Normal file
18
pkg/bitstream/bits.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package bitstream
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/icza/bitio"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PackColorLossy(r, g, b int) byte {
|
||||||
|
sum := (r*7/255)<<5 + (g*7/255)<<2 + (b * 3 / 255)
|
||||||
|
return byte(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnpackColorLossy(packed byte) (r, g, b int) {
|
||||||
|
sum := int(packed)
|
||||||
|
r = sum >> 5 * 255 / 7
|
||||||
|
g = ((sum >> 2) & 0x07) * 255 / 7
|
||||||
|
b = sum & 3 * 255 / 3
|
||||||
|
return
|
||||||
|
}
|
57
pkg/bitstream/bits_test.go
Normal file
57
pkg/bitstream/bits_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package bitstream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/common/entropy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func randomRGB() (r, g, b int) {
|
||||||
|
r = entropy.RNG(255)
|
||||||
|
g = entropy.RNG(255)
|
||||||
|
b = entropy.RNG(255)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPackColorLossy(t *testing.T) {
|
||||||
|
r := 0
|
||||||
|
g := 204
|
||||||
|
b := 255
|
||||||
|
check(r, g, b, t)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
r, g, b = randomRGB()
|
||||||
|
check(r, g, b, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func check(r, g, b int, t *testing.T) {
|
||||||
|
t.Logf("Original: R:%d G:%d B:%d", r, g, b)
|
||||||
|
packed := PackColorLossy(r, g, b)
|
||||||
|
t.Logf("Packed: %d", packed)
|
||||||
|
|
||||||
|
rn, gn, bn := UnpackColorLossy(packed)
|
||||||
|
t.Logf("Unpacked: R:%d G:%d B:%d", rn, gn, bn)
|
||||||
|
comp := map[string]map[int]int{
|
||||||
|
"r": {r: rn},
|
||||||
|
"g": {g: gn},
|
||||||
|
"b": {b: bn},
|
||||||
|
}
|
||||||
|
totalDiff := 0
|
||||||
|
for k, v := range comp {
|
||||||
|
col := k
|
||||||
|
for in, out := range v {
|
||||||
|
var l, s = in, out
|
||||||
|
if in < out {
|
||||||
|
l = out
|
||||||
|
}
|
||||||
|
diff := l - s
|
||||||
|
totalDiff += diff
|
||||||
|
if diff > 85 {
|
||||||
|
t.Errorf("[%s] lossy beyond tolerace: %d -> %d", col, in, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalDiff > 150 {
|
||||||
|
t.Errorf("lossy beyond tolerace: %d", totalDiff)
|
||||||
|
}
|
||||||
|
t.Logf("TotalDiff: %d", totalDiff)
|
||||||
|
}
|
26
pkg/logger/console.go
Normal file
26
pkg/logger/console.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
var l *zerolog.Logger
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
cl := zerolog.NewConsoleWriter(
|
||||||
|
func(w *zerolog.ConsoleWriter) {
|
||||||
|
w.TimeFormat = time.RFC822
|
||||||
|
},
|
||||||
|
)
|
||||||
|
ll := zerolog.New(cl).With().Timestamp().Logger()
|
||||||
|
l = &ll
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get() *zerolog.Logger {
|
||||||
|
if l == nil {
|
||||||
|
setup()
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
16
pkg/pools/buffers.go
Normal file
16
pkg/pools/buffers.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package pools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/common/pool"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Strings = pool.NewStringFactory()
|
||||||
|
FastHTTPBuffers = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return make([]byte, 32*1024)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
1
pkg/resp/rgb.go
Normal file
1
pkg/resp/rgb.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package resp
|
65
pkg/ws/params.go
Normal file
65
pkg/ws/params.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package ws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/fla5h/pkg/pools"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SSLParams struct {
|
||||||
|
tlsConfig *tls.Config
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebsocketServerParams struct {
|
||||||
|
Addr string
|
||||||
|
Port string
|
||||||
|
SSLParams SSLParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsp *WebsocketServerParams) GetAddr() string {
|
||||||
|
s := pools.Strings.Get()
|
||||||
|
s.MustWriteString(wsp.Addr)
|
||||||
|
s.MustWriteString(":")
|
||||||
|
s.MustWriteString(wsp.Port)
|
||||||
|
addr := s.String()
|
||||||
|
pools.Strings.MustPut(s)
|
||||||
|
return addr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsp *WebsocketServerParams) GetTLSConfig() *tls.Config {
|
||||||
|
if !wsp.SSLParams.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return wsp.SSLParams.tlsConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebsocketServerParams(addr string, port int) *WebsocketServerParams {
|
||||||
|
return &WebsocketServerParams{
|
||||||
|
Addr: addr,
|
||||||
|
Port: strconv.Itoa(port),
|
||||||
|
SSLParams: SSLParams{Enabled: false},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebsocketServerParamsWithSSL(addr string, port int, cert, key []byte) *WebsocketServerParams {
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{
|
||||||
|
tls.Certificate{
|
||||||
|
Certificate: [][]byte{cert},
|
||||||
|
PrivateKey: key,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &WebsocketServerParams{
|
||||||
|
Addr: addr,
|
||||||
|
Port: strconv.Itoa(port),
|
||||||
|
SSLParams: SSLParams{
|
||||||
|
Enabled: true,
|
||||||
|
tlsConfig: tlsConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
72
pkg/ws/server.go
Normal file
72
pkg/ws/server.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package ws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fasthttp/websocket"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/fla5h/pkg/logger"
|
||||||
|
"git.tcp.direct/kayos/fla5h/pkg/pools"
|
||||||
|
)
|
||||||
|
|
||||||
|
var upgrader = websocket.FastHTTPUpgrader{
|
||||||
|
HandshakeTimeout: time.Duration(5) * time.Second,
|
||||||
|
WriteBufferPool: pools.FastHTTPBuffers,
|
||||||
|
Subprotocols: []string{"fla5h"},
|
||||||
|
EnableCompression: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Serve(params WebsocketServerParams) error {
|
||||||
|
srv := &fasthttp.Server{
|
||||||
|
Name: "fla5h/0.1",
|
||||||
|
ReadTimeout: time.Duration(5) * time.Second,
|
||||||
|
WriteTimeout: time.Duration(5) * time.Second,
|
||||||
|
IdleTimeout: time.Duration(55) * time.Second,
|
||||||
|
// NoDefaultDate: true,
|
||||||
|
// NoDefaultContentType: false,
|
||||||
|
KeepHijackedConns: true,
|
||||||
|
CloseOnShutdown: true,
|
||||||
|
StreamRequestBody: true,
|
||||||
|
Logger: logger.Get(),
|
||||||
|
TLSConfig: params.GetTLSConfig(),
|
||||||
|
}
|
||||||
|
srv.Handler = func(ctx *fasthttp.RequestCtx) {
|
||||||
|
if string(ctx.Path()) == "/ws" {
|
||||||
|
Upgrade(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return srv.ListenAndServe(params.GetAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Upgrade(ctx *fasthttp.RequestCtx) (*websocket.Conn, error) {
|
||||||
|
var wsConn *websocket.Conn
|
||||||
|
err := upgrader.Upgrade(ctx, func(wsc *websocket.Conn) {
|
||||||
|
wsConn = wsc
|
||||||
|
})
|
||||||
|
return wsConn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func closer(ioc io.Closer) {
|
||||||
|
if err := ioc.Close(); err != nil {
|
||||||
|
logger.Get().Error().Msgf("io.Closer error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func wsHandler(wsc *websocket.Conn) {
|
||||||
|
wb := func(dat []byte) {
|
||||||
|
if err := wsc.WriteMessage(websocket.BinaryMessage, dat); err != nil {
|
||||||
|
logger.Get().Error().Msgf("WriteMessage error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws := func(dat []byte) {
|
||||||
|
if err := wsc.WriteMessage(websocket.TextMessage, dat); err != nil {
|
||||||
|
logger.Get().Error().Msgf("WriteMessage error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer closer(wsc)
|
||||||
|
for {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user