This commit is contained in:
kayos@tcp.direct 2023-05-03 23:22:21 -07:00
commit e2d0b51a50
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
10 changed files with 312 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.idea/

22
go.mod Normal file
View 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
View 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
View 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
}

View 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
View 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
View 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
View File

@ -0,0 +1 @@
package resp

65
pkg/ws/params.go Normal file
View 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
View 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 {
}
}