Commit e54b956e authored by Andrei Mihu's avatar Andrei Mihu
Browse files

Extend available runtime hash functions. (#221)

parent cf8fd5c0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,7 +4,13 @@ All notable changes to this project are documented below.
The format is based on [keep a changelog](http://keepachangelog.com) and this project uses [semantic versioning](http://semver.org).

## [Unreleased]
### Added
- New `bit32` module available in the code runtime.
- New code runtime function to create MD5 hashes.
- New code runtime function to create SHA256 hashes.

### Changed
- Reduce the frequency of socket checks on known active connections.

## [2.0.2] - 2018-07-09
### Added
+5 −15
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ func main() {
	cookie := newOrLoadCookie(config)
	gacode := "UA-89792135-1"
	if gaenabled {
		runTelemetry(startupLogger, http.DefaultClient, gacode, cookie)
		runTelemetry(http.DefaultClient, gacode, cookie)
	}

	// Respect OS stop signals.
@@ -206,24 +206,14 @@ func dbConnect(multiLogger *zap.Logger, config server.Config) (*sql.DB, string)
//
// This information is sent via Google Analytics which allows the Nakama team to
// analyze usage patterns and errors in order to help improve the server.
func runTelemetry(startupLogger *zap.Logger, httpc *http.Client, gacode string, cookie string) {
	err := ga.SendSessionStart(httpc, gacode, cookie)
	if err != nil {
		startupLogger.Debug("Send start session event failed.", zap.Error(err))
func runTelemetry(httpc *http.Client, gacode string, cookie string) {
	if ga.SendSessionStart(httpc, gacode, cookie) != nil {
		return
	}

	err = ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "version", Ea: fmt.Sprintf("%s+%s", version, commitID)})
	if err != nil {
		startupLogger.Debug("Send event failed.", zap.Error(err))
		return
	}

	err = ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "variant", Ea: "nakama"})
	if err != nil {
		startupLogger.Debug("Send event failed.", zap.Error(err))
	if ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "version", Ea: fmt.Sprintf("%s+%s", version, commitID)}) != nil {
		return
	}
	ga.SendEvent(httpc, gacode, cookie, &ga.Event{Ec: "variant", Ea: "nakama"})
}

func newOrLoadCookie(config server.Config) string {
+31 −29
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ type SocketConfig struct {
	WriteWaitMs          int               `yaml:"write_wait_ms" json:"write_wait_ms" usage:"Time in milliseconds to wait for an ack from the client when writing data. Used for real-time connections."`
	PongWaitMs           int               `yaml:"pong_wait_ms" json:"pong_wait_ms" usage:"Time in milliseconds to wait between pong messages received from the client. Used for real-time connections."`
	PingPeriodMs         int               `yaml:"ping_period_ms" json:"ping_period_ms" usage:"Time in milliseconds to wait between sending ping messages to the client. This value must be less than the pong_wait_ms. Used for real-time connections."`
	PingBackoffThreshold int               `yaml:"ping_backoff_threshold" json:"ping_backoff_threshold" usage:"Minimum number of messages received from the client during a single ping period that will delay the sending of a ping until the next ping period, to avoid sending unnecessary pings on regularly active connections. Default 20."`
	OutgoingQueueSize    int               `yaml:"outgoing_queue_size" json:"outgoing_queue_size" usage:"The maximum number of messages waiting to be sent to the client. If this is exceeded the client is considered too slow and will disconnect. Used when processing real-time connections."`
	SSLCertificate       string            `yaml:"ssl_certificate" json:"ssl_certificate" usage:"Path to certificate file if you want the server to use SSL directly. Must also supply ssl_private_key. NOT recommended for production use."`
	SSLPrivateKey        string            `yaml:"ssl_private_key" json:"ssl_private_key" usage:"Path to private key file if you want the server to use SSL directly. Must also supply ssl_certificate. NOT recommended for production use."`
@@ -348,6 +349,7 @@ func NewSocketConfig() *SocketConfig {
		WriteWaitMs:          5000,
		PongWaitMs:           10000,
		PingPeriodMs:         8000,
		PingBackoffThreshold: 20,
		OutgoingQueueSize:    64,
		SSLCertificate:       "",
		SSLPrivateKey:        "",
+209 −0
Original line number Diff line number Diff line
// Copyright 2018 The Nakama Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"github.com/yuin/gopher-lua"
	"math"
	"math/bits"
)

var (
	Bit32LibName   = "bit32"
	Bit32Default64 = int64(math.Pow(2, 32) - 1)
)

func OpenBit32(l *lua.LState) int {
	mod := l.RegisterModule(Bit32LibName, bit32Funcs)
	l.Push(mod)
	return 1
}

var bit32Funcs = map[string]lua.LGFunction{
	"arshift": bit32arshift,
	"band":    bit32band,
	"bnot":    bit32not,
	"bor":     bit32or,
	"btest":   bit32btest,
	"bxor":    bit32xor,
	"extract": bit32extract,
	"replace": bit32replace,
	"lrotate": bit32lrotate,
	"lshift":  bit32lshift,
	"rrotate": bit32rrotate,
	"rshift":  bit32rshift,
}

func bit32arshift(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	n := l.CheckInt(2)
	if n < 0 {
		l.Push(lua.LNumber(a << uint32(n*-1)))
	} else if a>>uint32(31) != 0 {
		l.Push(lua.LNumber((a >> uint32(n)) | (uint32(math.Pow(2, float64(n))-1) << uint32(32-n))))
	} else {
		l.Push(lua.LNumber(a >> uint32(n)))
	}
	return 1
}

func bit32band(l *lua.LState) int {
	a := uint32(l.OptInt64(1, Bit32Default64))
	next := 2
	for {
		val := l.Get(next)
		if val == lua.LNil {
			break
		}
		if val.Type() != lua.LTNumber {
			l.TypeError(next, lua.LTNumber)
			return 0
		}
		b := val.(lua.LNumber)
		a = a & uint32(b)
		next++
	}
	l.Push(lua.LNumber(a))
	return 1
}

func bit32not(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	l.Push(lua.LNumber(^a))
	return 1
}

func bit32or(l *lua.LState) int {
	a := uint32(l.OptInt64(1, 0))
	next := 2
	for {
		val := l.Get(next)
		if val == lua.LNil {
			break
		}
		if val.Type() != lua.LTNumber {
			l.TypeError(next, lua.LTNumber)
			return 0
		}
		b := val.(lua.LNumber)
		a = a | uint32(b)
		next++
	}
	l.Push(lua.LNumber(a))
	return 1
}

func bit32btest(l *lua.LState) int {
	a := uint32(l.OptInt64(1, Bit32Default64))
	next := 2
	for {
		val := l.Get(next)
		if val == lua.LNil {
			break
		}
		if val.Type() != lua.LTNumber {
			l.TypeError(next, lua.LTNumber)
			return 0
		}
		b := val.(lua.LNumber)
		a = a & uint32(b)
		next++
	}
	l.Push(lua.LBool(a != 0))
	return 1
}

func bit32xor(l *lua.LState) int {
	a := uint32(l.OptInt64(1, 0))
	next := 2
	for {
		val := l.Get(next)
		if val == lua.LNil {
			break
		}
		if val.Type() != lua.LTNumber {
			l.TypeError(next, lua.LTNumber)
			return 0
		}
		b := val.(lua.LNumber)
		a = a ^ uint32(b)
		next++
	}
	l.Push(lua.LNumber(a))
	return 1
}

func bit32extract(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	offset := l.CheckInt(2)
	width := l.OptInt(3, 1)
	if offset < 0 || offset > 31 || width < 1 || width > 32 || (offset+width) > 32 {
		l.RaiseError("trying to access non-existent bits")
		return 0
	}
	l.Push(lua.LNumber((a >> uint32(offset)) & (1<<uint32(width) - 1)))
	return 1
}

func bit32replace(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	v := uint32(l.CheckInt64(2))
	offset := l.CheckInt(3)
	width := l.OptInt(4, 1)
	if offset < 0 || offset > 31 || width < 1 || width > 32 || (offset+width) > 32 {
		l.RaiseError("trying to access non-existent bits")
		return 0
	}
	a = a ^ (((a >> uint32(offset)) & (1<<uint32(width) - 1)) << uint32(offset))
	v = ((v << uint32(32-width)) >> uint32(32-width)) << uint32(offset)
	l.Push(lua.LNumber(a | v))
	return 1
}

func bit32lrotate(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	n := l.CheckInt(2)
	l.Push(lua.LNumber(bits.RotateLeft32(a, n)))
	return 1
}

func bit32lshift(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	n := l.CheckInt(2)
	if n < 0 {
		l.Push(lua.LNumber(a >> uint32(n*-1)))
	} else {
		l.Push(lua.LNumber(a << uint32(n)))
	}
	return 1
}

func bit32rrotate(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	n := l.CheckInt(2)
	l.Push(lua.LNumber(bits.RotateLeft32(a, n*-1)))
	return 1
}

func bit32rshift(l *lua.LState) int {
	a := uint32(l.CheckInt64(1))
	n := l.CheckInt(2)
	if n < 0 {
		l.Push(lua.LNumber(a << uint32(n*-1)))
	} else {
		l.Push(lua.LNumber(a >> uint32(n)))
	}
	return 1
}
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ func LoadRuntimeModules(startupLogger *zap.Logger, config Config) (map[string]lu
		lua.OsLibName:     OpenOs,
		lua.StringLibName: lua.OpenString,
		lua.MathLibName:   lua.OpenMath,
		Bit32LibName:      OpenBit32,
	}

	startupLogger.Info("Found runtime modules", zap.Int("count", len(modulePaths)), zap.Strings("modules", modulePaths))
Loading